summaryrefslogtreecommitdiffstats
path: root/kbabel
diff options
context:
space:
mode:
Diffstat (limited to 'kbabel')
-rw-r--r--kbabel/AUTHORS7
-rw-r--r--kbabel/COPYING340
-rw-r--r--kbabel/ChangeLog287
-rw-r--r--kbabel/Makefile.am8
-rw-r--r--kbabel/README65
-rw-r--r--kbabel/TODO22
-rw-r--r--kbabel/VERSION1
-rw-r--r--kbabel/addons/Makefile.am3
-rw-r--r--kbabel/addons/kfile-plugins/Makefile.am22
-rw-r--r--kbabel/addons/kfile-plugins/kfile_po.cpp81
-rw-r--r--kbabel/addons/kfile-plugins/kfile_po.desktop61
-rw-r--r--kbabel/addons/kfile-plugins/kfile_po.h49
-rw-r--r--kbabel/addons/preview/Makefile.am15
-rw-r--r--kbabel/addons/preview/pothumbcreator.cpp360
-rw-r--r--kbabel/addons/preview/pothumbcreator.h54
-rw-r--r--kbabel/addons/preview/pothumbnail.desktop68
-rw-r--r--kbabel/catalogmanager/Makefile.am64
-rw-r--r--kbabel/catalogmanager/catalogmanager.cpp1371
-rw-r--r--kbabel/catalogmanager/catalogmanager.desktop98
-rw-r--r--kbabel/catalogmanager/catalogmanager.h218
-rw-r--r--kbabel/catalogmanager/catalogmanagerapp.h73
-rw-r--r--kbabel/catalogmanager/catalogmanageriface.h67
-rw-r--r--kbabel/catalogmanager/catalogmanagerui.rc262
-rw-r--r--kbabel/catalogmanager/catalogmanagerview.cpp3132
-rw-r--r--kbabel/catalogmanager/catalogmanagerview.h474
-rw-r--r--kbabel/catalogmanager/catmanlistitem.cpp932
-rw-r--r--kbabel/catalogmanager/catmanlistitem.h238
-rw-r--r--kbabel/catalogmanager/catmanresource.h73
-rw-r--r--kbabel/catalogmanager/findinfilesdialog.cpp229
-rw-r--r--kbabel/catalogmanager/findinfilesdialog.h85
-rw-r--r--kbabel/catalogmanager/future.cpp17
-rw-r--r--kbabel/catalogmanager/hi16-app-catalogmanager.pngbin0 -> 865 bytes
-rw-r--r--kbabel/catalogmanager/hi22-app-catalogmanager.pngbin0 -> 1396 bytes
-rw-r--r--kbabel/catalogmanager/hi32-app-catalogmanager.pngbin0 -> 2446 bytes
-rw-r--r--kbabel/catalogmanager/hi48-app-catalogmanager.pngbin0 -> 4498 bytes
-rw-r--r--kbabel/catalogmanager/icons/Makefile.am5
-rw-r--r--kbabel/catalogmanager/icons/hi16-action-nextmarked.pngbin0 -> 329 bytes
-rw-r--r--kbabel/catalogmanager/icons/hi16-action-nextpo.pngbin0 -> 348 bytes
-rw-r--r--kbabel/catalogmanager/icons/hi16-action-nexttemplate.pngbin0 -> 354 bytes
-rw-r--r--kbabel/catalogmanager/icons/hi16-action-prevmarked.pngbin0 -> 341 bytes
-rw-r--r--kbabel/catalogmanager/icons/hi16-action-prevpo.pngbin0 -> 356 bytes
-rw-r--r--kbabel/catalogmanager/icons/hi16-action-prevtemplate.pngbin0 -> 363 bytes
-rw-r--r--kbabel/catalogmanager/icons/hi16-action-statistics.pngbin0 -> 702 bytes
-rw-r--r--kbabel/catalogmanager/icons/hi16-action-syntax.pngbin0 -> 623 bytes
-rw-r--r--kbabel/catalogmanager/icons/hi22-action-nextmarked.pngbin0 -> 566 bytes
-rw-r--r--kbabel/catalogmanager/icons/hi22-action-nextpo.pngbin0 -> 454 bytes
-rw-r--r--kbabel/catalogmanager/icons/hi22-action-nexttemplate.pngbin0 -> 447 bytes
-rw-r--r--kbabel/catalogmanager/icons/hi22-action-prevmarked.pngbin0 -> 560 bytes
-rw-r--r--kbabel/catalogmanager/icons/hi22-action-prevpo.pngbin0 -> 440 bytes
-rw-r--r--kbabel/catalogmanager/icons/hi22-action-prevtemplate.pngbin0 -> 436 bytes
-rw-r--r--kbabel/catalogmanager/icons/hi22-action-statistics.pngbin0 -> 1180 bytes
-rw-r--r--kbabel/catalogmanager/icons/hi22-action-syntax.pngbin0 -> 1378 bytes
-rw-r--r--kbabel/catalogmanager/icons/hi32-action-nextmarked.pngbin0 -> 706 bytes
-rw-r--r--kbabel/catalogmanager/icons/hi32-action-nextpo.pngbin0 -> 593 bytes
-rw-r--r--kbabel/catalogmanager/icons/hi32-action-nexttemplate.pngbin0 -> 568 bytes
-rw-r--r--kbabel/catalogmanager/icons/hi32-action-prevmarked.pngbin0 -> 726 bytes
-rw-r--r--kbabel/catalogmanager/icons/hi32-action-prevpo.pngbin0 -> 624 bytes
-rw-r--r--kbabel/catalogmanager/icons/hi32-action-prevtemplate.pngbin0 -> 627 bytes
-rw-r--r--kbabel/catalogmanager/icons/hi32-action-statistics.pngbin0 -> 1456 bytes
-rw-r--r--kbabel/catalogmanager/icons/hi32-action-syntax.pngbin0 -> 1332 bytes
-rw-r--r--kbabel/catalogmanager/icons/lo16-action-nextmarked.pngbin0 -> 315 bytes
-rw-r--r--kbabel/catalogmanager/icons/lo16-action-nextpo.pngbin0 -> 353 bytes
-rw-r--r--kbabel/catalogmanager/icons/lo16-action-nexttemplate.pngbin0 -> 325 bytes
-rw-r--r--kbabel/catalogmanager/icons/lo16-action-prevmarked.pngbin0 -> 319 bytes
-rw-r--r--kbabel/catalogmanager/icons/lo16-action-prevpo.pngbin0 -> 362 bytes
-rw-r--r--kbabel/catalogmanager/icons/lo16-action-prevtemplate.pngbin0 -> 340 bytes
-rw-r--r--kbabel/catalogmanager/icons/lo16-action-statistics.pngbin0 -> 362 bytes
-rw-r--r--kbabel/catalogmanager/icons/lo16-action-syntax.pngbin0 -> 311 bytes
-rw-r--r--kbabel/catalogmanager/icons/lo22-action-statistics.pngbin0 -> 420 bytes
-rw-r--r--kbabel/catalogmanager/icons/lo22-action-syntax.pngbin0 -> 402 bytes
-rw-r--r--kbabel/catalogmanager/icons/lo32-action-nextmarked.pngbin0 -> 582 bytes
-rw-r--r--kbabel/catalogmanager/icons/lo32-action-nextpo.pngbin0 -> 593 bytes
-rw-r--r--kbabel/catalogmanager/icons/lo32-action-nexttemplate.pngbin0 -> 568 bytes
-rw-r--r--kbabel/catalogmanager/icons/lo32-action-prevmarked.pngbin0 -> 502 bytes
-rw-r--r--kbabel/catalogmanager/icons/lo32-action-prevpo.pngbin0 -> 497 bytes
-rw-r--r--kbabel/catalogmanager/icons/lo32-action-prevtemplate.pngbin0 -> 484 bytes
-rw-r--r--kbabel/catalogmanager/icons/lo32-action-statistics.pngbin0 -> 471 bytes
-rw-r--r--kbabel/catalogmanager/icons/lo32-action-syntax.pngbin0 -> 497 bytes
-rw-r--r--kbabel/catalogmanager/libcvs/Makefile.am11
-rw-r--r--kbabel/catalogmanager/libcvs/cvsdialog.cpp423
-rw-r--r--kbabel/catalogmanager/libcvs/cvsdialog.h158
-rw-r--r--kbabel/catalogmanager/libcvs/cvshandler.cpp398
-rw-r--r--kbabel/catalogmanager/libcvs/cvshandler.h114
-rw-r--r--kbabel/catalogmanager/libcvs/cvsresources.h41
-rw-r--r--kbabel/catalogmanager/libsvn/Makefile.am11
-rw-r--r--kbabel/catalogmanager/libsvn/svndialog.cpp400
-rw-r--r--kbabel/catalogmanager/libsvn/svndialog.h151
-rw-r--r--kbabel/catalogmanager/libsvn/svnhandler.cpp544
-rw-r--r--kbabel/catalogmanager/libsvn/svnhandler.h138
-rw-r--r--kbabel/catalogmanager/libsvn/svnresources.h50
-rw-r--r--kbabel/catalogmanager/lo16-app-catalogmanager.pngbin0 -> 323 bytes
-rw-r--r--kbabel/catalogmanager/lo32-app-catalogmanager.pngbin0 -> 554 bytes
-rw-r--r--kbabel/catalogmanager/main.cpp232
-rw-r--r--kbabel/catalogmanager/markpatterndialog.cpp172
-rw-r--r--kbabel/catalogmanager/markpatterndialog.h75
-rw-r--r--kbabel/catalogmanager/markpatternwidget.ui127
-rw-r--r--kbabel/catalogmanager/multiroughtransdlg.cpp148
-rw-r--r--kbabel/catalogmanager/multiroughtransdlg.h63
-rw-r--r--kbabel/catalogmanager/validateprogress.cpp313
-rw-r--r--kbabel/catalogmanager/validateprogress.h109
-rw-r--r--kbabel/catalogmanager/validateprogresswidget.ui129
-rw-r--r--kbabel/catalogmanager/validateprogresswidget.ui.h48
-rw-r--r--kbabel/catalogmanager/validationoptions.ui60
-rw-r--r--kbabel/common/Makefile.am67
-rw-r--r--kbabel/common/argextractor.cpp70
-rw-r--r--kbabel/common/argextractor.h83
-rw-r--r--kbabel/common/catalog.cpp3509
-rw-r--r--kbabel/common/catalog.h698
-rw-r--r--kbabel/common/catalog_private.h147
-rw-r--r--kbabel/common/catalogfileplugin.h205
-rw-r--r--kbabel/common/catalogitem.cpp521
-rw-r--r--kbabel/common/catalogitem.h220
-rw-r--r--kbabel/common/catalogitem_private.h90
-rw-r--r--kbabel/common/catalogsettings.cpp258
-rw-r--r--kbabel/common/catalogsettings.h176
-rw-r--r--kbabel/common/catalogview.h64
-rw-r--r--kbabel/common/diff.cpp465
-rw-r--r--kbabel/common/diff.h88
-rw-r--r--kbabel/common/editcmd.cpp106
-rw-r--r--kbabel/common/editcmd.h112
-rw-r--r--kbabel/common/exportplugin.cpp81
-rw-r--r--kbabel/common/findoptions.h86
-rw-r--r--kbabel/common/importplugin.cpp194
-rw-r--r--kbabel/common/importplugin_private.h69
-rw-r--r--kbabel/common/itempart.h37
-rw-r--r--kbabel/common/kbabel-projectrename.upd13
-rw-r--r--kbabel/common/kbabeldatatool.h63
-rw-r--r--kbabel/common/kbabelfilter.desktop60
-rw-r--r--kbabel/common/kbmailer.cpp244
-rw-r--r--kbabel/common/kbmailer.h166
-rw-r--r--kbabel/common/kbproject.cpp477
-rw-r--r--kbabel/common/kbproject.h109
-rw-r--r--kbabel/common/kbprojectmanager.cpp101
-rw-r--r--kbabel/common/kbprojectmanager.h62
-rw-r--r--kbabel/common/kbprojectsettings.kcfg354
-rw-r--r--kbabel/common/kbprojectsettings.kcfgc7
-rw-r--r--kbabel/common/libgettext/Makefile.am15
-rw-r--r--kbabel/common/libgettext/pofiles.h52
-rw-r--r--kbabel/common/libgettext/pofiles.ll107
-rw-r--r--kbabel/common/libgettext/tokens.h45
-rw-r--r--kbabel/common/msgfmt.cpp147
-rw-r--r--kbabel/common/msgfmt.h65
-rw-r--r--kbabel/common/pluralforms.h38
-rw-r--r--kbabel/common/poinfo.cpp781
-rw-r--r--kbabel/common/poinfo.h157
-rw-r--r--kbabel/common/projectsettings.cpp126
-rw-r--r--kbabel/common/projectsettings.h142
-rw-r--r--kbabel/common/regexpextractor.cpp271
-rw-r--r--kbabel/common/regexpextractor.h158
-rw-r--r--kbabel/common/resources.h43
-rw-r--r--kbabel/common/stringdistance.cpp182
-rw-r--r--kbabel/common/stringdistance.h131
-rw-r--r--kbabel/common/tagextractor.cpp54
-rw-r--r--kbabel/common/tagextractor.h58
-rw-r--r--kbabel/commonui/Makefile.am40
-rw-r--r--kbabel/commonui/cmdedit.cpp298
-rw-r--r--kbabel/commonui/cmdedit.h94
-rw-r--r--kbabel/commonui/context.cpp305
-rw-r--r--kbabel/commonui/context.h123
-rw-r--r--kbabel/commonui/diffpreferences.ui141
-rw-r--r--kbabel/commonui/diffpreferences.ui.h13
-rw-r--r--kbabel/commonui/finddialog.cpp553
-rw-r--r--kbabel/commonui/finddialog.h136
-rw-r--r--kbabel/commonui/kactionselector.cpp562
-rw-r--r--kbabel/commonui/kactionselector.h410
-rw-r--r--kbabel/commonui/kbabel_tool.desktop9
-rw-r--r--kbabel/commonui/kbabel_validator.desktop56
-rw-r--r--kbabel/commonui/klisteditor.ui261
-rw-r--r--kbabel/commonui/klisteditor.ui.h122
-rw-r--r--kbabel/commonui/projectpref.cpp278
-rw-r--r--kbabel/commonui/projectpref.h93
-rw-r--r--kbabel/commonui/projectprefwidgets.cpp1209
-rw-r--r--kbabel/commonui/projectprefwidgets.h285
-rw-r--r--kbabel/commonui/projectwizard.cpp172
-rw-r--r--kbabel/commonui/projectwizard.h74
-rw-r--r--kbabel/commonui/projectwizardwidget.ui266
-rw-r--r--kbabel/commonui/projectwizardwidget.ui.h40
-rw-r--r--kbabel/commonui/projectwizardwidget2.ui157
-rw-r--r--kbabel/commonui/roughtransdlg.cpp762
-rw-r--r--kbabel/commonui/roughtransdlg.h110
-rw-r--r--kbabel/commonui/toolaction.cpp108
-rw-r--r--kbabel/commonui/toolaction.h72
-rw-r--r--kbabel/commonui/toolselectionwidget.cpp105
-rw-r--r--kbabel/commonui/toolselectionwidget.h57
-rw-r--r--kbabel/configure.in.in12
-rw-r--r--kbabel/datatools/Makefile.am39
-rw-r--r--kbabel/datatools/accelerators/Makefile.am19
-rw-r--r--kbabel/datatools/accelerators/kbabel_accelstool.desktop105
-rw-r--r--kbabel/datatools/accelerators/main.cc137
-rw-r--r--kbabel/datatools/accelerators/main.h56
-rw-r--r--kbabel/datatools/arguments/Makefile.am19
-rw-r--r--kbabel/datatools/arguments/kbabel_argstool.desktop106
-rw-r--r--kbabel/datatools/arguments/main.cc277
-rw-r--r--kbabel/datatools/arguments/main.h55
-rw-r--r--kbabel/datatools/context/Makefile.am19
-rw-r--r--kbabel/datatools/context/kbabel_contexttool.desktop100
-rw-r--r--kbabel/datatools/context/main.cc115
-rw-r--r--kbabel/datatools/context/main.h52
-rw-r--r--kbabel/datatools/equations/Makefile.am19
-rw-r--r--kbabel/datatools/equations/kbabel_equationstool.desktop104
-rw-r--r--kbabel/datatools/equations/main.cc113
-rw-r--r--kbabel/datatools/equations/main.h50
-rw-r--r--kbabel/datatools/length/Makefile.am19
-rw-r--r--kbabel/datatools/length/kbabel_lengthtool.desktop98
-rw-r--r--kbabel/datatools/length/main.cc142
-rw-r--r--kbabel/datatools/length/main.h54
-rw-r--r--kbabel/datatools/length/test.po46
-rw-r--r--kbabel/datatools/not-translated/Makefile.am19
-rw-r--r--kbabel/datatools/not-translated/kbabel_nottranslatedtool.desktop97
-rw-r--r--kbabel/datatools/not-translated/main.cc129
-rw-r--r--kbabel/datatools/not-translated/main.h55
-rw-r--r--kbabel/datatools/not-translated/test.po48
-rw-r--r--kbabel/datatools/pluralforms/Makefile.am19
-rw-r--r--kbabel/datatools/pluralforms/kbabel_pluralformstool.desktop101
-rw-r--r--kbabel/datatools/pluralforms/main.cc129
-rw-r--r--kbabel/datatools/pluralforms/main.h53
-rw-r--r--kbabel/datatools/punctuation/Makefile.am19
-rw-r--r--kbabel/datatools/punctuation/kbabel_punctuationtool.desktop101
-rw-r--r--kbabel/datatools/punctuation/main.cc157
-rw-r--r--kbabel/datatools/punctuation/main.h47
-rw-r--r--kbabel/datatools/regexp/Makefile.am21
-rw-r--r--kbabel/datatools/regexp/kbabel_regexptool.desktop92
-rw-r--r--kbabel/datatools/regexp/main.cc181
-rw-r--r--kbabel/datatools/regexp/main.h73
-rw-r--r--kbabel/datatools/regexp/regexplist.xml303
-rw-r--r--kbabel/datatools/setfuzzy/Makefile.am19
-rw-r--r--kbabel/datatools/setfuzzy/kbabel_setfuzzytool.desktop98
-rw-r--r--kbabel/datatools/setfuzzy/main.cc98
-rw-r--r--kbabel/datatools/setfuzzy/main.h47
-rw-r--r--kbabel/datatools/whitespace/Makefile.am19
-rw-r--r--kbabel/datatools/whitespace/kbabel_whitespacetool.desktop98
-rw-r--r--kbabel/datatools/whitespace/main.cc144
-rw-r--r--kbabel/datatools/whitespace/main.h55
-rw-r--r--kbabel/datatools/whitespace/test.po92
-rw-r--r--kbabel/datatools/xml/Makefile.am19
-rw-r--r--kbabel/datatools/xml/kbabel_xmltool.desktop105
-rw-r--r--kbabel/datatools/xml/main.cc206
-rw-r--r--kbabel/datatools/xml/main.h59
-rw-r--r--kbabel/filters/Makefile.am3
-rw-r--r--kbabel/filters/gettext/Makefile.am20
-rw-r--r--kbabel/filters/gettext/gettextexport.cpp352
-rw-r--r--kbabel/filters/gettext/gettextexport.h88
-rw-r--r--kbabel/filters/gettext/gettextimport.cpp821
-rw-r--r--kbabel/filters/gettext/gettextimport.h70
-rw-r--r--kbabel/filters/gettext/kbabel_gettext_export.desktop53
-rw-r--r--kbabel/filters/gettext/kbabel_gettext_import.desktop53
-rw-r--r--kbabel/filters/linguist/Makefile.am18
-rw-r--r--kbabel/filters/linguist/kbabel_linguist_export.desktop53
-rw-r--r--kbabel/filters/linguist/kbabel_linguist_import.desktop53
-rw-r--r--kbabel/filters/linguist/linguistexport.cpp214
-rw-r--r--kbabel/filters/linguist/linguistexport.h68
-rw-r--r--kbabel/filters/linguist/linguistimport.cpp193
-rw-r--r--kbabel/filters/linguist/linguistimport.h68
-rw-r--r--kbabel/filters/xliff/Makefile.am18
-rw-r--r--kbabel/filters/xliff/kbabel_xliff_export.desktop47
-rw-r--r--kbabel/filters/xliff/kbabel_xliff_import.desktop47
-rw-r--r--kbabel/filters/xliff/xliffexport.cpp223
-rw-r--r--kbabel/filters/xliff/xliffexport.h66
-rw-r--r--kbabel/filters/xliff/xliffimport.cpp180
-rw-r--r--kbabel/filters/xliff/xliffimport.h68
-rw-r--r--kbabel/kbabel/Makefile.am92
-rw-r--r--kbabel/kbabel/charselectview.cpp115
-rw-r--r--kbabel/kbabel/charselectview.h71
-rw-r--r--kbabel/kbabel/colorpreferences.ui188
-rw-r--r--kbabel/kbabel/commentview.cpp221
-rw-r--r--kbabel/kbabel/commentview.h96
-rw-r--r--kbabel/kbabel/contextview.cpp158
-rw-r--r--kbabel/kbabel/contextview.h56
-rw-r--r--kbabel/kbabel/editordiffpreferences.ui192
-rw-r--r--kbabel/kbabel/editorpreferences.ui353
-rw-r--r--kbabel/kbabel/editorpreferences.ui.h23
-rw-r--r--kbabel/kbabel/errorlistview.cpp76
-rw-r--r--kbabel/kbabel/errorlistview.h55
-rw-r--r--kbabel/kbabel/fontpreferences.ui63
-rw-r--r--kbabel/kbabel/fontpreferences.ui.h14
-rw-r--r--kbabel/kbabel/gotodialog.cpp74
-rw-r--r--kbabel/kbabel/gotodialog.h63
-rw-r--r--kbabel/kbabel/headereditor.cpp214
-rw-r--r--kbabel/kbabel/headereditor.h85
-rw-r--r--kbabel/kbabel/headerwidget.ui64
-rw-r--r--kbabel/kbabel/hi16-app-kbabel.pngbin0 -> 952 bytes
-rw-r--r--kbabel/kbabel/hi32-app-kbabel.pngbin0 -> 2561 bytes
-rw-r--r--kbabel/kbabel/hi48-app-kbabel.pngbin0 -> 4753 bytes
-rw-r--r--kbabel/kbabel/hidingmsgedit.cpp426
-rw-r--r--kbabel/kbabel/hidingmsgedit.h161
-rw-r--r--kbabel/kbabel/icons/Makefile.am5
-rw-r--r--kbabel/kbabel/icons/hi16-action-autodiff.pngbin0 -> 242 bytes
-rw-r--r--kbabel/kbabel/icons/hi16-action-catalogmanager.pngbin0 -> 791 bytes
-rw-r--r--kbabel/kbabel/icons/hi16-action-diff.pngbin0 -> 203 bytes
-rw-r--r--kbabel/kbabel/icons/hi16-action-insert_arg.pngbin0 -> 303 bytes
-rw-r--r--kbabel/kbabel/icons/hi16-action-insert_tag.pngbin0 -> 329 bytes
-rw-r--r--kbabel/kbabel/icons/hi16-action-msgid2msgstr.pngbin0 -> 298 bytes
-rw-r--r--kbabel/kbabel/icons/hi16-action-nexterror.pngbin0 -> 416 bytes
-rw-r--r--kbabel/kbabel/icons/hi16-action-nextfuzzy.pngbin0 -> 299 bytes
-rw-r--r--kbabel/kbabel/icons/hi16-action-nextfuzzyuntrans.pngbin0 -> 422 bytes
-rw-r--r--kbabel/kbabel/icons/hi16-action-nextuntranslated.pngbin0 -> 323 bytes
-rw-r--r--kbabel/kbabel/icons/hi16-action-preverror.pngbin0 -> 443 bytes
-rw-r--r--kbabel/kbabel/icons/hi16-action-prevfuzzy.pngbin0 -> 346 bytes
-rw-r--r--kbabel/kbabel/icons/hi16-action-prevfuzzyuntrans.pngbin0 -> 469 bytes
-rw-r--r--kbabel/kbabel/icons/hi16-action-prevuntranslated.pngbin0 -> 350 bytes
-rw-r--r--kbabel/kbabel/icons/hi16-action-search2msgstr.pngbin0 -> 374 bytes
-rw-r--r--kbabel/kbabel/icons/hi16-action-spellcheck_actual.pngbin0 -> 223 bytes
-rw-r--r--kbabel/kbabel/icons/hi16-action-spellcheck_all.pngbin0 -> 204 bytes
-rw-r--r--kbabel/kbabel/icons/hi16-action-spellcheck_from_cursor.pngbin0 -> 216 bytes
-rw-r--r--kbabel/kbabel/icons/hi16-action-spellcheck_selected.pngbin0 -> 214 bytes
-rw-r--r--kbabel/kbabel/icons/hi16-action-togglefuzzy.pngbin0 -> 316 bytes
-rw-r--r--kbabel/kbabel/icons/hi16-action-transsearch.pngbin0 -> 694 bytes
-rw-r--r--kbabel/kbabel/icons/hi22-action-autodiff.pngbin0 -> 314 bytes
-rw-r--r--kbabel/kbabel/icons/hi22-action-catalogmanager.pngbin0 -> 1540 bytes
-rw-r--r--kbabel/kbabel/icons/hi22-action-diff.pngbin0 -> 227 bytes
-rw-r--r--kbabel/kbabel/icons/hi22-action-insert_arg.pngbin0 -> 316 bytes
-rw-r--r--kbabel/kbabel/icons/hi22-action-insert_tag.pngbin0 -> 332 bytes
-rw-r--r--kbabel/kbabel/icons/hi22-action-msgid2msgstr.pngbin0 -> 277 bytes
-rw-r--r--kbabel/kbabel/icons/hi22-action-nexterror.pngbin0 -> 530 bytes
-rw-r--r--kbabel/kbabel/icons/hi22-action-nextfuzzy.pngbin0 -> 471 bytes
-rw-r--r--kbabel/kbabel/icons/hi22-action-nextfuzzyuntrans.pngbin0 -> 561 bytes
-rw-r--r--kbabel/kbabel/icons/hi22-action-nextuntranslated.pngbin0 -> 459 bytes
-rw-r--r--kbabel/kbabel/icons/hi22-action-preverror.pngbin0 -> 465 bytes
-rw-r--r--kbabel/kbabel/icons/hi22-action-prevfuzzy.pngbin0 -> 413 bytes
-rw-r--r--kbabel/kbabel/icons/hi22-action-prevfuzzyuntrans.pngbin0 -> 490 bytes
-rw-r--r--kbabel/kbabel/icons/hi22-action-prevuntranslated.pngbin0 -> 399 bytes
-rw-r--r--kbabel/kbabel/icons/hi22-action-search2msgstr.pngbin0 -> 338 bytes
-rw-r--r--kbabel/kbabel/icons/hi22-action-togglefuzzy.pngbin0 -> 386 bytes
-rw-r--r--kbabel/kbabel/icons/hi22-action-transsearch.pngbin0 -> 1357 bytes
-rw-r--r--kbabel/kbabel/icons/hi32-action-autodiff.pngbin0 -> 571 bytes
-rw-r--r--kbabel/kbabel/icons/hi32-action-catalogmanager.pngbin0 -> 2201 bytes
-rw-r--r--kbabel/kbabel/icons/hi32-action-diff.pngbin0 -> 296 bytes
-rw-r--r--kbabel/kbabel/icons/hi32-action-insert_arg.pngbin0 -> 537 bytes
-rw-r--r--kbabel/kbabel/icons/hi32-action-insert_tag.pngbin0 -> 602 bytes
-rw-r--r--kbabel/kbabel/icons/hi32-action-msgid2msgstr.pngbin0 -> 531 bytes
-rw-r--r--kbabel/kbabel/icons/hi32-action-nexterror.pngbin0 -> 836 bytes
-rw-r--r--kbabel/kbabel/icons/hi32-action-nextfuzzy.pngbin0 -> 597 bytes
-rw-r--r--kbabel/kbabel/icons/hi32-action-nextfuzzyuntrans.pngbin0 -> 720 bytes
-rw-r--r--kbabel/kbabel/icons/hi32-action-nextuntranslated.pngbin0 -> 583 bytes
-rw-r--r--kbabel/kbabel/icons/hi32-action-preverror.pngbin0 -> 1334 bytes
-rw-r--r--kbabel/kbabel/icons/hi32-action-prevfuzzy.pngbin0 -> 1012 bytes
-rw-r--r--kbabel/kbabel/icons/hi32-action-prevfuzzyuntrans.pngbin0 -> 1140 bytes
-rw-r--r--kbabel/kbabel/icons/hi32-action-prevuntranslated.pngbin0 -> 1000 bytes
-rw-r--r--kbabel/kbabel/icons/hi32-action-search2msgstr.pngbin0 -> 756 bytes
-rw-r--r--kbabel/kbabel/icons/hi32-action-togglefuzzy.pngbin0 -> 854 bytes
-rw-r--r--kbabel/kbabel/icons/hi32-action-transsearch.pngbin0 -> 1807 bytes
-rw-r--r--kbabel/kbabel/icons/lo16-action-autodiff.pngbin0 -> 361 bytes
-rw-r--r--kbabel/kbabel/icons/lo16-action-catalogmanager.pngbin0 -> 588 bytes
-rw-r--r--kbabel/kbabel/icons/lo16-action-diff.pngbin0 -> 349 bytes
-rw-r--r--kbabel/kbabel/icons/lo16-action-insert_arg.pngbin0 -> 341 bytes
-rw-r--r--kbabel/kbabel/icons/lo16-action-insert_tag.pngbin0 -> 358 bytes
-rw-r--r--kbabel/kbabel/icons/lo16-action-msgid2msgstr.pngbin0 -> 342 bytes
-rw-r--r--kbabel/kbabel/icons/lo16-action-nexterror.pngbin0 -> 390 bytes
-rw-r--r--kbabel/kbabel/icons/lo16-action-nextfuzzy.pngbin0 -> 363 bytes
-rw-r--r--kbabel/kbabel/icons/lo16-action-nextfuzzyuntrans.pngbin0 -> 373 bytes
-rw-r--r--kbabel/kbabel/icons/lo16-action-nextuntranslated.pngbin0 -> 360 bytes
-rw-r--r--kbabel/kbabel/icons/lo16-action-preverror.pngbin0 -> 393 bytes
-rw-r--r--kbabel/kbabel/icons/lo16-action-prevfuzzy.pngbin0 -> 366 bytes
-rw-r--r--kbabel/kbabel/icons/lo16-action-prevfuzzyuntrans.pngbin0 -> 377 bytes
-rw-r--r--kbabel/kbabel/icons/lo16-action-prevuntranslated.pngbin0 -> 363 bytes
-rw-r--r--kbabel/kbabel/icons/lo16-action-search2msgstr.pngbin0 -> 370 bytes
-rw-r--r--kbabel/kbabel/icons/lo16-action-spellcheck_actual.pngbin0 -> 223 bytes
-rw-r--r--kbabel/kbabel/icons/lo16-action-spellcheck_all.pngbin0 -> 204 bytes
-rw-r--r--kbabel/kbabel/icons/lo16-action-spellcheck_from_cursor.pngbin0 -> 216 bytes
-rw-r--r--kbabel/kbabel/icons/lo16-action-spellcheck_selected.pngbin0 -> 214 bytes
-rw-r--r--kbabel/kbabel/icons/lo16-action-togglefuzzy.pngbin0 -> 316 bytes
-rw-r--r--kbabel/kbabel/icons/lo16-action-transsearch.pngbin0 -> 435 bytes
-rw-r--r--kbabel/kbabel/icons/lo32-action-autodiff.pngbin0 -> 478 bytes
-rw-r--r--kbabel/kbabel/icons/lo32-action-catalogmanager.pngbin0 -> 828 bytes
-rw-r--r--kbabel/kbabel/icons/lo32-action-diff.pngbin0 -> 390 bytes
-rw-r--r--kbabel/kbabel/icons/lo32-action-insert_arg.pngbin0 -> 409 bytes
-rw-r--r--kbabel/kbabel/icons/lo32-action-insert_tag.pngbin0 -> 431 bytes
-rw-r--r--kbabel/kbabel/icons/lo32-action-msgid2msgstr.pngbin0 -> 403 bytes
-rw-r--r--kbabel/kbabel/icons/lo32-action-nexterror.pngbin0 -> 539 bytes
-rw-r--r--kbabel/kbabel/icons/lo32-action-nextfuzzy.pngbin0 -> 430 bytes
-rw-r--r--kbabel/kbabel/icons/lo32-action-nextfuzzyuntrans.pngbin0 -> 472 bytes
-rw-r--r--kbabel/kbabel/icons/lo32-action-nextuntranslated.pngbin0 -> 429 bytes
-rw-r--r--kbabel/kbabel/icons/lo32-action-preverror.pngbin0 -> 547 bytes
-rw-r--r--kbabel/kbabel/icons/lo32-action-prevfuzzy.pngbin0 -> 428 bytes
-rw-r--r--kbabel/kbabel/icons/lo32-action-prevfuzzyuntrans.pngbin0 -> 474 bytes
-rw-r--r--kbabel/kbabel/icons/lo32-action-prevuntranslated.pngbin0 -> 427 bytes
-rw-r--r--kbabel/kbabel/icons/lo32-action-search2msgstr.pngbin0 -> 478 bytes
-rw-r--r--kbabel/kbabel/icons/lo32-action-togglefuzzy.pngbin0 -> 854 bytes
-rw-r--r--kbabel/kbabel/icons/lo32-action-transsearch.pngbin0 -> 1267 bytes
-rw-r--r--kbabel/kbabel/kbabel-difftoproject.upd6
-rw-r--r--kbabel/kbabel/kbabel-project.upd11
-rw-r--r--kbabel/kbabel/kbabel.cpp1825
-rw-r--r--kbabel/kbabel/kbabel.desktop83
-rw-r--r--kbabel/kbabel/kbabel.h325
-rw-r--r--kbabel/kbabel/kbabel.kcfg304
-rw-r--r--kbabel/kbabel/kbabeliface.h81
-rw-r--r--kbabel/kbabel/kbabelpref.cpp198
-rw-r--r--kbabel/kbabel/kbabelpref.h69
-rw-r--r--kbabel/kbabel/kbabelsettings.kcfgc5
-rw-r--r--kbabel/kbabel/kbabelsplash.cpp73
-rw-r--r--kbabel/kbabel/kbabelsplash.h55
-rw-r--r--kbabel/kbabel/kbabelui.rc235
-rw-r--r--kbabel/kbabel/kbabelview.cpp4473
-rw-r--r--kbabel/kbabel/kbabelview.h712
-rw-r--r--kbabel/kbabel/kbabelview2.cpp1025
-rw-r--r--kbabel/kbabel/kbbookmarkhandler.cpp131
-rw-r--r--kbabel/kbabel/kbbookmarkhandler.h155
-rw-r--r--kbabel/kbabel/kbcatalog.cpp63
-rw-r--r--kbabel/kbabel/kbcatalog.h61
-rw-r--r--kbabel/kbabel/kbcataloglistview.cpp136
-rw-r--r--kbabel/kbabel/kbcataloglistview.h82
-rw-r--r--kbabel/kbabel/kbcataloglistviewitem.cpp213
-rw-r--r--kbabel/kbabel/kbcataloglistviewitem.h72
-rw-r--r--kbabel/kbabel/kbcatalogview.cpp137
-rw-r--r--kbabel/kbabel/kbcatalogview.h102
-rw-r--r--kbabel/kbabel/kbcharselect.cpp94
-rw-r--r--kbabel/kbabel/kbcharselect.h65
-rw-r--r--kbabel/kbabel/kbhighlighting.cpp316
-rw-r--r--kbabel/kbabel/kbhighlighting.h104
-rw-r--r--kbabel/kbabel/lo16-app-kbabel.pngbin0 -> 352 bytes
-rw-r--r--kbabel/kbabel/lo32-app-kbabel.pngbin0 -> 546 bytes
-rw-r--r--kbabel/kbabel/main.cpp612
-rw-r--r--kbabel/kbabel/mymultilineedit.cpp1668
-rw-r--r--kbabel/kbabel/mymultilineedit.h307
-rw-r--r--kbabel/kbabel/pics/Makefile.am6
-rw-r--r--kbabel/kbabel/pics/broken.pngbin0 -> 188 bytes
-rw-r--r--kbabel/kbabel/pics/missing.pngbin0 -> 215 bytes
-rw-r--r--kbabel/kbabel/pics/needwork.pngbin0 -> 189 bytes
-rw-r--r--kbabel/kbabel/pics/noflag.pngbin0 -> 159 bytes
-rw-r--r--kbabel/kbabel/pics/ok.pngbin0 -> 219 bytes
-rw-r--r--kbabel/kbabel/pics/pref_identity.pngbin0 -> 1369 bytes
-rw-r--r--kbabel/kbabel/pics/splash.pngbin0 -> 24019 bytes
-rw-r--r--kbabel/kbabel/searchpreferences.ui109
-rw-r--r--kbabel/kbabel/sourceview.cpp75
-rw-r--r--kbabel/kbabel/sourceview.h57
-rw-r--r--kbabel/kbabel/spelldlg.cpp142
-rw-r--r--kbabel/kbabel/spelldlg.h63
-rw-r--r--kbabel/kbabel/spelldlgwidget.ui126
-rw-r--r--kbabel/kbabel/taglistview.cpp78
-rw-r--r--kbabel/kbabel/taglistview.h61
-rw-r--r--kbabel/kbabeldict/Makefile.am66
-rw-r--r--kbabel/kbabeldict/README5
-rw-r--r--kbabel/kbabeldict/README.modules34
-rw-r--r--kbabel/kbabeldict/aboutmoduledlg.cpp54
-rw-r--r--kbabel/kbabeldict/aboutmoduledlg.h55
-rw-r--r--kbabel/kbabeldict/dictchooser.cpp335
-rw-r--r--kbabel/kbabeldict/dictchooser.h94
-rw-r--r--kbabel/kbabeldict/dictionarymenu.cpp154
-rw-r--r--kbabel/kbabeldict/dictionarymenu.h81
-rw-r--r--kbabel/kbabeldict/hi16-app-kbabeldict.pngbin0 -> 829 bytes
-rw-r--r--kbabel/kbabeldict/hi32-app-kbabeldict.pngbin0 -> 2278 bytes
-rw-r--r--kbabel/kbabeldict/hi48-app-kbabeldict.pngbin0 -> 4127 bytes
-rw-r--r--kbabel/kbabeldict/kbabeldict.cpp113
-rw-r--r--kbabel/kbabeldict/kbabeldict.desktop96
-rw-r--r--kbabel/kbabeldict/kbabeldict.h62
-rw-r--r--kbabel/kbabeldict/kbabeldict_module.desktop54
-rw-r--r--kbabel/kbabeldict/kbabeldictbox.cpp1767
-rw-r--r--kbabel/kbabeldict/kbabeldictbox.h282
-rw-r--r--kbabel/kbabeldict/kbabeldictiface.h56
-rw-r--r--kbabel/kbabeldict/kbabeldictview.cpp294
-rw-r--r--kbabel/kbabeldict/kbabeldictview.h92
-rw-r--r--kbabel/kbabeldict/kbabelsplash.cpp73
-rw-r--r--kbabel/kbabeldict/kbabelsplash.h55
-rw-r--r--kbabel/kbabeldict/lo16-app-kbabeldict.pngbin0 -> 293 bytes
-rw-r--r--kbabel/kbabeldict/lo32-app-kbabeldict.pngbin0 -> 497 bytes
-rw-r--r--kbabel/kbabeldict/main.cpp136
-rw-r--r--kbabel/kbabeldict/modules/Makefile.am7
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine/AUTHOR1
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine/KDBSearchEngine.cpp1899
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine/KDBSearchEngine.h333
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine/Makefile.am34
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine/STRUCTURE25
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine/TODO27
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine/configure.in.bot5
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine/configure.in.in143
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine/database.cpp1533
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine/database.h329
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine/dbscan.cpp197
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine/dbscan.h86
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine/dbse_factory.cpp82
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine/dbse_factory.h26
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine/dbsearchengine.desktop52
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine/dbseprefwidget.ui1036
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine/makemsgdb.C327
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine/preferenceswidget.cpp111
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine/preferenceswidget.h28
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine2/AUTHOR1
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine2/KDBSearchEngine2.cpp686
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine2/KDBSearchEngine2.h202
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine2/Makefile.am34
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine2/README21
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine2/algorithms.cpp425
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine2/algorithms.h157
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine2/chunk.cpp203
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine2/chunk.h151
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine2/database.cpp752
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine2/database.h237
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine2/dbentries.cpp171
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine2/dbentries.h170
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine2/dbscan.cpp280
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine2/dbscan.h120
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine2/dbse2.ui732
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine2/dbse2_factory.cpp83
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine2/dbse2_factory.h26
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine2/dbsearchengine2.desktop52
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine2/dbseprefwidget.ui1039
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine2/preferenceswidget.cpp98
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine2/preferenceswidget.h26
-rw-r--r--kbabel/kbabeldict/modules/dbsearchengine2/sourcedialog.ui266
-rw-r--r--kbabel/kbabeldict/modules/poauxiliary/Makefile.am36
-rw-r--r--kbabel/kbabeldict/modules/poauxiliary/pa_factory.cpp110
-rw-r--r--kbabel/kbabeldict/modules/poauxiliary/pa_factory.h60
-rw-r--r--kbabel/kbabeldict/modules/poauxiliary/poauxiliary.cpp554
-rw-r--r--kbabel/kbabeldict/modules/poauxiliary/poauxiliary.desktop51
-rw-r--r--kbabel/kbabeldict/modules/poauxiliary/poauxiliary.h136
-rw-r--r--kbabel/kbabeldict/modules/poauxiliary/preferenceswidget.cpp115
-rw-r--r--kbabel/kbabeldict/modules/poauxiliary/preferenceswidget.h77
-rw-r--r--kbabel/kbabeldict/modules/poauxiliary/pwidget.ui133
-rw-r--r--kbabel/kbabeldict/modules/pocompendium/Makefile.am39
-rw-r--r--kbabel/kbabeldict/modules/pocompendium/compendiumdata.cpp261
-rw-r--r--kbabel/kbabeldict/modules/pocompendium/compendiumdata.h105
-rw-r--r--kbabel/kbabeldict/modules/pocompendium/pc_factory.cpp110
-rw-r--r--kbabel/kbabeldict/modules/pocompendium/pc_factory.h60
-rw-r--r--kbabel/kbabeldict/modules/pocompendium/pocompendium.cpp1246
-rw-r--r--kbabel/kbabeldict/modules/pocompendium/pocompendium.desktop50
-rw-r--r--kbabel/kbabeldict/modules/pocompendium/pocompendium.h147
-rw-r--r--kbabel/kbabeldict/modules/pocompendium/preferenceswidget.cpp352
-rw-r--r--kbabel/kbabeldict/modules/pocompendium/preferenceswidget.h97
-rw-r--r--kbabel/kbabeldict/modules/pocompendium/pwidget.ui280
-rw-r--r--kbabel/kbabeldict/modules/tmx/Makefile.am34
-rw-r--r--kbabel/kbabeldict/modules/tmx/pc_factory.cpp111
-rw-r--r--kbabel/kbabeldict/modules/tmx/pc_factory.h62
-rw-r--r--kbabel/kbabeldict/modules/tmx/preferenceswidget.cpp334
-rw-r--r--kbabel/kbabeldict/modules/tmx/preferenceswidget.h97
-rw-r--r--kbabel/kbabeldict/modules/tmx/pwidget.ui216
-rw-r--r--kbabel/kbabeldict/modules/tmx/tmxcompendium.cpp1007
-rw-r--r--kbabel/kbabeldict/modules/tmx/tmxcompendium.desktop50
-rw-r--r--kbabel/kbabeldict/modules/tmx/tmxcompendium.h137
-rw-r--r--kbabel/kbabeldict/modules/tmx/tmxcompendiumdata.cpp308
-rw-r--r--kbabel/kbabeldict/modules/tmx/tmxcompendiumdata.h106
-rw-r--r--kbabel/kbabeldict/searchengine.cpp283
-rw-r--r--kbabel/kbabeldict/searchengine.h534
532 files changed, 79265 insertions, 0 deletions
diff --git a/kbabel/AUTHORS b/kbabel/AUTHORS
new file mode 100644
index 00000000..3ce9a203
--- /dev/null
+++ b/kbabel/AUTHORS
@@ -0,0 +1,7 @@
+Matthias Kiefer <kiefer@kde.org>
+Stanislav Visnovsky <visnovsky@kde.org>
+Dwayne Bailey <dwayne@translate.org.za>
+Bram Schoenmakers <bramschoenmakers@kde.nl>
+Asgeir Frimannsson <asgeirf@redhat.com>
+Albert Cervera Areny <albertca@hotpop.com>
+
diff --git a/kbabel/COPYING b/kbabel/COPYING
new file mode 100644
index 00000000..3912109b
--- /dev/null
+++ b/kbabel/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/kbabel/ChangeLog b/kbabel/ChangeLog
new file mode 100644
index 00000000..c62d9c40
--- /dev/null
+++ b/kbabel/ChangeLog
@@ -0,0 +1,287 @@
+Changes 1.11.4 (KDE 3.5.4)
+ - Update reference to KBabel's web site (now http://kbabel.kde.org )
+
+Changes 1.11.2 (KDE 3.5.2)
+ - Improve loading of Gettext PO files, especially in the case of recoverable
+ or unrecoverable errors (bugs #117968, #120200, #121236).
+ - Make CVS/SVN dialogs of KBabel's catalog manager depend on projects.
+ - Improve sending PO file(s) as email.
+
+Changes 1.11.1 (KDE 3.5.1)
+- Avoid user-visible strings that need to be translated in two ways (bug #114151)
+- Fix and improve source references
+- Add a new variable @POFILEDIR@ for source references.
+ This is for allowing search paths starting at the directory of the PO file,
+ like what is needed for GNU projects: starting at the parent directory (bug #114041)
+- Allow backslashes in source references in the PO file (bug #116393)
+- Clicking the help button of KBabelDict calls the corresponding section in the KBabel documentation
+- Improved documentation (including bug #85885)
+
+Changes 1.11 (KDE 3.5):
+- Diff settings part of a project (Stanislav Visnovsky)
+- View for current list of errors (Albert Cervera Areny)
+- Datatool for generic regexp validation (Albert Cervera Areny)
+- Separated editor color settings to its own page (Stanislav Visnovsky)
+- Improve CVS support of catalog manager
+- Allow the user to select an encoding for CVS (bug #66605)
+- Add SVN support to catalog manager (bug #105805)
+- Support for Gettext context (keyword "msgctxt")
+- Improve Gettext plural support
+- Abort load of a PO file with CVS/SVN conflict markers in it (bug #108285)
+- Make optional the ; character before the "charset" of a Content-Type declaration in a PO file (bug #106733)
+- Make the catalog manager work with PO files having CR/LF line endings (bug #105399)
+- Fix remote saving of files (bug #106738)
+- Improve writing the header while saving a PO file (bugs #64413, #107782, #115275, #115276, #115295)
+
+Changes 1.10:
+- XLIFF support (Stanislav Visnovsky)
+- word count tool (Stanislav Visnovsky)
+- projects UI enhancements - recent projects, etc (Stanislav Visnovsky)
+- use KConfigXT for projects
+- Fixed bugs: #91989, #92537, #89710, #88293, #91900
+
+Changes 1.9:
+- project manager implemented (Stanislav Visnovsky)
+- support for cvs diff (Bram Schoenmakers)
+- support for detachable views (Stanislav Visnovsky)
+- it's possible to sort on marked items (Bram Schoenmakers)
+- only modified files get committed when doing cvs commit in a directory (Bram Schoenmakers)
+
+Changes 1.3:
+- Fixed bugs: #63603, #64413
+- allow to set "Plural-Forms" header (Stanislav Visnovsky)
+- dictionary plugin interface overhauled to include more information (e.g. plural forms, projects)
+ (Andrea Rizzi, Stanislav Visnovsky)
+- punctuation validation tool (Stanislav Visnovsky)
+
+Changes 1.2:
+- implemented rough translation using dictionary settings (Stanislav Visnovsky)
+- diff is shown correctly for word wrapped text (Stanislav Visnovsky)
+- GNU argument reordering is implemented, #48971 (Stanislav Visnovsky)
+- Fixed bugs: #62449, crash on open in a new window
+
+Changes 1.2beta3:
+- internal structures speedup (Stanislav Visnovsky)
+- do single word rough translation for all words, the last one was skipped (Stanislav Visnovsky)
+- when mailing files, store files relatively to the PO base dir (Marco Wegner)
+- word wrapping enabled, fix #53832 (elonen at iki.fi)
+- spellcheck from the current message to the end of file, wishlist #50937 (Marco Wegner)
+- mark/unmark files in catalog manager using wildcards, wishlist #48840 (Marco Wegner)
+- XML entities can contain dots (Stanislav Visnovsky)
+
+Changes 1.2beta2:
+- Next tag selection using Ctrl+/Ctrl-, wishlist #51641 (Stanislav Visnovsky)
+- Enable/disable columns in Catalog Manager, wishlist #52949 (Stanislav Visnovsky)
+- Dictionary modules can be temporarily reconfigured for rough translation (Stanislav Visnovsky)
+- On-the-fly spellchecking (Lukas Tinkl, Stanislav Visnovsky)
+- Validation errors in Catalog manager can be ignored for next validation (Stanislav Visnovsky)
+- Mark selection using regexps/wildcards (Marco Wegner)
+- Option to ignore %n in argument checks (Stanislav Visnovsky)
+- Diff mode to find difference against msgstr (Stanislav Visnovsky)
+- Better support for Translation Project robot, #57642 (Stanislav Visnovsky)
+- Fixed bugs: #53836, #58323, #57398
+
+Changes 1.2beta1:
+- GNU gettext plural forms (Stanislav Visnovsky)
+- Msgstr2plural - copy single text into a plural form (Stanislav Visnovsky)
+- Validation tools are plugins now - integration in Catalog Manager as well (Stanislav Visnovsky)
+- Non-breaking space is shown differently (Stanislav Visnovsky)
+- Import/export plugin framework to load/save files. (Stanislav Visnovsky)
+- Ported GNU gettext load/save to the new plugin framework (Stanislav Visnovsky)
+- It is not possible to edit raw header anymore (Stanislav Visnovsky)
+- Character selection tool (Stanislav Visnovsky)
+- CVS support in Catalog Manager (Marco Wegner)
+- KBabelDict module lookup using standard KDE KTrader
+- Autosave feature (Marco Wegner)
+- DataTool to check for translations with only whitespace (Dwayne Bailey)
+- DataTool for translations that are not translated (Dwayne Bailey)
+- DataTool to highlight translations that are too short or too long (Dwayne Bailey)
+
+Changes 1.1:
+- Bookmarks (c) Marco Wegner
+- Catalog Manager caching (c) Stefan Asserhall
+- Highlighting rewrite (c) Marco Wegner
+- Ressurection of Delete in Catalog Manager
+- Catalog Manager can toggle mark using mouse (click in the column)
+- Fix spellchecking for Maltese
+
+Changes 1.0:
+- Bug fixes
+- Mail files (both from KBabel and Catalog manager)
+
+Changes 1.0beta2:
+- Bug fixes
+- rough translation in catalog manager
+- Alt+123 feature to type a character by its code
+- perform all checks at once (KBabel)
+- KFile plugin (c) Marco Wegner <dubbleu@web.de>
+
+Changes 1.0beta1:
+- Bug fixes
+- Automatic update of PO header comment
+- Automatic update of Project-Id-Version
+- Possibility to specify localized translator name
+- Show source code
+- Args support similar to tags
+- Editing of tag regexps
+- Validation & highlighting of XML
+- Tag structure tool added
+- KDE specifics added to rough translation (e.g. only add a new translator in TRANSLATORS_...)
+- Mail PO-file
+- Save special (the settings can be changed for the particular save)
+- Concept of "package" visually introduced (used in source code tool, dictionaries, automatic updates of headers...)
+- Force update in Catalog Manager
+- Spellchecking in more files
+- Load/Save markings in Catalog Manager
+- Navigation bar in Catalog Manager
+
+Changes 0.9.6:
+- Stanislav Visnovsky is the new maintainer.
+- Port to KDE3/Qt3. This version cannot be compiled with older versions of the libraries.
+- Catalog Manager is standalone application now. This improves stability and performance.
+- Find/Replace in multiple files (Catalog Manager) + corresponding new functions in DCOP interface.
+- Fuzzy flag can be toggled now (not only unset)
+- Obsolete entries in PO files are not lost anymore
+- Timezone can be specified as offset (e.g. +0100)
+- Fixed validation of context info, equations
+- Fixed "slow KBabel" bug
+
+Changes 0.9.5:
+- Workaround for bug which caused a unfinite loop in dbsearchengine.
+
+Changes 0.9.4:
+- Check if requested charset exists, otherwise use locale encoding
+- Don't stop reading files when the encoding is faulty.
+
+Changes 0.9.3:
+- set charset for displaying characters according to the encoding
+ of the file.
+
+Changes 0.9.2:
+- rudimentary support for files with plural forms introduced by
+ gettext 0.10.36 was implemented.
+
+Changes 0.9.1:
+- added clever editing feature which makes editing more comfortable
+- some improvements in settings for the test of plural forms
+- quite a lot of spelling and grammar corrections in messages
+ (thanks to Malcolm Hunter)
+
+Changes 0.9:
+- added diff feature, which allows to diff with messages in the translation
+ database or in other po-files (thanks to Wolfram Diestel who implemented
+ the diff algorithm)
+- kbabel now prevents opening of the same file more than once
+- added possibility to open a file from a searchresult and directly
+ go to this msgid
+- added test for KDE specific plural forms in messages
+- added possibility to search in translations in KBabelDict modules
+- improved performance of file parser
+- small structure improvement in preferences dialog
+- new and improved toolbar icons and new icons for KBabel and KBabelDict
+- fixed storing of ignored words in spell check
+- some bug fixes
+
+Changes 0.8.1:
+- some bug fixes
+
+Changes 0.8:
+- A new plugin framework for dictionaries was implemented
+- Added a "rough translation" function, that uses the available dictionaries
+ for making suggestions for translations
+- Added support for tag handling
+- Support for wheelmice was added
+
+
+Changes 0.7.1:
+- A new options was added to allow saving files in the same encoding as they
+ were read in.
+- Copy now copies also from context view und searchresults.
+
+
+Changes 0.7:
+- A powerful spell checker was added
+- some smaller bugfixes
+
+Changes 0.6:
+- Added four methods for checking consistency of the messages:
+ - Check, that printf and Qt arguments are the same in msgid and msgstr
+ - Check, that keyboard accelerators exists in msgstr if there is one
+ in msgid
+ - Check, that context information for message (as used in KDE) is not
+ translated
+ - Check, that left side of a equation is the same in msgid and msgstr.
+ This is useful when editing KDE's desktop.po files
+- Some smaller improvements like adding keyboard shortcuts, etc.
+- Some bug fixes
+
+Changes 0.5.5:
+- Added another tool window for showing the context of an entry in the PO file
+
+Changes 0.5.4:
+- Catalogmanager now displays in icons, when files in a directory need
+ work. Also now the icons do not display missing templates, when no template
+ directory is given.
+- Major bugfix with the catalogmanager not updating files, when template
+ was deleted or added
+- Fixed the catalog manager crash, when no template directory was given.
+
+Changes 0.5.3:
+- added first version of documentation by Claudiu Costin
+- bugfixes and some cleanups
+
+Changes 0.5.2:
+- bugfixes
+
+Changes 0.5.1:
+- KBabel is now more liberate in parsing files.
+ Questionable entries are then accessible with go->next error
+- some bugfixes
+
+Changes 0.5:
+- undo/redo implemented
+- find & replace implemented
+- added function to copy msgid to msgstr
+- added function to copy searchresult to msgstr
+ (thanks to Hans Petter Bieker)
+- KBabel now uses the XML-GUI feature of KDE 2
+- many bug fixes and smaller enhancements
+- package now contains a little commandline tool "extractmsg" from Stephan Kulow
+ to extract translations from po-files
+
+Changes 0.4:
+- syntax highlighting
+- added several methods to see whitespace
+- configurable font for message editors
+- back and forward function
+- when saving, non existing directories are created
+- Catalog Manager now displays progress in reading file information
+- made led colors configurable
+- fixed bug with geometry managment in preferences dialog
+- some other bugfixes
+
+Changes 0.3.3:
+- configurable format of date and time in header
+- now using getExistingDirectory for choosing a directory
+- now using standard KDialogBase
+
+Changes 0.3.2:
+- made changes due to some api changes in kdelibs
+- partly fixed layout problem in the preferences dialog
+- fixed bug in commands editor for catalog manager
+
+Changes 0.3.1:
+- some bugfixes
+- added support for writing in utf8 and detecting used charet when reading
+
+Changes 0.3:
+- full featured catalog manager implemented
+- syntax checking with msgfmt implemented
+
+Changes 0.2:
+- searching in compendium and auxiliary implemented
+- some bugfixes
+- parsing of files rewritten
+- cleaner classes
+- added whatsthis help
+
diff --git a/kbabel/Makefile.am b/kbabel/Makefile.am
new file mode 100644
index 00000000..c38a56f3
--- /dev/null
+++ b/kbabel/Makefile.am
@@ -0,0 +1,8 @@
+AUTOMAKE_OPTIONS = foreign 1.4
+
+SUBDIRS = common filters datatools kbabeldict commonui catalogmanager kbabel addons
+
+messages: rc.cpp
+ $(EXTRACTRC) `find . -name \*.rc -o -name \*.ui` >> rc.cpp
+ $(XGETTEXT) `find . -name \*.cpp -o -name \*.cc` -o $(podir)/kbabel.pot
+
diff --git a/kbabel/README b/kbabel/README
new file mode 100644
index 00000000..34dc745f
--- /dev/null
+++ b/kbabel/README
@@ -0,0 +1,65 @@
+KBabel
+Matthias Kiefer <kiefer@kde.org>
+Stanislav Visnovsky <visnovsky@kde.org>
+----------------------------------------------------------------------
+
+KBabel is an advanced and easy to use editor for PO files.
+It is written using the KDE libs and gives the user an
+easy to use GUI.
+
+
+If you find a bug or if you have any comment or feature request,
+please send a mail to Stanislav Visnovsky <visnovsky@kde.org>.
+
+
+For always up-to-date information about KBabel have a look at its homepage at
+http://kbabel.kde.org
+The always newest version of KBabel can be found in module kdesdk in
+KDE's SVN.
+
+
+Requirements:
+- KDE 3.2/Qt 3.3 or higher
+- For the dictionary plugin "Translation database" you need
+ Berkeley DB IV. Have a look at http://www.sleepycat.com
+
+
+KBabel is published under the terms of the GNU GPL.
+See file "COPYING" for more details.
+
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+
+Credits:
+- Claudiu Costin for writing documentation and many bug reports
+ and useful feature requests
+- Thomas Diehl for many useful hints to the GUI design and the
+ behaviour of KBabel
+- Wolfram Diestel for fixing kspell and many useful hints.
+- Stephan Kulow for helping keeping KBabel in sync with
+ the frequently changing KDE api and for often giving me a helping hand.
+- Andrea Rizzi for writing the dictionary plugin for searching in a database
+- Stefan Asserhall for implementing tag highlighting and validation, catalog manager caching
+- SuSE GmbH for sponsoring the work of Matthias Kiefer on KBabel
+- Marco Wegner <dubbleu@web.de> for KFile plugin, bookmarks and bug fixes
+- Dwayne Bailey <dwayne@translate.org.za> some validation plugins
+- all the others who spent their time sending bug reports and feature requests.
+
+
+Have fun,
+ Matthias Kiefer
+
diff --git a/kbabel/TODO b/kbabel/TODO
new file mode 100644
index 00000000..b98e6d1e
--- /dev/null
+++ b/kbabel/TODO
@@ -0,0 +1,22 @@
+- Bugs, bugs, bugs...
+- Context menu handling for comment view
+
+KBabel:
+- non-modal search and replace dialog
+- ignore newlines in search and replace
+- spellchecking in original messages
+- offer help with broken po files
+- Integration of external dictionaries
+- Network transparency for source files
+- diff for plural forms support
+- use DCOPsignals for file update
+
+KBabelDict:
+- In Po-auxiliary: make it easier to search in different language files
+
+Catalog manager:
+- more file managment functions
+- support for different structure of file trees (template <-> po files)
+- support for different file types (docbook)
+- graphical statistics
+- rewrite reading to use QTimer instead (should improve stability)
diff --git a/kbabel/VERSION b/kbabel/VERSION
new file mode 100644
index 00000000..3d0e6231
--- /dev/null
+++ b/kbabel/VERSION
@@ -0,0 +1 @@
+1.11.4
diff --git a/kbabel/addons/Makefile.am b/kbabel/addons/Makefile.am
new file mode 100644
index 00000000..291996f0
--- /dev/null
+++ b/kbabel/addons/Makefile.am
@@ -0,0 +1,3 @@
+AUTOMAKE_OPTIONS = foreign 1.4
+
+SUBDIRS = preview kfile-plugins
diff --git a/kbabel/addons/kfile-plugins/Makefile.am b/kbabel/addons/kfile-plugins/Makefile.am
new file mode 100644
index 00000000..fab776e0
--- /dev/null
+++ b/kbabel/addons/kfile-plugins/Makefile.am
@@ -0,0 +1,22 @@
+## Makefile.am for po file meta info plugin
+
+# set the include path for X, qt and KDE
+INCLUDES = -I$(srcdir)/../../common/ $(all_includes)
+
+# these are the headers for the project
+noinst_HEADERS = kfile_po.h
+
+kde_module_LTLIBRARIES = kfile_po.la
+
+kfile_po_la_SOURCES = kfile_po.cpp
+kfile_po_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+kfile_po_la_LIBADD = ../../common/libkbabelcommon.la $(LIB_KIO)
+
+# let automoc handle all of the meta source files (moc)
+METASOURCES = AUTO
+
+messages: rc.cpp
+ $(XGETTEXT) kfile_po.cpp -o $(podir)/kfile_po.pot
+
+services_DATA = kfile_po.desktop
+servicesdir = $(kde_servicesdir)
diff --git a/kbabel/addons/kfile-plugins/kfile_po.cpp b/kbabel/addons/kfile-plugins/kfile_po.cpp
new file mode 100644
index 00000000..3b9b1a49
--- /dev/null
+++ b/kbabel/addons/kfile-plugins/kfile_po.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2002 Marco Wegner <mail@marcowegner.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 version 2.
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+ */
+
+
+#include "kfile_po.h"
+
+#include <qstringlist.h>
+
+#include "poinfo.h"
+#include <kgenericfactory.h>
+
+using namespace KBabel;
+
+typedef KGenericFactory<KPoPlugin> POFactory;
+K_EXPORT_COMPONENT_FACTORY(kfile_po, POFactory("kfile_po"))
+
+KPoPlugin::KPoPlugin(QObject *parent, const char *name,
+ const QStringList& args)
+ : KFilePlugin(parent, name, args)
+{
+ KFileMimeTypeInfo* info = addMimeTypeInfo("application/x-gettext");
+
+ KFileMimeTypeInfo::GroupInfo* group =
+ addGroupInfo(info, "CatalogInfo", i18n("Catalog Information"));
+
+ KFileMimeTypeInfo::ItemInfo* item;
+ item = addItemInfo(group, "Total", i18n("Total Messages"), QVariant::Int);
+ item = addItemInfo(group, "Fuzzy", i18n("Fuzzy Messages"), QVariant::Int);
+ item = addItemInfo(group, "Untranslated", i18n("Untranslated Messages"), QVariant::Int);
+ item = addItemInfo(group, "LastTranslator", i18n("Last Translator"), QVariant::String);
+ item = addItemInfo(group, "LanguageTeam", i18n("Language Team"), QVariant::String);
+ item = addItemInfo(group, "Revision", i18n("Revision"), QVariant::String);
+}
+
+bool KPoPlugin::readInfo(KFileMetaInfo& metaInfo, uint)
+{
+ PoInfo poInfo;
+ QStringList wordList;
+ ConversionStatus status = PoInfo::info(metaInfo.path(), poInfo, wordList, false, false, false);
+ if (status == OK) {
+ KFileMetaInfoGroup group = appendGroup(metaInfo, "CatalogInfo");
+
+ appendItem(group, "Total", poInfo.total);
+ appendItem(group, "Fuzzy", poInfo.fuzzy);
+ appendItem(group, "Untranslated", poInfo.untranslated);
+ appendItem(group, "LastTranslator", poInfo.lastTranslator);
+ appendItem(group, "LanguageTeam", poInfo.languageTeam);
+ appendItem(group, "Revision", poInfo.revision);
+
+ return true;
+ }
+ return false;
+}
+
+#include "kfile_po.moc"
diff --git a/kbabel/addons/kfile-plugins/kfile_po.desktop b/kbabel/addons/kfile-plugins/kfile_po.desktop
new file mode 100644
index 00000000..c1848a58
--- /dev/null
+++ b/kbabel/addons/kfile-plugins/kfile_po.desktop
@@ -0,0 +1,61 @@
+[Desktop Entry]
+Type=Service
+Name=Catalog Information
+Name[af]=Katalogus Informasie
+Name[bg]=Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° каталог
+Name[br]=Titouroù diwar-benn ar c'hatalog
+Name[bs]=Katalog informacije
+Name[ca]=Informació de catàleg
+Name[cs]=Informace o katalogu
+Name[cy]=Gwybodaeth Catalog
+Name[da]=Kataloginformation
+Name[de]=Katalog-Information
+Name[el]=ΠληÏοφοÏίες καταλόγου
+Name[en_GB]=Catalogue Information
+Name[eo]=Kataloginformoj
+Name[es]=Información de catálogo
+Name[et]=Kataloogi info
+Name[eu]=Katalogo informatizioa
+Name[fa]=اطلاعات Ùهرست
+Name[fi]=Käännöspaketin tiedot
+Name[fr]=Informations du catalogue
+Name[ga]=Eolas Catalóga
+Name[gl]=Información do Catálogo
+Name[he]=מידע קטלוג
+Name[hi]=केटलॉग जानकारी
+Name[hr]=Informacije o katalogu
+Name[hu]=Katalógusjellemzők
+Name[is]=Upplýsingar um þýðingaskrár
+Name[it]=Informazioni sul catalogo
+Name[ja]=カタログ情報
+Name[ka]=კáƒáƒ¢áƒáƒšáƒáƒ’ის ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ
+Name[kk]=Каталог мәліметі
+Name[lt]=Katalogo informacija
+Name[ms]=Maklumat Katalog
+Name[nb]=Kataloginformasjon
+Name[nds]=Katalooginformatschoon
+Name[ne]=विवरणिका सूचना
+Name[nl]=Catalogusinformatie
+Name[nn]=Kataloginformasjon
+Name[pa]=ਸੂਚੀ ਜਾਣਕਾਰੀ
+Name[pl]=Informacje o tłumaczeniu
+Name[pt]=Informações do Catálogo
+Name[pt_BR]=Informação do Catálogo
+Name[ru]=Ð¡Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð¾ файле Ñообщений
+Name[sk]=Informácie o katalógu
+Name[sl]=Informacije o katalogu
+Name[sr]=Информације о каталогу
+Name[sr@Latn]=Informacije o katalogu
+Name[sv]=Kataloginformation
+Name[ta]=விவரபà¯à®ªà®Ÿà¯à®Ÿà®¿ தகவலà¯
+Name[tg]=Маълумот дар бораи каталог
+Name[tr]=Katalog Bilgisi
+Name[uk]=Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ñƒ
+Name[xh]=Ulwazi Lwencwadi yemifanekiso
+Name[zh_CN]=目录信æ¯
+Name[zh_TW]=類別資訊
+ServiceTypes=KFilePlugin
+X-KDE-Library=kfile_po
+MimeType=application/x-gettext
+PreferredGroups=CatalogInfo
+PreferredItems=Total,Fuzzy,Untranslated,LastTranslator,LanguageTeam,Revision
diff --git a/kbabel/addons/kfile-plugins/kfile_po.h b/kbabel/addons/kfile-plugins/kfile_po.h
new file mode 100644
index 00000000..942a62dc
--- /dev/null
+++ b/kbabel/addons/kfile-plugins/kfile_po.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2002 Marco Wegner <mail@marcowegner.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 version 2.
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+ */
+
+
+#ifndef KFILE_PO_H
+#define KFILE_PO_H
+
+#include <kfilemetainfo.h>
+
+class QStringList;
+
+
+class KPoPlugin : public KFilePlugin
+{
+ Q_OBJECT
+
+ public:
+ KPoPlugin(QObject *parent, const char *name, const QStringList& args);
+ virtual bool readInfo(KFileMetaInfo& info, uint);
+};
+
+#endif // KFILE_PO_H
diff --git a/kbabel/addons/preview/Makefile.am b/kbabel/addons/preview/Makefile.am
new file mode 100644
index 00000000..28afdfbd
--- /dev/null
+++ b/kbabel/addons/preview/Makefile.am
@@ -0,0 +1,15 @@
+
+INCLUDES = -I$(srcdir)/../../common $(all_includes)
+METASOURCES = AUTO
+
+kde_module_LTLIBRARIES = pothumbnail.la
+
+pothumbnail_la_SOURCES = pothumbcreator.cpp
+pothumbnail_la_LIBADD = ../../common/libkbabelcommon.la
+pothumbnail_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+
+noinst_HEADERS = pothumbcreator.h
+
+services_DATA = pothumbnail.desktop
+servicesdir = $(kde_servicesdir)
+
diff --git a/kbabel/addons/preview/pothumbcreator.cpp b/kbabel/addons/preview/pothumbcreator.cpp
new file mode 100644
index 00000000..f067948a
--- /dev/null
+++ b/kbabel/addons/preview/pothumbcreator.cpp
@@ -0,0 +1,360 @@
+/*
+ This file is part of KBabel
+ Copyright (C) 2001 Matthias Kiefer <kiefer@kde.org>
+
+ Text painting code is based on the text file preview textthumbnail by
+ Copyright (C) 2000 Carsten Pfeiffer <pfeiffer@kde.org>
+ 2000 Malte Starostik <malte@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qimage.h>
+
+#include <kapplication.h>
+#include <kglobal.h>
+#include <kiconloader.h>
+#include <kstandarddirs.h>
+#include <kpixmapsplitter.h>
+
+#include "pothumbcreator.h"
+#include "poinfo.h"
+
+using namespace KBabel;
+
+extern "C"
+{
+ KDE_EXPORT ThumbCreator *new_creator()
+ {
+ return new PoThumbCreator;
+ }
+}
+
+PoThumbCreator::PoThumbCreator()
+ : m_splitter(0)
+{
+}
+
+PoThumbCreator::~PoThumbCreator()
+{
+ if(m_splitter)
+ delete m_splitter;
+}
+
+bool PoThumbCreator::create(const QString &path, int width, int height, QImage &img)
+{
+ if ( !m_splitter )
+ {
+ m_splitter = new KPixmapSplitter;
+ QString pixmap = locate( "data", "konqueror/pics/thumbnailfont_7x4.png" );
+ if ( !pixmap.isEmpty() )
+ {
+ m_splitter->setPixmap( QPixmap( pixmap ));
+ m_splitter->setItemSize( QSize( 4, 7 ));
+ }
+ }
+
+ bool ok = false;
+ PoInfo poInfo;
+ QStringList wordList;
+
+ // We do not call msgfmt, as a thumbnail must be created fast.
+ if( PoInfo::info( path, poInfo, wordList, false, true, false ) == OK )
+ {
+ ok = true;
+
+ QPixmap pix;
+ if (height * 3 > width * 4)
+ pix.resize(width, width * 4 / 3);
+ else
+ pix.resize(height * 3 / 4, height);
+
+ pix.fill( QColor( 245, 245, 245 ) ); // light-grey background
+
+
+
+ // one pixel for the rectangle, the rest. whitespace
+ int xBorder = 1 + pix.width()/16; // minimum x-border
+ int yBorder = 1 + pix.height()/16; // minimum y-border
+
+ int circle = 16*360;
+ int fuzzyAngle = poInfo.fuzzy*circle/poInfo.total;
+ int untransAngle = poInfo.untranslated*circle/poInfo.total;
+
+ int w = pix.width()-2*xBorder;
+ int h = pix.height()*2/3-2*yBorder;
+
+ int d = QMIN(w,h);
+ xBorder = (pix.width()-d)/2;
+ yBorder = (pix.height()*2/3-d)/2;
+
+ QPainter p(&pix);
+
+ if(fuzzyAngle>0)
+ {
+ p.setBrush(Qt::blue);
+
+ if(poInfo.total == poInfo.fuzzy)
+ {
+ p.drawEllipse(xBorder,yBorder,d,d);
+ }
+ else
+ {
+ p.drawPie(xBorder,yBorder, d, d, 0, -fuzzyAngle);
+ }
+ }
+
+ if(untransAngle>0)
+ {
+ p.setBrush(Qt::red);
+
+ if(poInfo.untranslated == poInfo.total)
+ {
+ p.drawEllipse(xBorder,yBorder,d,d);
+ }
+ else
+ {
+ p.drawPie(xBorder,yBorder, d, d, -fuzzyAngle, -untransAngle);
+ }
+ }
+
+ if(circle - fuzzyAngle - untransAngle>0)
+ {
+ p.setBrush(Qt::darkGreen);
+
+ if(poInfo.fuzzy==0 && poInfo.untranslated==0)
+ {
+ p.drawEllipse(xBorder,yBorder,d,d);
+ }
+ else
+ {
+ p.drawPie(xBorder,yBorder, d, d, -fuzzyAngle-untransAngle
+ , -(circle-fuzzyAngle-untransAngle) );
+ }
+ }
+
+ p.end();
+
+
+
+ QRect rect;
+
+ QSize chSize = m_splitter->itemSize(); // the size of one char
+ int xOffset = chSize.width();
+ int yOffset = chSize.height();
+
+ // one pixel for the rectangle, the rest. whitespace
+ xBorder = 1 + pix.width()/16; // minimum x-border
+ yBorder = 1 + pix.height()/16; // minimum y-border
+
+ // calculate a better border so that the text is centered
+ int canvasWidth = pix.width() - 2*xBorder;
+ int canvasHeight = pix.height()/3 - 2*yBorder;
+ int numCharsPerLine = (int) (canvasWidth / chSize.width());
+ int numLines = (int) (canvasHeight / chSize.height());
+
+ int rest = pix.width() - (numCharsPerLine * chSize.width());
+ xBorder = QMAX( xBorder, rest/2); // center horizontally
+ rest = pix.height()/3 - (numLines * chSize.height());
+ yBorder = QMAX( yBorder, rest/2); // center vertically
+ // end centering
+
+
+ QString text;
+
+ if(numCharsPerLine < 30)
+ {
+ if(!poInfo.revision.isEmpty())
+ text += poInfo.revision+'\n';
+ if(!poInfo.lastTranslator.isEmpty())
+ text += poInfo.lastTranslator+'\n';
+ if(!poInfo.languageTeam.isEmpty())
+ text += poInfo.languageTeam+'\n';
+ if(!poInfo.contentType.isEmpty())
+ text += poInfo.contentType+'\n';
+ if(!poInfo.creation.isEmpty())
+ text += poInfo.creation+'\n';
+ if(!poInfo.project.isEmpty())
+ text += poInfo.project+'\n';
+ if(!poInfo.mimeVersion.isEmpty())
+ text += "MIME-Version: "+poInfo.mimeVersion+'\n';
+ if(!poInfo.encoding.isEmpty())
+ text += poInfo.encoding+'\n';
+
+ int lines = text.contains('\n')+1;
+ if(lines < numLines)
+ {
+ text = poInfo.headerComment+'\n'+text;
+ if(!poInfo.others.isEmpty())
+ text += poInfo.others+'\n';
+ }
+
+ if(text.at(text.length()-1) == '\n')
+ text.truncate(text.length()-1);
+ }
+ else
+ {
+ if(!poInfo.headerComment.isEmpty())
+ text += poInfo.headerComment+'\n';
+ if(!poInfo.project.isEmpty())
+ text += "Project-Id-Version: "+poInfo.project+'\n';
+ if(!poInfo.creation.isEmpty())
+ text += "POT-Creation-Date: "+poInfo.creation+'\n';
+ if(!poInfo.revision.isEmpty())
+ text += "PO-Revision-Date: "+ poInfo.revision+'\n';
+ if(!poInfo.lastTranslator.isEmpty())
+ text += "Last-Translator: "+poInfo.lastTranslator+'\n';
+ if(!poInfo.languageTeam.isEmpty())
+ text += "Language-Team: "+poInfo.languageTeam+'\n';
+ if(!poInfo.contentType.isEmpty())
+ text += "Content-Type: "+poInfo.contentType+'\n';
+ if(!poInfo.mimeVersion.isEmpty())
+ text += "MIME-Version: "+poInfo.mimeVersion+'\n';
+ if(!poInfo.encoding.isEmpty())
+ text += "Content-Transfer-Encoding: "+poInfo.encoding+'\n';
+ if(!poInfo.others.isEmpty())
+ text += poInfo.others;
+
+
+ if(text.at(text.length()-1) == '\n')
+ text.truncate(text.length()-1);
+ }
+ /*
+ double p = ((double)(poInfo.total-poInfo.fuzzy-poInfo.untranslated))*100/poInfo.total;
+ text = locale->formatNumber(p,0)+'%';
+ */
+ // find the maximum string length to center the text
+ QStringList lineList=QStringList::split('\n',text);
+ uint max=0;
+ for( QStringList::Iterator it = lineList.begin(); it != lineList.end()
+ ; ++it )
+ {
+ if((*it).length() > max)
+ max = (*it).length();
+ }
+ rest = pix.width() - (max * chSize.width());
+ xBorder = QMAX( xBorder, rest/2); // center horizontally
+ rest = pix.height()/3 - (lineList.count() * chSize.height());
+ yBorder = QMAX( yBorder, rest/2); // center vertically
+
+ // where to paint the characters
+ int x = xBorder, y = pix.height()*2/3;
+ int posNewLine = pix.width() - (chSize.width() + xBorder);
+ int posLastLine = pix.height() - (chSize.height() + yBorder);
+ bool newLine = false;
+ Q_ASSERT( posNewLine > 0 );
+ const QPixmap *fontPixmap = &(m_splitter->pixmap());
+
+
+ for ( uint i = 0; i < text.length(); i++ )
+ {
+ if ( x > posNewLine || newLine ) // start a new line?
+ {
+ x = xBorder;
+ y += yOffset;
+
+ if ( y > posLastLine ) // more text than space
+ break;
+
+ // after starting a new line, we also jump to the next
+ // physical newline in the file if we don't come from one
+ if ( !newLine )
+ {
+ int pos = text.find( '\n', i );
+ if ( pos > (int) i )
+ i = pos +1;
+ }
+
+ newLine = false;
+ }
+
+ // check for newlines in the text (unix,dos)
+ QChar ch = text.at( i );
+ if ( ch == '\n' )
+ {
+ newLine = true;
+ continue;
+ }
+ else if ( ch == '\r' && text.at(i+1) == '\n' )
+ {
+ newLine = true;
+ i++; // skip the next character (\n) as well
+ continue;
+ }
+
+ rect = m_splitter->coordinates( ch );
+ if ( !rect.isEmpty() )
+ {
+ bitBlt( &pix, QPoint(x,y), fontPixmap, rect, Qt::CopyROP );
+ }
+
+ x += xOffset; // next character
+ }
+
+ // very very seldom a babelfish lives in po files and even
+ // in this seldom cases they are usually hidden ;-)
+ if(pix.width() > 40 && KApplication::random()%2000 == 0)
+ {
+ QPixmap kbabelPix;
+ if(pix.width() < 80)
+ {
+ kbabelPix = KGlobal::iconLoader()->loadIcon("kbabel"
+ ,KIcon::Small,16,KIcon::DefaultState,0,true);
+ }
+ else if(pix.width() < 150)
+ {
+ kbabelPix = KGlobal::iconLoader()->loadIcon("kbabel"
+ ,KIcon::Desktop,32,KIcon::DefaultState,0,true);
+ }
+ else
+ {
+ kbabelPix = KGlobal::iconLoader()->loadIcon("kbabel"
+ ,KIcon::Desktop,48,KIcon::DefaultState,0,true);
+ }
+
+ int x = pix.width()-kbabelPix.width()-4;
+ x = QMAX(x,0);
+ if(!kbabelPix.isNull())
+ {
+ bitBlt(&pix, QPoint(x,4), &kbabelPix, kbabelPix.rect()
+ , Qt::CopyROP);
+ }
+ }
+
+ img = pix.convertToImage();
+ }
+
+ return ok;
+}
+
+ThumbCreator::Flags PoThumbCreator::flags() const
+{
+ return (Flags)(DrawFrame);
+}
+
diff --git a/kbabel/addons/preview/pothumbcreator.h b/kbabel/addons/preview/pothumbcreator.h
new file mode 100644
index 00000000..401e9431
--- /dev/null
+++ b/kbabel/addons/preview/pothumbcreator.h
@@ -0,0 +1,54 @@
+/*
+ This file is part of KBabel
+ Copyright (C) 2001 Matthias Kiefer <kiefer@kde.org>
+
+ Text painting code is based on the text file preview textthumbnail by
+ Copyright (C) 2000 Carsten Pfeiffer <pfeiffer@kde.org>
+ 2000 Malte Starostik <malte@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+#ifndef POTHUMBCREATOR_H
+#define POTHUMBCREATOR_H
+
+#include <kio/thumbcreator.h>
+
+class KPixmapSplitter;
+
+class PoThumbCreator : public ThumbCreator
+{
+public:
+ PoThumbCreator();
+ virtual ~PoThumbCreator();
+ virtual bool create(const QString &path, int width, int height, QImage &img);
+ virtual Flags flags() const;
+
+private:
+ KPixmapSplitter *m_splitter;
+};
+
+#endif
diff --git a/kbabel/addons/preview/pothumbnail.desktop b/kbabel/addons/preview/pothumbnail.desktop
new file mode 100644
index 00000000..2c15345b
--- /dev/null
+++ b/kbabel/addons/preview/pothumbnail.desktop
@@ -0,0 +1,68 @@
+[Desktop Entry]
+Type=Service
+Name=Message Catalogs
+Name[af]=Boodskap Katalogusse
+Name[az]=İsmarış Kataloqu
+Name[bg]=Каталози ÑÑŠÑ ÑъобщениÑ
+Name[br]=Katalogoù c'hemennadoù
+Name[bs]=Katalozi poruka
+Name[ca]=Catàlegs de missatges
+Name[cs]=Katalogy zpráv
+Name[cy]=Catalogau Negesau
+Name[da]=Beskedkataloger
+Name[de]=Nachrichtenkataloge
+Name[el]=Κατάλογοι μηνυμάτων
+Name[en_GB]=Message Catalogues
+Name[eo]=MesaÄkatalogoj
+Name[es]=Catálogos de mensajes
+Name[et]=Tõlkefailide kataloogid
+Name[eu]=Katalogo mezuak
+Name[fa]=Ùهرست پیامها
+Name[fi]=Käännöspaketit
+Name[fr]=Catalogues de messages
+Name[ga]=Catalóg teachtaireachtaí
+Name[gl]=Catálogos de Mensaxes
+Name[he]=קטלוגי הודעות
+Name[hi]=संदेश केटलॉग
+Name[hr]=Katalog poruka
+Name[hu]=Üzenetkatalógusok
+Name[is]=Þýðingaskrár
+Name[it]=Cataloghi di messaggi
+Name[ja]=メッセージカタログ
+Name[ka]=შეტყáƒáƒ‘ინებáƒáƒ—რკáƒáƒ¢áƒáƒšáƒáƒ’ი
+Name[kk]=Gettext жазулар каталогы
+Name[lt]=Pranešimų katalogai
+Name[lv]=Ziņojumu Katalogs
+Name[ms]=Mesej Katalog
+Name[mt]=Katalgu ta' Messaġġi
+Name[nb]=Meldingskataloger
+Name[nds]=Narichtenkatalogen
+Name[ne]=सनà¥à¤¦à¥‡à¤¶ विवरणिका
+Name[nl]=Gettext-catalogus
+Name[nn]=Meldingskatalogar
+Name[pa]=ਸà©à¨¨à©‡à¨¹à¨¾ ਸੂਚੀ
+Name[pl]=Katalog napisów
+Name[pt]=Catálogos de Mensagens
+Name[pt_BR]=Catálogo de mensagens
+Name[ro]=Cataloage de mesaje
+Name[ru]=Ð¡Ð¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Gettext
+Name[sk]=Katalógy správ
+Name[sl]=Katalogi s sporoÄili
+Name[sr]=Каталози порука
+Name[sr@Latn]=Katalozi poruka
+Name[sv]=Meddelandekataloger
+Name[ta]=செயà¯à®¤à®¿ விவரபà¯à®ªà®Ÿà¯à®Ÿà®¿
+Name[tg]=Каталоги хабарҳо
+Name[th]=à¹à¸„ตตาล็อà¸à¸‚้อความ
+Name[tr]=Mesaj Katalogları
+Name[uk]=Каталоги повідомлень
+Name[ven]=Khathalogo dza mulaedza
+Name[vi]=Mục lục các thông điệp
+Name[xh]=Umyalezo wemifanekiso esencwadini
+Name[zh_CN]=消æ¯ç›®å½•
+Name[zh_TW]=訊æ¯é¡žåˆ¥
+Name[zu]=Umyalezo Wemifanekiso esencwadini
+ServiceTypes=ThumbCreator
+MimeTypes=application/x-gettext
+X-KDE-Library=pothumbnail
+CacheThumbnail=false
diff --git a/kbabel/catalogmanager/Makefile.am b/kbabel/catalogmanager/Makefile.am
new file mode 100644
index 00000000..2d8d1836
--- /dev/null
+++ b/kbabel/catalogmanager/Makefile.am
@@ -0,0 +1,64 @@
+## Makefile.am for KBabel catalogmanager
+
+# this has all of the subdirectories that make will recurse into. If
+# there are none, comment this out
+SUBDIRS = libcvs libsvn icons
+
+# this is the program that gets installed. Its name is used for all
+# of the other Makefile.am variables
+noinst_LTLIBRARIES = libcatalogmanager.la
+bin_PROGRAMS = catalogmanager
+
+# set the include path for X, qt and KDE. Let $(all_includes) be always last.
+INCLUDES = -I$(srcdir)/../common -I../common -I$(srcdir)/../kbabeldict \
+-I$(srcdir)/../commonui -I../commonui -I./libsvn -I./libcvs \
+-I$(srcdir)/libsvn -I$(srcdir)/libcvs $(all_includes)
+
+
+# which sources should be compiled for kbabel
+libcatalogmanager_la_SOURCES = catalogmanageriface.skel \
+ validationoptions.ui \
+ catalogmanagerview.cpp \
+ catalogmanager.cpp findinfilesdialog.cpp \
+ catmanlistitem.cpp multiroughtransdlg.cpp validateprogresswidget.ui \
+ validateprogress.cpp markpatternwidget.ui markpatterndialog.cpp
+
+
+libcatalogmanager_la_LIBADD = ../commonui/libkbabelcommonui.la \
+../kbabeldict/libkbabeldict.la ./libcvs/libcatalogmanagercvs.la \
+./libsvn/libcatalogmanagersvn.la $(LIB_KIO)
+libcatalogmanager_la_LDFLAGS = $(all_libraries) -no-undefined
+
+
+catalogmanager_SOURCES = main.cpp
+
+# the libraries to link against.
+catalogmanager_LDADD = libcatalogmanager.la
+catalogmanager_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+
+# these are the headers for your project
+noinst_HEADERS = catalogmanageriface.h catalogmanager.h \
+ catalogmanagerview.h catalogmanagerapp.h findinfilesdialog.h \
+ catmanlistitem.h catmanresource.h multiroughtransdlg.h
+
+# let automoc handle all of the meta source files (moc)
+METASOURCES = AUTO
+
+rcdir = $(kde_datadir)/catalogmanager
+rc_DATA = catalogmanagerui.rc
+
+
+api:
+ mkdir -p API && kdoc -d API -u $$PWD/API -p -lkdeui -lkdecore -lqt -ldcop $(noinst_HEADERS)
+
+distclean-local:
+ rm -r -f API
+
+KDE_ICON = AUTO
+
+# this is where the kdelnk file will go
+xdg_apps_DATA = catalogmanager.desktop
+
+catalogmanager.lo: ../common/version.h
+main.o: ../common/version.h
+
diff --git a/kbabel/catalogmanager/catalogmanager.cpp b/kbabel/catalogmanager/catalogmanager.cpp
new file mode 100644
index 00000000..6cbe964d
--- /dev/null
+++ b/kbabel/catalogmanager/catalogmanager.cpp
@@ -0,0 +1,1371 @@
+/*****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2001-2004 by Stanislav Visnovsky <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#include "catmanresource.h"
+#include "catalogmanager.h"
+#include "catalog.h"
+#include "catalogmanagerapp.h"
+#include "findinfilesdialog.h"
+#include "kbabeldictbox.h"
+#include "resources.h"
+#include "projectpref.h"
+#include "kbprojectmanager.h"
+#include "projectwizard.h"
+#include "msgfmt.h"
+#include "toolaction.h"
+
+#include <qlabel.h>
+#include <qpainter.h>
+
+#include <dcopclient.h>
+#include <kapplication.h>
+#include <kaction.h>
+#include <kcmenumngr.h>
+#include <kconfig.h>
+#include <kcursor.h>
+#include <kdatatool.h>
+#include <kdialogbase.h>
+//#include <kedittoolbar.h>
+#include <kfiledialog.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kpopupmenu.h>
+#include <kprogress.h>
+#include <kstdaccel.h>
+#include <kstdaction.h>
+#include <kstandarddirs.h>
+#include <kstatusbar.h>
+#include <ktoolbar.h>
+#include <kwin.h>
+
+#include <qfileinfo.h>
+#include <qdir.h>
+#include <qtimer.h>
+#include <qbitmap.h>
+#include <qwhatsthis.h>
+#include <qheader.h>
+#include <qdragobject.h>
+#include <qlayout.h>
+#include <qhbox.h>
+
+using namespace KBabel;
+
+WId CatalogManagerApp::_preferredWindow = 0;
+
+QStringList CatalogManager::_foundFilesList;
+QStringList CatalogManager::_toBeSearched;
+
+CatalogManager::CatalogManager(QString configFile )
+ :KMainWindow(0,0)
+{
+ if ( configFile.isEmpty() )
+ configFile = KBabel::ProjectManager::defaultProjectName();
+ _configFile = configFile;
+
+ init();
+ restoreSettings();
+ updateSettings();
+}
+
+CatalogManager::~CatalogManager()
+{
+ saveView();
+ saveSettings(_configFile);
+ delete config;
+}
+
+void CatalogManager::init()
+{
+ _foundToBeSent = 0;
+ _totalFound = 0;
+ _foundFilesList.clear();
+ _toBeSearched.clear();
+ _timerFind = new QTimer( this );
+ connect(_timerFind, SIGNAL( timeout() ), this, SLOT(findNextFile()) );
+ _searchStopped = false;
+
+ _prefDialog=0;
+ _findDialog=0;
+ _replaceDialog=0;
+
+ _project = KBabel::ProjectManager::open(_configFile);
+
+ if ( _project == NULL )
+ {
+ KMessageBox::error( this, i18n("Cannot open project file\n%1").arg(_configFile)
+ , i18n("Project File Error"));
+
+ _project = KBabel::ProjectManager::open(KBabel::ProjectManager::defaultProjectName());
+ }
+
+ connect( _project, SIGNAL (signalCatManSettingsChanged())
+ , this, SLOT (updateSettings()));
+
+ QWidget *view = new QWidget(this);
+ QVBoxLayout* layout= new QVBoxLayout(view);
+ layout->setMargin(0);
+ layout->setSpacing(KDialog::spacingHint());
+
+ _catalogManager=new CatalogManagerView(_project, view,"catalog manager");
+ layout->addWidget(_catalogManager);
+ layout->setStretchFactor(_catalogManager,1);
+
+ connect(this,SIGNAL(settingsChanged(KBabel::CatManSettings))
+ ,_catalogManager,SLOT(setSettings(KBabel::CatManSettings)));
+ connect(_catalogManager,SIGNAL(openFile(QString,QString))
+ ,this,SLOT(openFile(QString,QString)));
+ connect(_catalogManager,SIGNAL(openFileInNewWindow(QString,QString))
+ ,this,SLOT(openFileInNewWindow(QString,QString)));
+ connect(_catalogManager,SIGNAL(openTemplate(QString,QString,QString))
+ ,this,SLOT(openTemplate(QString,QString,QString)));
+ connect(_catalogManager,SIGNAL(openTemplateInNewWindow(QString,QString,QString))
+ ,this,SLOT(openTemplateInNewWindow(QString,QString,QString)));
+ connect(_catalogManager,SIGNAL(gotoFileEntry(QString,QString,int))
+ ,this,SLOT(openFile(QString,QString,int)));
+ connect(_catalogManager, SIGNAL(selectedChanged(uint)),
+ this, SLOT(selectedChanged(uint)));
+
+ KWin::setIcons(winId(),BarIcon("catalogmanager",32)
+ ,SmallIcon("catalogmanager"));
+
+ QHBoxLayout* hBoxL = new QHBoxLayout(layout);
+ _progressLabel = new QLabel(view);
+ hBoxL->addWidget(_progressLabel);
+ _progressBar=new KProgress(view);
+ hBoxL->addWidget(_progressBar);
+ hBoxL->setStretchFactor(_progressBar,1);
+
+ _progressLabel->hide();
+ _progressBar->hide();
+
+ connect(_catalogManager,SIGNAL(prepareProgressBar(QString,int))
+ , this, SLOT(prepareProgressBar(QString,int)));
+ connect(_catalogManager,SIGNAL(clearProgressBar())
+ , this, SLOT(clearProgressBar()));
+ connect(_catalogManager,SIGNAL(progress(int))
+ , _progressBar, SLOT(setProgress(int)));
+// connect(_catalogManager, SIGNAL(signalBuildTree(bool))
+// , this, SLOT(enableMenuForFiles(bool)));
+ connect(_catalogManager, SIGNAL(signalBuildTree(bool))
+ , this, SLOT(enableActions(bool)));
+ connect(this, SIGNAL(searchStopped())
+ , _catalogManager, SLOT(stopSearch()));
+ connect(_catalogManager, SIGNAL(prepareFindProgressBar(int))
+ , this, SLOT(prepareStatusProgressBar(int)));
+
+ setCentralWidget(view);
+ resize( 600,300);
+
+ setupStatusBar();
+ setupActions();
+
+
+ QPopupMenu* popup;
+ popup = (QPopupMenu*)(factory()->container("rmb_file", this));
+ if(popup)
+ {
+ _catalogManager->setRMBMenuFile(popup);
+ }
+ popup = (QPopupMenu*)(factory()->container("rmb_dir", this));
+ if(popup)
+ {
+ _catalogManager->setRMBMenuDir(popup);
+ }
+
+ connect(_catalogManager, SIGNAL(signalSearchedFile(int))
+ , _statusProgressBar, SLOT(advance(int)));
+
+ restoreView();
+}
+
+void CatalogManager::setupActions()
+{
+ KGlobal::iconLoader()->addAppDir("kbabel");
+
+ KAction *action;
+
+ // the file menu
+ action = new KAction( i18n("&Open"), CTRL+Key_O, _catalogManager,
+ SLOT(slotOpenFile()),actionCollection(), "open");
+ action->setEnabled(false);
+ action = new KAction(i18n("&Open Template"),Key_Space,_catalogManager,
+ SLOT(slotOpenTemplate()),actionCollection(), "open_template");
+ action->setEnabled(false);
+ action = new KAction(i18n("Open in &New Window"),CTRL+SHIFT+Key_O,_catalogManager,
+ SLOT(slotOpenFileInNewWindow()),actionCollection(), "open_new_window");
+ action->setEnabled(false);
+
+ action = KStdAction::quit(kapp, SLOT (closeAllWindows()), actionCollection());
+
+ actionMap["open_template"] = NEEDS_POT;
+
+ // the edit menu
+ action = new KAction( i18n("Fi&nd in Files..."), CTRL+Key_F, this,
+ SLOT(find()), actionCollection(), "find_in_files");
+ action->setEnabled(false);
+ action = new KAction( i18n("Re&place in Files..."), CTRL+Key_R, this,
+ SLOT(replace()), actionCollection(), "replace_in_files");
+ action->setEnabled(false);
+ action = new KAction( i18n("&Stop Searching"), "stop", Key_Escape, this,
+ SLOT(stopSearching()), actionCollection(), "stop_search");
+ action->setEnabled(false);
+ action = new KAction( i18n("&Reload"), "reload", KStdAccel::reload(), _catalogManager,
+ SLOT(updateCurrent()), actionCollection(), "reload");
+ action->setEnabled(false);
+
+ // the marking menu
+ action = new KAction( i18n("&Toggle Marking"), CTRL+Key_M, _catalogManager,
+ SLOT(toggleMark()), actionCollection(), "toggle_marking");
+ action->setEnabled(false);
+ action = new KAction( i18n("Remove Marking"), 0, _catalogManager,
+ SLOT(slotClearMarksInDir()), actionCollection(), "remove_marking");
+ action->setEnabled(false);
+ action = new KAction( i18n("Toggle All Markings"), 0, _catalogManager,
+ SLOT(toggleAllMarks()), actionCollection(), "toggle_all_marking");
+ action->setEnabled(false);
+ action = new KAction( i18n("Remove All Markings"), 0, _catalogManager,
+ SLOT(clearAllMarks()), actionCollection(), "remove_all_marking");
+ action->setEnabled(false);
+ action = new KAction( i18n("Mark Modified Files"), 0, _catalogManager,
+ SLOT(markModifiedFiles()), actionCollection(), "mark_modified_files");
+ // fixme to enabling this when loading is done using updateFinished() signal
+ action->setEnabled(true);
+ action = new KAction( i18n("&Load Markings..."), 0, _catalogManager,
+ SLOT(loadMarks()), actionCollection(), "load_marking");
+ action->setEnabled(false);
+ action = new KAction( i18n("&Save Markings..."), 0, _catalogManager,
+ SLOT(saveMarks()), actionCollection(), "save_marking");
+ action->setEnabled(false);
+ (void)new KAction(i18n("&Mark Files..."), 0, _catalogManager,
+ SLOT(slotMarkPattern()), actionCollection(), "mark_pattern");
+ (void)new KAction(i18n("&Unmark Files..."), 0, _catalogManager,
+ SLOT(slotUnmarkPattern()), actionCollection(), "unmark_pattern");
+
+ actionMap["remove_marking"] = NEEDS_MARK;
+ actionMap["remove_all_marking"] = NEEDS_MARK;
+ actionMap["mark_pattern"] = NEEDS_DIR;
+ actionMap["unmark_pattern"] = NEEDS_DIR | NEEDS_MARK;
+
+ // go menu
+ action = new KAction(i18n("Nex&t Untranslated"), "nextuntranslated", ALT+Key_Next,
+ _catalogManager, SLOT(gotoNextUntranslated()),actionCollection(), "go_next_untrans");
+ action->setEnabled(false);
+ action = new KAction(i18n("Prev&ious Untranslated"), "prevuntranslated", ALT+Key_Prior,
+ _catalogManager, SLOT(gotoPreviousUntranslated()),actionCollection(), "go_prev_untrans");
+ action->setEnabled(false);
+ action = new KAction(i18n("Ne&xt Fuzzy"), "nextfuzzy", CTRL+Key_Next,
+ _catalogManager, SLOT(gotoNextFuzzy()),actionCollection(), "go_next_fuzzy");
+ action->setEnabled(false);
+ action = new KAction(i18n("Pre&vious Fuzzy"), "prevfuzzy", CTRL+Key_Prior,
+ _catalogManager, SLOT(gotoPreviousFuzzy()),actionCollection(), "go_prev_fuzzy");
+ action->setEnabled(false);
+ action = new KAction(i18n("N&ext Fuzzy or Untranslated"), "nextfuzzyuntrans", CTRL+SHIFT+Key_Next,
+ _catalogManager, SLOT(gotoNextFuzzyOrUntranslated()),actionCollection(), "go_next_fuzzyUntr");
+ action->setEnabled(false);
+ action = new KAction(i18n("P&revious Fuzzy or Untranslated"), "prevfuzzyuntrans", CTRL+SHIFT+Key_Prior,
+ _catalogManager, SLOT(gotoPreviousFuzzyOrUntranslated()),actionCollection(), "go_prev_fuzzyUntr");
+ action->setEnabled(false);
+
+ action = new KAction(i18n("Next Err&or"), "nexterror", ALT+SHIFT+Key_Next,
+ _catalogManager, SLOT(gotoNextError()),actionCollection(), "go_next_error");
+ action->setEnabled(false);
+ action = new KAction(i18n("Previo&us Error"), "preverror", ALT+SHIFT+Key_Prior,
+ _catalogManager, SLOT(gotoPreviousError()),actionCollection(), "go_prev_error");
+ action->setEnabled(false);
+ action = new KAction(i18n("Next Te&mplate Only"), "nexttemplate", CTRL+Key_Down,
+ _catalogManager, SLOT(gotoNextTemplate()),actionCollection(), "go_next_template");
+ action->setEnabled(false);
+ action = new KAction(i18n("Previous Temp&late Only"), "prevtemplate", CTRL+Key_Up,
+ _catalogManager, SLOT(gotoPreviousTemplate()),actionCollection(), "go_prev_template");
+ action->setEnabled(false);
+ action = new KAction(i18n("Next Tran&slation Exists"), "nextpo", ALT+Key_Down,
+ _catalogManager, SLOT(gotoNextPo()),actionCollection(), "go_next_po");
+ action->setEnabled(false);
+ action = new KAction(i18n("Previous Transl&ation Exists"), "prevpo", ALT+Key_Up,
+ _catalogManager, SLOT(gotoPreviousPo()),actionCollection(), "go_prev_po");
+ action->setEnabled(false);
+
+ action = new KAction(i18n("Previous Marke&d"), "prevmarked", SHIFT+Key_Up,
+ _catalogManager, SLOT(gotoPreviousMarked()),actionCollection(), "go_prev_marked");
+ action->setEnabled(false);
+ action = new KAction(i18n("Next &Marked"), "nextmarked", SHIFT+Key_Down,
+ _catalogManager, SLOT(gotoNextMarked()),actionCollection(), "go_next_marked");
+ action->setEnabled(false);
+
+ // project menu
+ // the project menu
+ action = new KAction(i18n("&New..."), "filenew"
+ , this, SLOT(projectNew()),actionCollection()
+ ,"project_new");
+
+ action = new KAction(i18n("&Open..."), "fileopen"
+ , this, SLOT(projectOpen()),actionCollection()
+ ,"project_open");
+
+ action = new KAction(i18n("C&lose"), "fileclose"
+ , this, SLOT(projectClose()),actionCollection()
+ ,"project_close");
+
+ action->setEnabled (_project->filename() != KBabel::ProjectManager::defaultProjectName() );
+
+ action = new KAction(i18n("&Configure..."), "configure"
+ , this, SLOT(projectConfigure()),actionCollection()
+ ,"project_settings");
+
+ // tools menu
+ action = new KAction( i18n("&Statistics"), "statistics", CTRL+Key_S,
+ _catalogManager, SLOT(statistics()), actionCollection(), "statistics");
+ action->setEnabled(false);
+ action = new KAction( i18n("S&tatistics in Marked"), "statistics", CTRL+ALT+Key_S,
+ _catalogManager, SLOT(markedStatistics()), actionCollection(), "statistics_marked");
+ action->setEnabled(false);
+ action = new KAction( i18n("Check S&yntax"), "syntax", CTRL+Key_Y,
+ _catalogManager, SLOT(checkSyntax()), actionCollection(), "syntax");
+ action->setEnabled(false);
+ action = new KAction( i18n("S&pell Check"), "spellcheck", CTRL+Key_I,
+ this, SLOT(spellcheck()), actionCollection(), "spellcheck");
+ action->setEnabled(false);
+ action = new KAction( i18n("Spell Check in &Marked"), "spellcheck", CTRL+ALT+Key_I,
+ this, SLOT(markedSpellcheck()), actionCollection(), "spellcheck_marked");
+ action->setEnabled(false);
+ action = new KAction( i18n("&Rough Translation"), CTRL+Key_T,
+ _catalogManager, SLOT(roughTranslation()), actionCollection(), "rough_translation");
+ action->setEnabled(false);
+ action = new KAction( i18n("Rough Translation in M&arked"), CTRL+ALT+Key_T,
+ _catalogManager, SLOT(markedRoughTranslation()), actionCollection(), "rough_translation_marked");
+ action->setEnabled(false);
+ action = new KAction( i18n("Mai&l"), "mail_send", CTRL+Key_A,
+ _catalogManager, SLOT(mailFiles()), actionCollection(), "mail_file");
+ action->setEnabled(false);
+ action = new KAction( i18n("Mail Mar&ked"), "mail_send", CTRL+ALT+Key_A,
+ _catalogManager, SLOT(mailMarkedFiles()), actionCollection(), "mail_file_marked");
+ action->setEnabled(false);
+
+ action = new KAction( i18n("&Pack"), "tar", CTRL+Key_B,
+ _catalogManager, SLOT(packageFiles()), actionCollection(), "package_file");
+ action = new KAction( i18n("Pack &Marked"), "tar", CTRL+ALT+Key_B, _catalogManager, SLOT(packageMarkedFiles()), actionCollection(), "package_file_marked");
+ action->setEnabled(false);
+
+ actionMap["statistics_marked"] = NEEDS_DIR | NEEDS_MARK;
+ actionMap["syntax"] = NEEDS_PO;
+ actionMap["spellcheck"] = NEEDS_PO;
+ actionMap["spellcheck_marked"] = NEEDS_PO | NEEDS_MARK;
+ actionMap["rough_translation_marked"] = NEEDS_MARK;
+ actionMap["mail_file"] = NEEDS_PO;
+ actionMap["mail_file_marked"] = NEEDS_PO | NEEDS_MARK;
+ actionMap["package_file_marked"] = NEEDS_PO | NEEDS_MARK;
+
+ // dynamic tools
+ QValueList<KDataToolInfo> tools = ToolAction::validationTools();
+
+ QPtrList<KAction> actions = ToolAction::dataToolActionList(
+ tools, _catalogManager, SLOT(validateUsingTool( const KDataToolInfo &, const QString& ))
+ ,"validate", false, actionCollection() );
+
+ KActionMenu* m_menu = new KActionMenu(i18n("&Validation"), actionCollection(),
+ "dynamic_validation");
+
+ KAction*ac;
+
+ for(ac = actions.first(); ac ; ac = actions.next() )
+ {
+ m_menu->insert(ac);
+ }
+
+ actions = ToolAction::dataToolActionList(
+ tools, _catalogManager, SLOT(validateMarkedUsingTool( const KDataToolInfo &, const QString& ))
+ ,"validate", false, actionCollection(), "marked_" );
+ m_menu = new KActionMenu(i18n("V&alidation Marked"), actionCollection(),
+ "dynamic_validation_marked");
+
+ for( ac = actions.first(); ac ; ac = actions.next() )
+ {
+ m_menu->insert(ac);
+ }
+
+ actionMap["dynamic_validation"] = NEEDS_PO;
+ actionMap["dynamic_validation_marked"] = NEEDS_PO | NEEDS_MARK;
+
+ // CVS submenu
+ // Actions for PO files
+ (void)new KAction( i18n( "Update" ), "down", 0, _catalogManager,
+ SLOT( cvsUpdate( ) ), actionCollection( ), "cvs_update" );
+ (void)new KAction( i18n( "Update Marked" ), 0, _catalogManager,
+ SLOT( cvsUpdateMarked( ) ), actionCollection( ), "cvs_update_marked" );
+ (void)new KAction( i18n( "Commit" ), "up", 0, _catalogManager,
+ SLOT( cvsCommit( ) ), actionCollection( ), "cvs_commit" );
+ (void)new KAction( i18n( "Commit Marked" ), 0, _catalogManager,
+ SLOT( cvsCommitMarked( ) ), actionCollection( ), "cvs_commit_marked" );
+ (void)new KAction( i18n( "Status" ), 0, _catalogManager,
+ SLOT( cvsStatus( ) ), actionCollection( ), "cvs_status" );
+ (void)new KAction( i18n( "Status for Marked" ), 0, _catalogManager,
+ SLOT( cvsStatusMarked( ) ), actionCollection( ), "cvs_status_marked" );
+ (void)new KAction( i18n( "Show Diff" ), 0, _catalogManager,
+ SLOT( cvsDiff( ) ), actionCollection( ), "cvs_diff" );
+
+ // CVS
+ actionMap["cvs_update"] = NEEDS_PO | NEEDS_PO_CVS;
+ actionMap["cvs_update_marked"] = NEEDS_PO | NEEDS_PO_CVS | NEEDS_MARK;
+ actionMap["cvs_commit"] = NEEDS_PO | NEEDS_PO_CVS;
+ actionMap["cvs_commit_marked"] = NEEDS_PO | NEEDS_PO_CVS | NEEDS_MARK;
+ actionMap["cvs_status"] = NEEDS_PO | NEEDS_PO_CVS;
+ actionMap["cvs_status_marked"] = NEEDS_PO | NEEDS_PO_CVS | NEEDS_MARK;
+ actionMap["cvs_diff"] = NEEDS_PO | NEEDS_PO_CVS;
+
+ // SVN submenu
+ // Actions for PO files
+ (void)new KAction( i18n( "Update" ), "down", 0, _catalogManager,
+ SLOT( svnUpdate( ) ), actionCollection( ), "svn_update" );
+ (void)new KAction( i18n( "Update Marked" ), 0, _catalogManager,
+ SLOT( svnUpdateMarked( ) ), actionCollection( ), "svn_update_marked" );
+ (void)new KAction( i18n( "Commit" ), "up", 0, _catalogManager,
+ SLOT( svnCommit( ) ), actionCollection( ), "svn_commit" );
+ (void)new KAction( i18n( "Commit Marked" ), 0, _catalogManager,
+ SLOT( svnCommitMarked( ) ), actionCollection( ), "svn_commit_marked" );
+ (void)new KAction( i18n( "Status (Local)" ), 0, _catalogManager,
+ SLOT( svnStatusLocal() ), actionCollection( ), "svn_status_local" );
+ (void)new KAction( i18n( "Status (Local) for Marked" ), 0, _catalogManager,
+ SLOT( svnStatusLocalMarked() ), actionCollection( ), "svn_status_local_marked" );
+ (void)new KAction( i18n( "Status (Remote)" ), 0, _catalogManager,
+ SLOT( svnStatusRemote() ), actionCollection( ), "svn_status_remote" );
+ (void)new KAction( i18n( "Status (Remote) for Marked" ), 0, _catalogManager,
+ SLOT( svnStatusRemoteMarked() ), actionCollection( ), "svn_status_remote_marked" );
+ (void)new KAction( i18n( "Show Diff" ), 0, _catalogManager,
+ SLOT( svnDiff( ) ), actionCollection( ), "svn_diff" );
+ (void)new KAction( i18n( "Show Information" ), 0, _catalogManager,
+ SLOT( svnInfo() ), actionCollection( ), "svn_info" );
+ (void)new KAction( i18n( "Show Information for Marked" ), 0, _catalogManager,
+ SLOT( svnInfoMarked() ), actionCollection( ), "svn_info_marked" );
+
+ // SVN
+ actionMap["svn_update"] = NEEDS_PO | NEEDS_PO_SVN;
+ actionMap["svn_update_marked"] = NEEDS_PO | NEEDS_PO_SVN | NEEDS_MARK;
+ actionMap["svn_commit"] = NEEDS_PO | NEEDS_PO_SVN;
+ actionMap["svn_commit_marked"] = NEEDS_PO | NEEDS_PO_SVN | NEEDS_MARK;
+ actionMap["svn_status_local"] = NEEDS_PO | NEEDS_PO_SVN;
+ actionMap["svn_status_local_marked"] = NEEDS_PO | NEEDS_PO_SVN | NEEDS_MARK;
+ actionMap["svn_status_remote"] = NEEDS_PO | NEEDS_PO_SVN;
+ actionMap["svn_status_remote_marked"] = NEEDS_PO | NEEDS_PO_SVN | NEEDS_MARK;
+ actionMap["svn_diff"] = NEEDS_PO | NEEDS_PO_SVN;
+ actionMap["svn_info"] = NEEDS_PO | NEEDS_PO_SVN;
+ actionMap["svn_info_marked"] = NEEDS_PO | NEEDS_PO_SVN | NEEDS_MARK;
+
+ // CVS Actions for POT files
+ (void)new KAction( i18n( "Update Templates" ), 0, _catalogManager,
+ SLOT( cvsUpdateTemplate( ) ), actionCollection( ), "cvs_update_template" );
+ (void)new KAction( i18n( "Update Marked Templates" ), 0, _catalogManager,
+ SLOT( cvsUpdateMarkedTemplate( ) ), actionCollection( ), "cvs_update_marked_template" );
+ (void)new KAction( i18n( "Commit Templates" ), 0, _catalogManager,
+ SLOT( cvsCommitTemplate( ) ), actionCollection( ), "cvs_commit_template" );
+ (void)new KAction( i18n( "Commit Marked Templates" ), 0, _catalogManager,
+ SLOT( cvsCommitMarkedTemplate( ) ), actionCollection( ), "cvs_commit_marked_template" );
+
+ actionMap["cvs_update_template"] = NEEDS_POT | NEEDS_POT_CVS;
+ actionMap["cvs_update_marked_template"] = NEEDS_POT | NEEDS_POT_CVS | NEEDS_MARK;
+ actionMap["cvs_commit_template"] = NEEDS_POT | NEEDS_POT_CVS;
+ actionMap["cvs_commit_marked_template"] = NEEDS_POT | NEEDS_POT_CVS | NEEDS_MARK;
+
+ // SVN Actions for POT files
+ (void)new KAction( i18n( "Update Templates" ), 0, _catalogManager,
+ SLOT( svnUpdateTemplate( ) ), actionCollection( ), "svn_update_template" );
+ (void)new KAction( i18n( "Update Marked Templates" ), 0, _catalogManager,
+ SLOT( svnUpdateMarkedTemplate( ) ), actionCollection( ), "svn_update_marked_template" );
+ (void)new KAction( i18n( "Commit Templates" ), 0, _catalogManager,
+ SLOT( svnCommitTemplate( ) ), actionCollection( ), "svn_commit_template" );
+ (void)new KAction( i18n( "Commit Marked Templates" ), 0, _catalogManager,
+ SLOT( svnCommitMarkedTemplate( ) ), actionCollection( ), "svn_commit_marked_template" );
+
+ actionMap["svn_update_template"] = NEEDS_POT | NEEDS_POT_SVN;
+ actionMap["svn_update_marked_template"] = NEEDS_POT | NEEDS_POT_SVN | NEEDS_MARK;
+ actionMap["svn_commit_template"] = NEEDS_POT | NEEDS_POT_SVN;
+ actionMap["svn_commit_marked_template"] = NEEDS_POT | NEEDS_POT_SVN | NEEDS_MARK;
+
+ // settings menu
+ // FIXME: KStdAction::preferences(this, SLOT( optionsPreferences()), actionCollection());
+
+ createStandardStatusBarAction();
+
+ setStandardToolBarMenuEnabled ( true );
+
+ // commands menus
+ KActionMenu* actionMenu=new KActionMenu(i18n("Commands"), 0,
+ actionCollection(), "dir_commands");
+ _catalogManager->setDirCommandsMenu( actionMenu->popupMenu());
+
+ actionMenu=new KActionMenu(i18n("Commands"), 0,
+ actionCollection(), "file_commands");
+ _catalogManager->setFileCommandsMenu( actionMenu->popupMenu());
+
+ action = new KAction(i18n("&Delete"),Key_Delete,_catalogManager,SLOT(slotDeleteFile()),actionCollection(), "delete");
+ action->setEnabled(false);
+
+#if KDE_IS_VERSION( 3, 2, 90 )
+ setupGUI();
+#else
+ createGUI();
+#endif
+}
+
+void CatalogManager::setupStatusBar()
+{
+ _foundLabel = new QLabel( " ", statusBar());
+ statusBar()->addWidget(_foundLabel,0);
+
+ QHBox* progressBox = new QHBox(statusBar(), "progressBox" );
+ progressBox->setSpacing(2);
+ _statusProgressLabel = new QLabel( "", progressBox );
+ _statusProgressBar = new KProgress( progressBox, "progressBar");
+ _statusProgressBar->hide();
+
+ statusBar()->addWidget(progressBox,1);
+ statusBar()->setMinimumHeight(_statusProgressBar->sizeHint().height());
+
+ QWhatsThis::add(statusBar(),
+ i18n("<qt><p><b>Statusbar</b></p>\n"
+ "<p>The statusbar displays information about progress of"
+ " the current find or replace operation. The first number in <b>Found:</b>"
+ " displays the number of files with an occurrence of the searched text not"
+ " yet shown in the KBabel window. The second shows the total number of files"
+ " containing the searched text found so far.</p></qt>"));
+}
+
+void CatalogManager::enableMenuForFiles(bool enable)
+{
+ stateChanged( "treeBuilt", enable ? StateNoReverse: StateReverse );
+}
+
+void CatalogManager::selectedChanged(uint actionValue)
+{
+ QMap<QString,uint>::Iterator it;
+ for (it = actionMap.begin( ); it != actionMap.end( ); ++it) {
+ KAction * action = actionCollection()->action(it.key( ).latin1( ));
+ if (action) action->setEnabled((actionValue & it.data( )) == it.data( ));
+ }
+}
+
+CatManSettings CatalogManager::settings() const
+{
+ return _catalogManager->settings();
+}
+
+void CatalogManager::updateSettings()
+{
+ _settings = _project->catManSettings();
+ _catalogManager->setSettings(_settings);
+ _openNewWindow=_settings.openWindow;
+}
+
+void CatalogManager::saveSettings( QString configFile )
+{
+ _settings = _catalogManager->settings(); // restore settings from the view
+
+ _project->setSettings( _settings );
+
+ config = new KConfig(configFile);
+
+ _catalogManager->saveView(config);
+
+ config->sync();
+}
+
+void CatalogManager::restoreSettings()
+{
+ _settings = _project->catManSettings();
+ _openNewWindow=_settings.openWindow;
+ _catalogManager->restoreView(_project->config());
+}
+
+void CatalogManager::setPreferredWindow(WId window)
+{
+ _preferredWindow = window;
+ kdDebug(KBABEL_CATMAN) << "setPrefereedWindow set to :" << _preferredWindow << endl;
+}
+
+void CatalogManager::updateFile(QString fileWithPath)
+{
+ _catalogManager->updateFile(fileWithPath,true); //force update
+}
+
+void CatalogManager::updateAfterSave(QString fileWithPath, PoInfo &info)
+{
+ _catalogManager->updateAfterSave(fileWithPath, info);
+}
+
+CatalogManagerView *CatalogManager::view()
+{
+ return _catalogManager;
+}
+
+void CatalogManager::openFile(QString filename, QString package)
+{
+ DCOPClient * client = kapp->dcopClient();
+
+ if( startKBabel() )
+ {
+
+ QByteArray data;
+ QCString url = filename.local8Bit();
+ QDataStream arg(data, IO_WriteOnly);
+ arg << url;
+ arg << package.utf8();
+ arg << CatalogManagerApp::_preferredWindow;
+ arg << ( _openNewWindow ? 1 : 0 );
+
+ kdDebug(KBABEL_CATMAN) << "Open file with project " << _configFile << endl;
+
+ QCString callfunc="openURL(QCString, QCString, WId,int)";
+ if(_configFile != "kbabelrc" )
+ {
+ arg << _configFile.utf8();
+ callfunc="openURL(QCString, QCString, WId,int,QCString)";
+ }
+
+ kdDebug(KBABEL_CATMAN) << callfunc << endl;
+
+ // update the user timestamp for KBabel to get it a focus
+ kapp->updateRemoteUserTimestamp ("kbabel");
+
+ if( !client->send("kbabel","KBabelIFace", callfunc, data) )
+ KMessageBox::error(this, i18n("Cannot send a message to KBabel.\n"
+ "Please check your installation of KDE."));
+ }
+}
+
+void CatalogManager::openFile(QString filename, QString package, int msgid)
+{
+ DCOPClient * client = kapp->dcopClient();
+
+ if( startKBabel() )
+ {
+ QByteArray data;
+ QCString url = filename.local8Bit();
+ QDataStream arg(data, IO_WriteOnly);
+ arg << url;
+ arg << package.utf8();
+ arg << msgid;
+
+ kdDebug(KBABEL_CATMAN) << "Open file with project " << _configFile << endl;
+
+ QCString callfunc="gotoFileEntry(QCString, QCString, int)";
+ if(_configFile != "kbabelrc" )
+ {
+ arg << _configFile.utf8();
+ callfunc="gotoFileEntry(QCString, QCString,int,QCString)";
+ }
+
+ kdDebug(KBABEL_CATMAN) << callfunc << endl;
+
+ // update the user timestamp for KBabel to get it a focus
+ kapp->updateRemoteUserTimestamp ("kbabel");
+
+ if( !client->send("kbabel","KBabelIFace", callfunc, data) )
+ KMessageBox::error(this, i18n("Cannot send a message to KBabel.\n"
+ "Please check your installation of KDE."));
+ }
+}
+
+void CatalogManager::openFileInNewWindow(QString filename, QString package)
+{
+ DCOPClient * client = kapp->dcopClient();
+
+ if( startKBabel() )
+ {
+
+ QByteArray data;
+ QCString url = filename.local8Bit();
+ QDataStream arg(data, IO_WriteOnly);
+ arg << url;
+ arg << package.utf8();
+ arg << CatalogManagerApp::_preferredWindow;
+ arg << ((int)1);
+
+ QCString callfunc="openURL(QCString, QCString, WId,int)";
+ if(_configFile != "kbabelrc" )
+ {
+ arg << _configFile.utf8();
+ callfunc="openURL(QCString, QCString, WId,int,QCString)";
+ }
+
+ // update the user timestamp for KBabel to get it a focus
+ kapp->updateRemoteUserTimestamp ("kbabel");
+
+ if( !client->send("kbabel","KBabelIFace", callfunc, data) )
+ KMessageBox::error(this, i18n("Cannot send a message to KBabel.\n"
+ "Please check your installation of KDE."));
+ }
+}
+
+void CatalogManager::openTemplate(QString openFilename,QString saveFilename,QString package)
+{
+ DCOPClient * client = kapp->dcopClient();
+
+ if( startKBabel() ) {
+ QByteArray data;
+ QCString url = openFilename.local8Bit();
+ QDataStream arg(data, IO_WriteOnly);
+ arg << url;
+ url = saveFilename.utf8();
+ arg << url;
+ arg << package.utf8();
+ arg << (_openNewWindow ? 1 : 0 );
+
+ QCString callfunc="openTemplate(QCString,QCString,QCString,int)";
+ if(_configFile != "kbabelrc" )
+ {
+ arg << _configFile.utf8();
+ callfunc="openTemplate(QCString,QCString,QCString,int,QCString)";
+ }
+
+ // update the user timestamp for KBabel to get it a focus
+ kapp->updateRemoteUserTimestamp ("kbabel");
+
+ if( !client->send("kbabel","KBabelIFace", callfunc, data) )
+ KMessageBox::error(this, i18n("Cannot send a message to KBabel.\n"
+ "Please check your installation of KDE."));
+ }
+}
+
+void CatalogManager::openTemplateInNewWindow(QString openFilename,QString saveFilename,QString package)
+{
+ DCOPClient * client = kapp->dcopClient();
+
+ if( startKBabel() ) {
+ QByteArray data;
+ QCString url = openFilename.local8Bit();
+ QDataStream arg(data, IO_WriteOnly);
+ arg << url;
+ url = saveFilename.utf8();
+ arg << url;
+ arg << package.utf8();
+ arg << ((int)1);
+
+ QCString callfunc="openTemplate(QCString,QCString,QCString,int)";
+ if(_configFile != "kbabelrc" )
+ {
+ arg << _configFile.utf8();
+ callfunc="openTemplate(QCString,QCString,QCString,int,QCString)";
+ }
+
+ // update the user timestamp for KBabel to get it a focus
+ kapp->updateRemoteUserTimestamp ("kbabel");
+
+ if( !client->send("kbabel","KBabelIFace", callfunc, data) )
+ KMessageBox::error(this, i18n("Cannot send a message to KBabel.\n"
+ "Please check your installation of KDE."));
+ }
+}
+
+void CatalogManager::spellcheck()
+{
+ DCOPClient * client = kapp->dcopClient();
+
+ QStringList fileList = _catalogManager->current();
+
+ if( startKBabel() ) {
+ QByteArray data;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << fileList;
+
+ // update the user timestamp for KBabel to get it a focus
+ kapp->updateRemoteUserTimestamp ("kbabel");
+
+ if( !client->send("kbabel","KBabelIFace", "spellcheck(QStringList)", data) )
+ KMessageBox::error(this, i18n("Cannot send a message to KBabel.\n"
+ "Please check your installation of KDE."));
+ }
+}
+
+void CatalogManager::markedSpellcheck()
+{
+ DCOPClient * client = kapp->dcopClient();
+
+ QStringList fileList = _catalogManager->marked();
+
+ if( startKBabel() ) {
+ QByteArray data;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << fileList;
+
+ // update the user timestamp for KBabel to get it a focus
+ kapp->updateRemoteUserTimestamp ("kbabel");
+
+ if( !client->send("kbabel","KBabelIFace", "spellcheck(QStringList)", data) )
+ KMessageBox::error(this, i18n("Cannot send a message to KBabel.\n"
+ "Please check your installation of KDE."));
+ }
+}
+
+bool CatalogManager::startKBabel()
+{
+ QCString service;
+ QString result;
+
+ DCOPClient * client = kapp->dcopClient();
+
+ // find out, if there is a running kbabel
+ QCStringList apps = client->registeredApplications();
+ for( QCStringList::Iterator it = apps.begin() ; it != apps.end() ; ++it )
+ {
+ QString clientID = *it;
+ if( clientID=="kbabel" )
+ {
+ service = *it;
+ break;
+ }
+ }
+
+ // if there is no running kbabel, start one
+ if( service.isEmpty() )
+ {
+ QString app = "kbabel";
+ QString url = "";
+ if( kapp->startServiceByDesktopName(app,url, &result, &service))
+ {
+ KMessageBox::error( this, i18n("Unable to use KLauncher to start KBabel.\n"
+ "You should check the installation of KDE.\n"
+ "Please start KBabel manually."));
+ return false;
+ } else sleep(1);
+ }
+
+ return true;
+}
+
+
+void CatalogManager::prepareProgressBar(QString msg, int max)
+{
+ _progressBar->setTotalSteps(max);
+ _progressBar->setProgress(0);
+ _progressLabel->setText(msg);
+
+ _progressBar->show();
+ _progressLabel->show();
+}
+
+void CatalogManager::clearProgressBar()
+{
+ _progressBar->setProgress(0);
+
+ _progressBar->hide();
+ _progressLabel->hide();
+}
+
+void CatalogManager::prepareStatusProgressBar(QString msg, int max)
+{
+ _totalFound = 0;
+ _foundToBeSent = 0;
+ _statusProgressBar->setTotalSteps(max);
+ _statusProgressLabel->setText(msg);
+ _foundLabel->setText( i18n("Found: 0/0") );
+
+ _statusProgressBar->show();
+ _statusProgressLabel->show();
+}
+
+void CatalogManager::prepareStatusProgressBar(int max)
+{
+ _statusProgressBar->setTotalSteps(max);
+}
+
+void CatalogManager::clearStatusProgressBar()
+{
+ _statusProgressBar->setValue(0);
+
+ _statusProgressBar->hide();
+ _statusProgressLabel->hide();
+ _foundLabel->setText(" ");
+}
+
+void CatalogManager::setNumberOfFound(int toBeSent, int total)
+{
+ _foundLabel->setText(i18n("Found: %1/%2").arg(toBeSent).arg(total));
+}
+
+void CatalogManager::decreaseNumberOfFound()
+{
+ if( _foundToBeSent > 0 ) {
+ _foundToBeSent--;
+ setNumberOfFound( _foundToBeSent, _totalFound );
+ }
+}
+
+void CatalogManager::slotHelp()
+{
+ kapp->invokeHelp("CATALOGMANAGER","kbabel");
+}
+
+void CatalogManager::find()
+{
+ if( !_findDialog ) _findDialog = new FindInFilesDialog(false,this);
+
+ if( _findDialog->exec("") == QDialog::Accepted )
+ {
+ _timerFind->stop();
+ _searchStopped = false;
+ _catalogManager->stop(false); // surely we are not in process of quitting, since there is no window and user cannot invoke Find
+ prepareStatusProgressBar(i18n("Searching"),1); // just show the progress bar
+
+ // enable stop action to stop searching
+ KAction *action = (KAction*)actionCollection()->action("stop_search");
+ action->setEnabled(true);
+
+ _findOptions = _findDialog->findOpts();
+
+ // get from options the information for ignoring text parts
+ _findOptions.contextInfo = QRegExp( _project->miscSettings().contextInfo );
+ _findOptions.accelMarker = _project->miscSettings().accelMarker;
+
+ _foundFilesList.clear();
+ kdDebug(KBABEL_CATMAN) << "Calling catalogmanagerview::find" << endl;
+ QString url = _catalogManager->find(_findOptions, _toBeSearched );
+
+ if( _catalogManager->isStopped() ) return;
+ if( !url.isEmpty() )
+ {
+ if( startKBabel() )
+ {
+ QCString funcCall("findInFile(QCString,QCString,QString,int,int,int,int,int,int,int,int,int,int)");
+ DCOPClient *client = kapp->dcopClient();
+ QByteArray data;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << client->appId();
+ arg << url.utf8();
+ arg << _findOptions.findStr;
+ arg << (_findOptions.caseSensitive ? 1 : 0);
+ arg << (_findOptions.wholeWords ? 1 : 0);
+ arg << (_findOptions.isRegExp ? 1 : 0);
+ arg << (_findOptions.inMsgid ? 1 : 0);
+ arg << (_findOptions.inMsgstr ? 1 : 0);
+ arg << (_findOptions.inComment ? 1 : 0);
+ arg << (_findOptions.ignoreAccelMarker ? 1 : 0);
+ arg << (_findOptions.ignoreContextInfo ? 1 : 0);
+ arg << (_findOptions.askForNextFile ? 1 : 0);
+ arg << (_findOptions.askForSave ? 1 : 0);
+ if(_configFile != "kbabelrc" ) {
+ arg << _configFile.utf8();
+ funcCall="findInFile(QCString,QCString,QString,int,int,int,int,int,int,int,int,int,int,QCString)";
+ }
+ kdDebug(KBABEL) << "DCOP: " << QString(data.data()) << endl;
+ if( !client->send("kbabel","KBabelIFace",
+ funcCall, data)
+ ) {
+ KMessageBox::error( this, i18n("DCOP communication with KBabel failed."), i18n("DCOP Communication Error"));
+ stopSearching();
+ return;
+ }
+
+ if( !_toBeSearched.isEmpty() )
+ {
+ _totalFound = 1;
+ _foundToBeSent = 0;
+ setNumberOfFound( 0, 1 ); // one found, but already sent
+ _timerFind->start(100,true);
+ } else stopSearching();
+ }
+ else
+ {
+ KMessageBox::error( this, i18n("KBabel cannot be started."), i18n("Cannot Start KBabel"));
+ stopSearching();
+ }
+
+ }
+ else
+ {
+ if( !_searchStopped) KMessageBox::information(this, i18n("Search string not found!"));
+ stopSearching();
+ }
+ }
+}
+
+void CatalogManager::replace()
+{
+ if( !_replaceDialog ) _replaceDialog = new FindInFilesDialog(true,this);
+
+
+ if( _replaceDialog->exec("") == QDialog::Accepted )
+ {
+ _timerFind->stop();
+ _searchStopped = false;
+ _catalogManager->stop(false); // surely we are not in process of quitting, since there is no window and user cannot invoke Find
+ prepareStatusProgressBar(i18n("Searching"),1); // just show the progress bar
+
+ // enable stop action to stop searching
+ KAction *action = (KAction*)actionCollection()->action("stop_search");
+ action->setEnabled(true);
+
+ ReplaceOptions options = _replaceDialog->replaceOpts();
+
+ _findOptions = options;
+
+ // get from options the information for ignoring text parts
+ options.contextInfo = QRegExp( _project->miscSettings().contextInfo );
+ options.accelMarker = _project->miscSettings().accelMarker;
+
+ _foundFilesList.clear();
+ QString url = _catalogManager->find(options, _toBeSearched );
+
+ if( _catalogManager->isStopped() ) return;
+ if( !url.isEmpty() )
+ {
+ if( startKBabel() )
+ {
+ QCString funcCall("replaceInFile(QCString,QCString,QString,QString,int,int,int,int,int,int,int,int,int,int,int)");
+ DCOPClient *client = kapp->dcopClient();
+ QByteArray data;
+ QDataStream arg(data, IO_WriteOnly);
+
+ arg << client->appId();
+ arg << url.utf8();
+ arg << options.findStr;
+ arg << options.replaceStr;
+ arg << (options.caseSensitive ? 1 : 0);
+ arg << (options.wholeWords ? 1 : 0);
+ arg << (options.isRegExp ? 1 : 0);
+ arg << (options.inMsgid ? 1 : 0);
+ arg << (options.inMsgstr ? 1 : 0);
+ arg << (options.inComment ? 1 : 0);
+ arg << (options.ignoreAccelMarker ? 1 : 0);
+ arg << (options.ignoreContextInfo ? 1 : 0);
+ arg << (options.ask ? 1 : 0);
+ arg << (options.askForNextFile ? 1 : 0);
+ arg << (options.askForSave ? 1 : 0);
+ if(_configFile != "kbabelrc" ) {
+ arg << _configFile.utf8();
+ funcCall="replaceInFile(QCString,QCString,QString,QString,int,int,int,int,int,int,int,int,int,int,int,QCString)";
+ }
+ if( !client->send("kbabel","KBabelIFace",
+ funcCall, data)
+ ) {
+ KMessageBox::error( this, i18n("DCOP communication with KBabel failed."), i18n("DCOP Communication Error"));
+ stopSearching();
+ return;
+ }
+
+ if( !_toBeSearched.isEmpty() )
+ {
+ _totalFound = 1;
+ setNumberOfFound( 0, 1 );
+ _timerFind->start(100,true);
+ } else stopSearching();
+ }
+ else
+ {
+ KMessageBox::error( this, i18n("KBabel cannot be started."), i18n("Cannot Start KBabel"));
+ stopSearching(); // update window
+ }
+
+ }
+ else
+ {
+ if( !_searchStopped ) KMessageBox::information(this, i18n("Search string not found!"));
+ stopSearching(); // update window
+ }
+ }
+}
+
+void CatalogManager::findNextFile()
+{
+ _timerFind->stop(); // stop the timer for lookup time
+ if(_toBeSearched.empty() )
+ {
+ stopSearching();
+ return;
+ }
+ QString file = _toBeSearched.first();
+ _toBeSearched.pop_front();
+ if( PoInfo::findInFile( file, _findOptions ) )
+ {
+ _foundFilesList.append(file);
+ _totalFound++;
+ _foundToBeSent++;
+ setNumberOfFound(_foundToBeSent,_totalFound);
+ }
+ _statusProgressBar->advance(1);
+ if( !_toBeSearched.empty() )
+ _timerFind->start(100,true); // if there is more files to be searched, start the timer again
+ else
+ stopSearching();
+}
+
+void CatalogManager::stopSearching()
+{
+ _searchStopped = true;
+ emit searchStopped();
+ // clear the list of files to be searched
+ _toBeSearched.clear();
+
+ // fake that we are over (fake, because findNextFile can still be running for the last file
+ clearStatusProgressBar(); // clear the status bar, we are finished
+ // disable stop action as well
+ KAction *action = (KAction*)actionCollection()->action("stop_search");
+ action->setEnabled(false);
+}
+
+void CatalogManager::optionsPreferences()
+{
+ if(!_prefDialog)
+ {
+ _prefDialog = new KBabel::ProjectDialog(_project);
+ }
+
+ _prefDialog->exec();
+}
+
+void CatalogManager::newToolbarConfig()
+{
+ createGUI();
+ restoreView();
+}
+
+void CatalogManager::optionsShowStatusbar(bool on)
+{
+ if( on )
+ statusBar()->show();
+ else
+ statusBar()->hide();
+}
+
+bool CatalogManager::queryClose()
+{
+ _catalogManager->stop();
+ saveView();
+ saveSettings(_configFile);
+ return true;
+}
+
+void CatalogManager::saveView()
+{
+ saveMainWindowSettings( KGlobal::config(), "View");
+}
+
+
+void CatalogManager::restoreView()
+{
+ applyMainWindowSettings( KGlobal::config(), "View");
+
+ KToggleAction * toggle = (KToggleAction*)actionCollection()->
+ action(KStdAction::stdName(KStdAction::ShowStatusbar));
+ toggle->setChecked(!statusBar()->isHidden() );
+}
+
+
+void CatalogManager::projectNew()
+{
+ KBabel::Project::Ptr p = KBabel::ProjectWizard::newProject();
+ if( p )
+ {
+ disconnect( _project, SIGNAL (signalCatManSettingsChanged())
+ , this, SLOT (updateSettings()));
+ _project = p;
+ connect( _project, SIGNAL (signalCatManSettingsChanged())
+ , this, SLOT (updateSettings()));
+
+ _configFile = _project->filename();
+ restoreSettings();
+ updateSettings();
+ changeProjectActions(p->filename());
+ emit settingsChanged(_settings);
+ }
+}
+
+void CatalogManager::projectOpen()
+{
+ QString oldproject = _project->filename();
+ if( oldproject == KBabel::ProjectManager::defaultProjectName() )
+ {
+ oldproject = QString();
+ }
+ const QString file = KFileDialog::getOpenFileName(oldproject, QString::null, this);
+ if (file.isEmpty())
+ {
+ return;
+ }
+ KBabel::Project::Ptr p = KBabel::ProjectManager::open(file);
+ if( p )
+ {
+ disconnect( _project, SIGNAL (signalCatManSettingsChanged())
+ , this, SLOT (updateSettings()));
+ _project = p;
+ connect( _project, SIGNAL (signalCatManSettingsChanged())
+ , this, SLOT (updateSettings()));
+
+ _configFile = p->filename();
+ restoreSettings();
+ updateSettings();
+ changeProjectActions(file);
+ emit settingsChanged(_settings);
+
+ }
+ else
+ {
+ KMessageBox::error (this, i18n("Cannot open project file %1").arg(file));
+ }
+}
+
+void CatalogManager::projectClose()
+{
+ disconnect( _project, SIGNAL (signalCatManSettingsChanged())
+ , this, SLOT (updateSettings()));
+ _project = KBabel::ProjectManager::open(KBabel::ProjectManager::defaultProjectName());
+ connect( _project, SIGNAL (signalCatManSettingsChanged())
+ , this, SLOT (updateSettings()));
+ _configFile = _project->filename();
+ restoreSettings();
+ updateSettings();
+ changeProjectActions(KBabel::ProjectManager::defaultProjectName());
+ emit settingsChanged(_settings);
+}
+
+void CatalogManager::changeProjectActions(const QString& project)
+{
+ bool def = ( project == KBabel::ProjectManager::defaultProjectName() ) ;
+
+ KAction* saveAction=(KAction*)actionCollection()->action( "project_close" );
+ saveAction->setEnabled( ! def );
+}
+
+void CatalogManager::projectConfigure()
+{
+ KBabel::ProjectDialog* _projectDialog = new ProjectDialog(_project);
+
+ connect (_projectDialog, SIGNAL (settingsChanged())
+ , this, SLOT (updateSettings()));
+
+ // settings are updated via signals
+ _projectDialog->exec();
+
+ delete _projectDialog;
+}
+
+void CatalogManager::enableActions()
+{
+ enableActions(true);
+}
+
+void CatalogManager::disableActions()
+{
+ enableActions(false);
+}
+
+void CatalogManager::enableActions(bool enable)
+{
+ KAction* action;
+ // the file menu
+
+ action = (KAction*)actionCollection()->action( "open" );
+ action->setEnabled(enable);
+
+ action = (KAction*)actionCollection()->action( "open_new_window" );
+ action->setEnabled(enable);
+
+ action = (KAction*)actionCollection()->action( "find_in_files" );
+ action->setEnabled(enable);
+
+ action = (KAction*)actionCollection()->action( "replace_in_files" );
+ action->setEnabled(enable);
+
+ action = (KAction*)actionCollection()->action( "reload" );
+ action->setEnabled(enable);
+
+ action = (KAction*)actionCollection()->action( "toggle_marking" );
+ action->setEnabled(enable);
+
+ action = (KAction*)actionCollection()->action( "toggle_all_marking" );
+ action->setEnabled(enable);
+
+ action = (KAction*)actionCollection()->action( "mark_modified_files" );
+ action->setEnabled(enable);
+
+ action = (KAction*)actionCollection()->action( "load_marking" );
+ action->setEnabled(enable);
+
+ action = (KAction*)actionCollection()->action( "save_marking" );
+ action->setEnabled(enable);
+
+ action = (KAction*)actionCollection()->action( "go_next_untrans" );
+ action->setEnabled(enable);
+
+ action = (KAction*)actionCollection()->action( "go_prev_untrans" );
+ action->setEnabled(enable);
+
+ action = (KAction*)actionCollection()->action( "go_next_fuzzy" );
+ action->setEnabled(enable);
+
+ action = (KAction*)actionCollection()->action( "go_prev_fuzzy" );
+ action->setEnabled(enable);
+
+ action = (KAction*)actionCollection()->action( "go_next_fuzzyUntr" );
+ action->setEnabled(enable);
+
+ action = (KAction*)actionCollection()->action( "go_prev_fuzzyUntr" );
+ action->setEnabled(enable);
+
+ action = (KAction*)actionCollection()->action( "go_next_error" );
+ action->setEnabled(enable);
+
+ action = (KAction*)actionCollection()->action( "go_prev_error" );
+ action->setEnabled(enable);
+
+ action = (KAction*)actionCollection()->action( "go_next_template" );
+ action->setEnabled(enable);
+
+ action = (KAction*)actionCollection()->action( "go_prev_template" );
+ action->setEnabled(enable);
+
+ action = (KAction*)actionCollection()->action( "go_next_po" );
+ action->setEnabled(enable);
+
+ action = (KAction*)actionCollection()->action( "go_prev_po" );
+ action->setEnabled(enable);
+
+ action = (KAction*)actionCollection()->action( "go_next_marked" );
+ action->setEnabled(enable);
+
+ action = (KAction*)actionCollection()->action( "go_prev_marked" );
+ action->setEnabled(enable);
+
+ action = (KAction*)actionCollection()->action( "statistics" );
+ action->setEnabled(enable);
+
+ action = (KAction*)actionCollection()->action( "package_file" );
+ action->setEnabled(enable);
+
+ action = (KAction*)actionCollection()->action( "rough_translation" );
+ action->setEnabled(enable);
+}
+
+#include "catalogmanager.moc"
diff --git a/kbabel/catalogmanager/catalogmanager.desktop b/kbabel/catalogmanager/catalogmanager.desktop
new file mode 100644
index 00000000..3c470b1c
--- /dev/null
+++ b/kbabel/catalogmanager/catalogmanager.desktop
@@ -0,0 +1,98 @@
+[Desktop Entry]
+Name=KBabel Catalog Manager
+Name[bg]=Управление на каталога - KBabel
+Name[br]=Merour katalogoù KBabel
+Name[ca]=Gestor de catàlegs de KBabel
+Name[cs]=Správce katalogů
+Name[da]=KBabel kataloghåndtering
+Name[de]=KBabel-Katalogmanager
+Name[el]=ΔιαχειÏιστής καταλόγων του KBabel
+Name[en_GB]=KBabel Catalogue Manager
+Name[eo]=Babelo-katalogadministrilo
+Name[es]=Administrador de catálogos de KBabel
+Name[et]=Kataloogihaldur
+Name[eu]=KBabel katalogo kudeatzailea
+Name[fa]= مدیر Ùهرست KBabel
+Name[fi]=KBabel - käännöspakettien hallinta
+Name[fr]=Gestionnaire de catalogues de KBabel
+Name[ga]=KBabel - Bainisteoir na gCatalóg
+Name[gl]=Xestor de Catálogos de KBabel
+Name[he]=KBabel - מנהל הקטלוגי×
+Name[hu]=KBabel listakezelő
+Name[is]=KBabel Þýðingarstjóri
+Name[it]=Gestore dei cataloghi di KBabel
+Name[ja]=KBabel カタログマãƒãƒ¼ã‚¸ãƒ£
+Name[ka]=KBabel-ის კáƒáƒ¢áƒáƒšáƒáƒ’ის მმáƒáƒ áƒ—ველი
+Name[kk]=KBabel каталог менеджері
+Name[lt]=KBabel katalogo tvarkytuvÄ—
+Name[nb]=KBabel-katalogbehandler
+Name[nds]=KBabel-Kataloogpleger
+Name[ne]=केबà¥à¤¯à¤¾à¤¬à¤² विवरणिका पà¥à¤°à¤¬à¤¨à¥à¤§à¤•
+Name[nl]=KBabel catalogusbeheer
+Name[nn]=KBabel Kataloghandsamar
+Name[pa]=KBabel ਸੂਚੀ ਪà©à¨°à¨¬à©°à¨§à¨•
+Name[pl]=KBabel - Menedżer tłumaczeń
+Name[pt]=Gestor de Catálogos do KBabel
+Name[pt_BR]=Gerenciador de Catálogos do KBabel
+Name[ru]=Менеджер Ñообщений Gettext
+Name[sk]=KBabel - správca katalógov
+Name[sl]=Upravitelj katalogov KBabel
+Name[sr]=KBabel-ов Менаџер каталога
+Name[sr@Latn]=KBabel-ov Menadžer kataloga
+Name[sv]=Kbabel kataloghanterare
+Name[tr]=KBabel Katalog Yöneticisi
+Name[uk]=Менеджер каталогів KBabel
+Name[zh_CN]=KBabel 目录管ç†å™¨
+Name[zh_TW]=KBabel - 目錄管ç†å“¡
+GenericName=Translation Tool Catalog Manager
+GenericName[bg]=ИнÑтрумент за превод
+GenericName[ca]=Gestor de catàlegs de l'eina de traducció
+GenericName[cs]=Správce katalogů překladů
+GenericName[da]=Oversættelsesværktøjs kataloghåndtering
+GenericName[de]=Katalogmanager für Übersetzungsprogramm
+GenericName[el]=ΔιαχειÏιστής καταλόγων εÏγαλείου μετάφÏασης
+GenericName[en_GB]=Translation Tool Catalogue Manager
+GenericName[eo]=Katalogadministrilo por Tradukiloj
+GenericName[es]=Administrador de catálogos de la herramienta de traducción
+GenericName[et]=KBabel'i kataloogihaldur
+GenericName[eu]=Itzulpen tresnen katalogo kudeatzailea
+GenericName[fa]=مدیر Ùهرست ابزار ترجمه
+GenericName[fi]=Käännöstyökalun käännöspakettien hallinta
+GenericName[fr]=Gestionnaire de catalogues de traduction
+GenericName[ga]=Uirlis Aistriúcháin - Bainisteoir na gCatalóg
+GenericName[gl]=Xestor de Catálogos de Tradución
+GenericName[he]=מנהל ×”×§×˜×œ×•×’×™× ×©×œ כלי התרגו×
+GenericName[hu]=Fordítássegítő
+GenericName[is]=Þýðingarforrit - Þýðingarstjóri
+GenericName[it]=Gestore dei cataloghi di uno strumento di traduzione
+GenericName[ja]=翻訳ツール カタログマãƒãƒ¼ã‚¸ãƒ£
+GenericName[ka]=კáƒáƒ¢áƒáƒšáƒáƒ’ის მმáƒáƒ áƒ—ველის სáƒáƒ—áƒáƒ áƒ’მნი ხელსáƒáƒ¬áƒ§áƒ
+GenericName[kk]=Ðудару құралының Каталог менеджері
+GenericName[lt]=Vertimo įrankio katalogo tvarkytuvė
+GenericName[nb]=Verktøy for håndtering av oversettelseskataloger
+GenericName[nds]=Översettenwarktüüch-Kataloogpleger
+GenericName[ne]=अनà¥à¤¬à¤¾à¤¦ उपकरण विवरणिका पà¥à¤°à¤¬à¤¨à¥à¤§à¤•
+GenericName[nl]=Vertaalhulpmiddel catalogusbeheer
+GenericName[nn]=Verktøy for handtering av omsetjingskatalogar
+GenericName[pa]=ਅਨà©à¨µà¨¾à¨¦ ਸੰਦ ਲਈ ਸੂਚੀ ਪà©à¨°à¨¬à©°à¨§à¨•
+GenericName[pl]=Menedżer tłumaczeń
+GenericName[pt]=Gestor de Catálogos de Ferramenta de Tradução
+GenericName[pt_BR]=Gerenciador de Catálogo da Ferramenta de Tradução
+GenericName[ru]=Ð›Ð¾ÐºÐ°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ð¹
+GenericName[sk]=Správca katalógov pre prekladací nástroj
+GenericName[sl]=Upravitelj katalogov orodja za prevajanje
+GenericName[sr]=Менаџер каталога преводилачких алата
+GenericName[sr@Latn]=Menadžer kataloga prevodilaÄkih alata
+GenericName[sv]=Översättningsverktyg kataloghanterare
+GenericName[tr]=Çeviri Aracı Katalog Yöneticisi
+GenericName[uk]=Менеджер каталогів заÑобу Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐºÐ»Ð°Ð´Ñ–Ð²
+GenericName[zh_CN]=翻译工具目录管ç†å™¨
+GenericName[zh_TW]=翻譯工具目錄管ç†å“¡
+Exec=catalogmanager %i %m -caption "%c" %U
+Icon=catalogmanager
+Type=Application
+DocPath=kbabel/index.html
+Terminal=false
+X-KDE-StartupNotify=true
+X-DCOP-ServiceType=Multi
+Categories=Qt;KDE;Development;Translation;
diff --git a/kbabel/catalogmanager/catalogmanager.h b/kbabel/catalogmanager/catalogmanager.h
new file mode 100644
index 00000000..67f871fa
--- /dev/null
+++ b/kbabel/catalogmanager/catalogmanager.h
@@ -0,0 +1,218 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2001-2004 by Stanislav Visnovsky <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef CATALOGMANAGER_H
+#define CATALOGMANAGER_H
+
+#include <qdict.h>
+#include <qlistview.h>
+#include <qdatetime.h>
+#include <qfileinfo.h>
+#include <qguardedptr.h>
+#include <qmap.h>
+
+#include <kdeversion.h>
+#include <kmainwindow.h>
+#include <kdirwatch.h>
+#include <kprocess.h>
+#include <qptrlist.h>
+
+#include "projectsettings.h"
+#include "kbproject.h"
+#include "catalog.h"
+#include "catalogmanagerview.h"
+
+class CatManListItem;
+class QPixmap;
+class QPopupMenu;
+class QTimer;
+class KProgress;
+class KAction;
+class KConfig;
+class FindInFilesDialog;
+
+namespace KBabel
+{
+ class PoInfo;
+ class ProjectDialog;
+}
+
+class CatalogManager : public KMainWindow
+{
+ Q_OBJECT
+public:
+ CatalogManager(QString configfile = QString() );
+ ~CatalogManager();
+
+ KBabel::CatManSettings settings() const;
+ /**
+ * Sets the window, in which the files should be opened.
+ * This is set by KBabel::openCatalogManager
+ */
+ void setPreferredWindow(WId id);
+
+ /** updates the file fileWithPath in the @ref CatalogManagerView */
+ void updateFile(QString fileWithPath);
+ void updateAfterSave(QString fileWithPath, KBabel::PoInfo &info);
+
+ CatalogManagerView *view();
+
+ void pause(bool flag) { if( _catalogManager ) _catalogManager->pause (flag); }
+
+ static QStringList _foundFilesList;
+ static QStringList _toBeSearched;
+
+public slots:
+ /** updates the settings from the project */
+ void updateSettings();
+ void enableMenuForFiles(bool enable);
+ void selectedChanged(uint actionValue);
+ virtual void slotHelp();
+
+ virtual void find();
+ virtual void replace();
+ virtual void stopSearching();
+ virtual void optionsPreferences();
+ virtual void optionsShowStatusbar(bool on);
+ virtual void dummySlot() {}
+
+ void projectNew();
+ void projectOpen();
+ void projectClose();
+ void projectConfigure();
+ void changeProjectActions(const QString& project);
+
+ virtual void clearProgressBar();
+ virtual void prepareProgressBar(QString msg, int max);
+
+ virtual void clearStatusProgressBar();
+ virtual void prepareStatusProgressBar(QString msg, int max);
+ virtual void prepareStatusProgressBar(int max);
+
+ virtual void setNumberOfFound( int toBeSent, int total );
+ virtual void decreaseNumberOfFound();
+
+protected slots:
+ virtual void findNextFile();
+ virtual bool queryClose();
+
+signals:
+ void settingsChanged(KBabel::CatManSettings);
+ void signalQuit();
+ void searchStopped();
+
+private:
+ void init();
+
+ void restoreView();
+ void saveView();
+
+ void saveSettings( QString configFile = QString::null );
+
+ void setupActions();
+ void setupStatusBar();
+
+ bool startKBabel();
+
+private slots:
+ /**
+ * calls @ref KBabel::open where as preferred windos _preferredWindow
+ * is used. If this is deleted meanwhile, the first window in
+ * @ref KMainWindow::memberList is used.
+ */
+ void openFile(QString filename,QString package);
+ void openFile(QString filename,QString package, int msgid);
+ void openFileInNewWindow(QString filename,QString package);
+ /**
+ * calls @ref KBabel::openTemplate where as preferred windos _preferredWindow
+ * is used. If this is deleted meanwhile, the first window in
+ * @ref KMainWindow::memberList is used.
+ */
+ void openTemplate(QString openFilename,QString saveFileName,QString package);
+ void openTemplateInNewWindow(QString openFilename,QString saveFileName,QString package);
+
+ void markedSpellcheck();
+ void spellcheck();
+
+ void newToolbarConfig();
+
+ /** updates views and _settings variable */
+ void restoreSettings();
+
+ void enableActions();
+ void disableActions();
+
+ void enableActions(bool enable);
+
+private:
+ CatalogManagerView* _catalogManager;
+
+ WId _preferredWindow;
+
+ bool _openNewWindow;
+
+ FindInFilesDialog* _findDialog;
+ FindInFilesDialog* _replaceDialog;
+ KBabel::ProjectDialog* _prefDialog;
+
+ /// update progress bar
+ KProgress* _progressBar;
+ QLabel* _progressLabel;
+
+ /// statusbar progress bar
+ KProgress* _statusProgressBar;
+ QLabel* _statusProgressLabel;
+ QLabel* _foundLabel;
+ int _foundToBeSent;
+ int _totalFound;
+
+ QTimer* _timerFind;
+ bool _searchStopped;
+
+ KBabel::CatManSettings _settings;
+ KBabel::MiscSettings _miscSettings;
+
+ /// options used in findNextFile
+ KBabel::FindOptions _findOptions;
+
+
+ /// project configuration file
+ QString _configFile;
+ KBabel::Project::Ptr _project;
+
+ KConfig* config;
+
+ QMap<QString,uint> actionMap;
+};
+
+#endif // CATALOGMANAGER_H
diff --git a/kbabel/catalogmanager/catalogmanagerapp.h b/kbabel/catalogmanager/catalogmanagerapp.h
new file mode 100644
index 00000000..e0762e5b
--- /dev/null
+++ b/kbabel/catalogmanager/catalogmanagerapp.h
@@ -0,0 +1,73 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2001 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2001 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef CATALOGMANAGERAPP_H
+#define CATALOGMANAGERAPP_H
+
+#include "catalogmanager.h"
+#include "catalogmanageriface.h"
+
+#include "version.h"
+
+#include <kapplication.h>
+#include <kwin.h>
+
+class CatalogManagerInterface : public CatalogManagerIface
+{
+public:
+ CatalogManagerInterface();
+
+ virtual void setPreferredWindow( WId id );
+ virtual QCString findNextFile();
+ virtual void updatedFile( QCString url );
+};
+
+class CatalogManagerApp : public KApplication
+{
+public:
+ CatalogManagerApp();
+ virtual ~CatalogManagerApp();
+
+ virtual int newInstance();
+
+ static void setPreferredWindow( WId id );
+ static QCString findNextFile();
+ static void updatedFile( QCString url );
+ static WId _preferredWindow;
+private:
+ CatalogManagerInterface *kbInterface;
+ static CatalogManager * _view;
+};
+
+#endif
diff --git a/kbabel/catalogmanager/catalogmanageriface.h b/kbabel/catalogmanager/catalogmanageriface.h
new file mode 100644
index 00000000..232a694c
--- /dev/null
+++ b/kbabel/catalogmanager/catalogmanageriface.h
@@ -0,0 +1,67 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2001 by Stanislav Visnovsky <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef CATALOGMANAGERIFACE_H
+#define CATALOGMANAGERIFACE_H
+
+#include <dcopobject.h>
+
+class CatalogManagerIface : virtual public DCOPObject
+{
+ K_DCOP
+public:
+
+k_dcop:
+
+ /**
+ * Sets the WId of the preferred window. The window will get
+ * calls to open files or templates when requested in catalog manager.
+ * @param id is the WId of the window to be used
+ */
+ virtual void setPreferredWindow( WId id ) { id = 0; }
+
+ /**
+ * Returns a next file containing the searched string. Invoked from
+ * KBabel in case the FindNext() finishes a file and wants to continue in
+ * the next one.
+ * @returns a URL to the next file, QString:null if there is no more
+ * files to be searched or empty string if the search string
+ * is not found yet, but there is more files to be searched in.
+ */
+ virtual QCString findNextFile() = 0;
+
+ /**
+ * If you care about this file, you should update information shown.
+ */
+ virtual void updatedFile( QCString url) = 0;
+};
+
+#endif // CATALOGMANAGERIFACE_H
diff --git a/kbabel/catalogmanager/catalogmanagerui.rc b/kbabel/catalogmanager/catalogmanagerui.rc
new file mode 100644
index 00000000..498a4bc7
--- /dev/null
+++ b/kbabel/catalogmanager/catalogmanagerui.rc
@@ -0,0 +1,262 @@
+<!DOCTYPE kpartgui>
+<kpartgui name="catalogmanager" version="26">
+ <MenuBar>
+ <Menu name="edit"><text>&amp;Edit</text>
+ <Action name="find_in_files"/>
+ <Action name="replace_in_files"/>
+ <Action name="stop_search"/>
+ <Separator/>
+ <Action name="reload"/>
+ </Menu>
+ <Menu name="go"><text>&amp;Go</text>
+ <Action name="go_next_fuzzyUntr"/>
+ <Action name="go_prev_fuzzyUntr"/>
+ <Action name="go_next_fuzzy"/>
+ <Action name="go_prev_fuzzy"/>
+ <Action name="go_next_untrans"/>
+ <Action name="go_prev_untrans"/>
+ <Separator/>
+ <Action name="go_next_error"/>
+ <Action name="go_prev_error"/>
+ <Separator/>
+ <Action name="go_next_marked"/>
+ <Action name="go_prev_marked"/>
+ <Separator/>
+ <Action name="go_next_template"/>
+ <Action name="go_prev_template"/>
+ <Action name="go_next_po"/>
+ <Action name="go_prev_po"/>
+ </Menu>
+ <Menu name="markings"><text>&amp;Markings</text>
+ <Action name="toggle_marking"/>
+ <Action name="remove_marking"/>
+ <Action name="toggle_all_marking"/>
+ <Action name="remove_all_marking"/>
+ <Action name="mark_modified_files"/>
+ <Separator/>
+ <Action name="mark_pattern"/>
+ <Action name="unmark_pattern"/>
+ <Separator/>
+ <Action name="load_marking"/>
+ <Action name="save_marking"/>
+ </Menu>
+ <Menu name="projects"><text>&amp;Project</text>
+ <Action name="project_new"/>
+ <Action name="project_open"/>
+ <Action name="project_close"/>
+ <Action name="project_settings"/>
+ </Menu>
+ <Menu name="tools"><text>&amp;Tools</text>
+ <Action name="statistics"/>
+ <Action name="statistics_marked"/>
+ <Action name="syntax"/>
+ <Separator/>
+ <Action name="spellcheck"/>
+ <Action name="spellcheck_marked"/>
+ <Separator/>
+ <Action name="rough_translation"/>
+ <Action name="rough_translation_marked"/>
+ <Separator/>
+ <Menu name="cvs_menu"><text>CVS</text>
+ <Action name="cvs_update"/>
+ <Action name="cvs_update_marked"/>
+ <Separator/>
+ <Action name="cvs_commit"/>
+ <Action name="cvs_commit_marked"/>
+ <Separator/>
+ <Action name="cvs_status"/>
+ <Action name="cvs_status_marked"/>
+ <Separator/>
+ <Action name="cvs_update_template"/>
+ <Action name="cvs_update_marked_template"/>
+ <Separator/>
+ <Action name="cvs_commit_template"/>
+ <Action name="cvs_commit_marked_template"/>
+ <Separator/>
+ <Action name="cvs_diff"/>
+ </Menu>
+ <Menu name="svn_menu"><text>SVN</text>
+ <Action name="svn_update"/>
+ <Action name="svn_update_marked"/>
+ <Separator/>
+ <Action name="svn_commit"/>
+ <Action name="svn_commit_marked"/>
+ <Separator/>
+ <Action name="svn_status_local"/>
+ <Action name="svn_status_local_marked"/>
+ <Separator/>
+ <Action name="svn_status_remote"/>
+ <Action name="svn_status_remote_marked"/>
+ <Separator/>
+ <Action name="svn_update_template"/>
+ <Action name="svn_update_marked_template"/>
+ <Separator/>
+ <Action name="svn_commit_template"/>
+ <Action name="svn_commit_marked_template"/>
+ <Separator/>
+ <Action name="svn_diff"/>
+ <Separator/>
+ <Action name="svn_info"/>
+ <Action name="svn_info_marked"/>
+ </Menu>
+ <Separator/>
+ <Action name="mail_file"/>
+ <Action name="mail_file_marked"/>
+ <Separaator/>
+ <Action name="package_file"/>
+ <Action name="package_file_marked"/>
+ <Separator/>
+ <Action name="dynamic_validation"/>
+ <Action name="dynamic_validation_marked"/>
+ </Menu>
+ <Menu name="settings"><text>&amp;Settings</text>
+ <Action name="settings_show_navbar" append="show_merge"/>
+ <Action name="settings_show_comments" append="show_merge"/>
+ <Action name="settings_show_tools" append="show_merge"/>
+ </Menu>
+ <Menu name="help"><text>&amp;Help</text>
+ <Action name="help_gettext"/>
+ <Action name="dict_about" append="about_merge"/>
+ </Menu>
+ </MenuBar>
+ <ToolBar name="mainToolBar"><text>Main</text>
+ <Action name="reload"/>
+ <Action name="statistics"/>
+ <Action name="syntax"/>
+ <Action name="stop_search"/>
+ </ToolBar>
+ <ToolBar name="navigationbar"><text>Navigationbar</text>
+ <Action name="go_prev_entry"/>
+ <Action name="go_next_entry"/>
+ <Separator/>
+ <Action name="go_first"/>
+ <Action name="go_last"/>
+ <Action name="go_prev_fuzzyUntr"/>
+ <Action name="go_next_fuzzyUntr"/>
+ <Action name="go_prev_fuzzy"/>
+ <Action name="go_next_fuzzy"/>
+ <Action name="go_prev_untrans"/>
+ <Action name="go_next_untrans"/>
+ <Separator/>
+ <Action name="go_prev_error"/>
+ <Action name="go_next_error"/>
+ <Separator/>
+ <Action name="go_prev_marked"/>
+ <Action name="go_next_marked"/>
+ <Separator/>
+ <Action name="go_prev_template"/>
+ <Action name="go_next_template"/>
+ <Action name="go_prev_po"/>
+ <Action name="go_next_po"/>
+ </ToolBar>
+ <Menu name="rmb_file">
+ <Action name="open"/>
+ <Action name="open_new_window"/>
+ <Action name="open_template"/>
+ <Action name="toggle_marking"/>
+ <Separator/>
+ <Action name="reload"/>
+ <Separator/>
+ <Action name="syntax"/>
+ <Action name="statistics"/>
+ <Action name="dynamic_validation"/>
+ <Action name="file_commands"/>
+ <Separator/>
+ <Menu name="rmb_file_cvs"><text>CVS</text>
+ <Action name="cvs_update"/>
+ <Action name="cvs_commit"/>
+ <Action name="cvs_status"/>
+ <Separator/>
+ <Action name="cvs_update_template"/>
+ <Action name="cvs_commit_template"/>
+ <Separator/>
+ <Action name="cvs_diff"/>
+ </Menu>
+ <Menu name="rmb_file_svn"><text>SVN</text>
+ <Action name="svn_update"/>
+ <Action name="svn_commit"/>
+ <Action name="svn_status_local"/>
+ <Action name="svn_status_remote"/>
+ <Separator/>
+ <Action name="svn_update_template"/>
+ <Action name="svn_commit_template"/>
+ <Separator/>
+ <Action name="svn_diff"/>
+ </Menu>
+ <Separator/>
+ <Action name="delete"/>
+ </Menu>
+ <Menu name="rmb_dir">
+ <Action name="toggle_marking"/>
+ <Action name="remove_marking"/>
+ <Action name="toggle_all_marking"/>
+ <Action name="remove_all_marking"/>
+ <Separator/>
+ <Action name="reload"/>
+ <Separator/>
+ <Action name="syntax"/>
+ <Action name="statistics"/>
+ <Action name="dynamic_validation"/>
+ <Action name="dir_commands"/>
+ <Separator/>
+ <Menu name="rmb_dir_cvs"><text>CVS</text>
+ <Action name="cvs_update"/>
+ <Action name="cvs_commit"/>
+ <Action name="cvs_status"/>
+ <Separator/>
+ <Action name="cvs_update_template"/>
+ <Action name="cvs_commit_template"/>
+ <Separator/>
+ <Action name="cvs_diff"/>
+ </Menu>
+ <Menu name="rmb_dir_svn"><text>SVN</text>
+ <Action name="svn_update"/>
+ <Action name="svn_commit"/>
+ <Action name="svn_status_local"/>
+ <Action name="svn_status_remote"/>
+ <Separator/>
+ <Action name="svn_update_template"/>
+ <Action name="svn_commit_template"/>
+ <Separator/>
+ <Action name="svn_diff"/>
+ </Menu>
+ </Menu>
+
+<State name="treeBuilt">
+ <Enable>
+ <Action name="open"/>
+ <Action name="open_new_window"/>
+ <Action name="find_in_files"/>
+ <Action name="replace_in_files"/>
+ <Action name="reload"/>
+
+ <Action name="go_next_fuzzyUntr"/>
+ <Action name="go_prev_fuzzyUntr"/>
+ <Action name="go_next_fuzzy"/>
+ <Action name="go_prev_fuzzy"/>
+ <Action name="go_next_untrans"/>
+ <Action name="go_prev_untrans"/>
+ <Action name="go_next_error"/>
+ <Action name="go_prev_error"/>
+ <Action name="go_next_marked"/>
+ <Action name="go_prev_marked"/>
+ <Action name="go_next_template"/>
+ <Action name="go_prev_template"/>
+ <Action name="go_next_po"/>
+ <Action name="go_prev_po"/>
+ <Action name="load_marking"/>
+ <Action name="save_marking"/>
+ <Action name="toggle_marking"/>
+ <Action name="toggle_all_marking"/>
+ <Action name="statistics"/>
+ <Action name="rough_translation"/>
+ <Action name="reload"/>
+ <Action name="dynamic_validation"/>
+ <Action name="dynamic_validation_marked"/>
+ <Action name="mail_file"/>
+ <Action name="mark_pattern"/>
+ <Action name="unmark_pattern"/>
+ </Enable>
+</State>
+
+</kpartgui>
diff --git a/kbabel/catalogmanager/catalogmanagerview.cpp b/kbabel/catalogmanager/catalogmanagerview.cpp
new file mode 100644
index 00000000..6bb4c88f
--- /dev/null
+++ b/kbabel/catalogmanager/catalogmanagerview.cpp
@@ -0,0 +1,3132 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2001-2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+ Copyright (C) 2005, 2006 by Nicolas GOUTTE <goutte@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#include "catmanresource.h"
+#include "catalogmanager.h"
+#include "catmanlistitem.h"
+#include "catalog.h"
+#include "kbabeldictbox.h"
+
+#include "resources.h"
+#include "multiroughtransdlg.h"
+#include "msgfmt.h"
+#include "kbmailer.h"
+#include "validateprogress.h"
+#include "cvshandler.h"
+#include "svnhandler.h"
+#include "markpatterndialog.h"
+#include "validationoptions.h"
+
+#include <qcheckbox.h>
+#include <qpopupmenu.h>
+#include <qlabel.h>
+#include <qpainter.h>
+
+#include <kcmenumngr.h>
+#include <kcursor.h>
+#include <klocale.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+#include <kconfig.h>
+#include <kdatatool.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+#include <kapplication.h>
+#include <kaction.h>
+#include <kfiledialog.h>
+#include <kio/netaccess.h>
+#include <kprogress.h>
+#include <kwin.h>
+#include <kdeversion.h>
+#include <ktempfile.h>
+
+#include <qfileinfo.h>
+#include <qdir.h>
+#include <qtimer.h>
+#include <qbitmap.h>
+#include <qwhatsthis.h>
+#include <qheader.h>
+#include <qdragobject.h>
+#include <qlayout.h>
+#include <qtextedit.h>
+
+using namespace KBabel;
+
+const char* columnNames[] = {
+ I18N_NOOP("Name"),
+ I18N_NOOP("M"),
+ I18N_NOOP("Fuzzy"),
+ I18N_NOOP("Untranslated"),
+ I18N_NOOP("Total"),
+ I18N_NOOP("CVS/SVN Status"),
+ I18N_NOOP("Last Revision"),
+ I18N_NOOP("Last Translator")
+};
+
+#define COLTEXT(a) (i18n(columnNames[a]))
+
+CatalogManagerView::CatalogManagerView(KBabel::Project::Ptr project, QWidget* parent,const char* name)
+ : QListView(parent,name)
+ , _dirWatch(0)
+ , _readInfoCount(0)
+ , _active(false)
+ , _stop(false)
+ , _stopSearch(false)
+ , _updateNesting(0)
+ , _logView(0)
+ , _logWindow(0)
+ , m_validPOCVSRepository( false )
+ , m_validPOTCVSRepository( false )
+ , m_validPOSVNRepository( false )
+ , m_validPOTSVNRepository( false )
+ , markPatternDialog(0)
+ , _validateDialog(0)
+ , _validateOptions(0)
+ , _validateOptionsDlg(0)
+ , _markAsFuzzy(false)
+ , _ignoreFuzzy(false)
+ , _project(project)
+{
+ _dirList.resize(200);
+ _fileList.resize(500);
+ _readInfoFileList.clear();
+
+ _pendingProcesses.setAutoDelete(true);
+
+ setSelectionMode(Single);
+
+ _dictBox = new KBabelDictBox(this, "dictbox");
+ _dictBox->hide();
+
+ _updateTimer = new QTimer(this);
+ connect(_updateTimer,SIGNAL(timeout()),this,SLOT(checkUpdate()));
+
+ addColumn(COLTEXT(COL_NAME));
+ addColumn(COLTEXT(COL_MARKER),25);
+ setColumnAlignment(1,AlignCenter);
+ addColumn(COLTEXT(COL_FUZZY));
+ setColumnAlignment(1,AlignCenter);
+ addColumn(COLTEXT(COL_UNTRANS));
+ setColumnAlignment(2,AlignCenter);
+ addColumn(COLTEXT(COL_TOTAL));
+ setColumnAlignment(3,AlignCenter);
+ addColumn(QString::null); // CVS/SVN column, header is set later
+ addColumn(COLTEXT(COL_REVISION));
+ addColumn(COLTEXT(COL_TRANSLATOR));
+
+
+ header()->setMovingEnabled(false);
+ setAllColumnsShowFocus(true);
+ setSorting(0);
+
+ if(KContextMenuManager::showOnButtonPress())
+ {
+ connect(this,SIGNAL(rightButtonPressed(QListViewItem*,const QPoint &, int))
+ ,this, SLOT(showContentsMenu(QListViewItem*,const QPoint &, int)));
+ }
+ else
+ {
+ connect(this,SIGNAL(rightButtonClicked(QListViewItem*,const QPoint &, int))
+ ,this, SLOT(showContentsMenu(QListViewItem*,const QPoint &, int)));
+ }
+ connect(this, SIGNAL(returnPressed(QListViewItem*))
+ ,this, SLOT(activateItem(QListViewItem*)));
+ connect(this, SIGNAL(doubleClicked(QListViewItem*))
+ ,this, SLOT(activateItem(QListViewItem*)));
+ connect(this,SIGNAL(selectionChanged()),this,SLOT(checkSelected()));
+ connect( this, SIGNAL( clicked(QListViewItem *, const QPoint &, int)),
+ this, SLOT( columnClicked(QListViewItem *, const QPoint &, int)));
+
+ _dirCommandsMenu = 0;
+ _fileCommandsMenu = 0;
+ _dirContentsMenu = 0;
+ _fileContentsMenu = 0;
+
+ _logWindow = new KDialogBase(0,"log window",false,i18n("Log Window")
+ ,KDialogBase::Close | KDialogBase::User1,KDialogBase::Close);
+ _logWindow->setButtonText(KDialogBase::User1,i18n("C&lear"));
+ _logWindow->setInitialSize(QSize(300,200));
+
+ QWhatsThis::add(_logWindow,i18n("<qt><p><b>Log window</b></p>\n"
+ "<p>In this window the output of "
+ "the executed commands are shown.</p></qt>"));
+
+ _logView = new QTextEdit(_logWindow);
+ _logView->setReadOnly(true);
+
+ _logWindow->setMainWidget(_logView);
+
+ connect(_logWindow,SIGNAL(user1Clicked()),_logView,SLOT(clear()));
+
+ QWhatsThis::add(this,i18n("<qt><p><b>Catalog Manager</b></p>\n"
+"<p>The Catalog Manager merges two folders into one tree and displays all\n"
+"PO and POT files in these folders. This way you can easily see if a\n"
+"template has been added or removed. Also some information about the files\n"
+"is displayed.</p>"
+"<p>For more information see section <b>The Catalog Manager</b>"
+" in the online help.</p></qt>"));
+
+ setAcceptDrops(true); // just to get the drag displayed immediately
+
+ mailer = new KBabelMailer( this, _project );
+
+ // CVS
+ cvshandler = new CVSHandler( );
+ connect( cvshandler, SIGNAL( signalIsPORepository( bool ) ),
+ this, SLOT( slotValidPOCVSRepository( bool ) ) );
+ connect( cvshandler, SIGNAL( signalIsPOTRepository( bool ) ),
+ this, SLOT( slotValidPOTCVSRepository( bool ) ) );
+ connect( cvshandler, SIGNAL( signalFilesCommitted( const QStringList& ) ),
+ this, SLOT( updateFiles( const QStringList& ) ) );
+
+ // SVN
+ svnhandler = new SVNHandler( );
+ connect( svnhandler, SIGNAL( signalIsPORepository( bool ) ),
+ this, SLOT( slotValidPOSVNRepository( bool ) ) );
+ connect( svnhandler, SIGNAL( signalIsPOTRepository( bool ) ),
+ this, SLOT( slotValidPOTSVNRepository( bool ) ) );
+ connect( svnhandler, SIGNAL( signalFilesCommitted( const QStringList& ) ),
+ this, SLOT( updateFiles( const QStringList& ) ) );
+
+ KConfig *config = KGlobal::config();
+ restoreView(config);
+
+ _dictBox->readSettings(_project->config());
+}
+
+CatalogManagerView::~CatalogManagerView()
+{
+ if(_active)
+ stop();
+
+ if(_dirWatch)
+ delete _dirWatch;
+
+ if(_settings.killCmdOnExit)
+ {
+ KProcess* proc;
+ for ( proc=_pendingProcesses.first(); proc != 0; proc=_pendingProcesses.next() )
+ {
+ proc->kill(SIGKILL);
+ }
+ }
+
+ delete _logWindow;
+ delete mailer;
+ delete cvshandler;
+ delete svnhandler;
+ if (markPatternDialog) delete markPatternDialog;
+}
+
+
+void CatalogManagerView::saveView( KConfig *config) const
+{
+ saveMarker(config);
+
+ KConfigGroupSaver( config, "CatalogManager" );
+
+ config->writeEntry( "ValidateMarkAsFuzzy", _markAsFuzzy );
+ config->writeEntry( "ValidateIgnoreFuzzy", _ignoreFuzzy );
+}
+
+
+void CatalogManagerView::restoreView( KConfig *config)
+{
+ readMarker(config);
+
+ _markAsFuzzy = config->readBoolEntry( "ValidateMarkAsFuzzy", false );
+ _ignoreFuzzy = config->readBoolEntry( "ValidateIgnoreFuzzy", false );
+}
+
+void CatalogManagerView::setRMBMenuFile( QPopupMenu *m )
+{
+ _fileContentsMenu = m;
+}
+
+void CatalogManagerView::setRMBMenuDir( QPopupMenu *m )
+{
+ _dirContentsMenu = m;
+}
+
+void CatalogManagerView::setDirCommandsMenu( QPopupMenu *m )
+{
+ _dirCommandsMenu = m;
+ connect(_dirCommandsMenu,SIGNAL(activated(int)),this,SLOT(slotDirCommand(int)));
+}
+
+void CatalogManagerView::setFileCommandsMenu( QPopupMenu *m )
+{
+ _fileCommandsMenu = m;
+ connect(_fileCommandsMenu,SIGNAL(activated(int)),this,SLOT(slotFileCommand(int)));
+}
+
+void CatalogManagerView::checkUpdate()
+{
+ _updateNesting++;
+ pause(true);
+
+ QDictIterator<CatManListItem> it( _fileList ); // iterator for dict
+
+ while ( it.current() && !_stop)
+ {
+ CatManListItem* item=it.current();
+
+ item->checkUpdate();
+ ++it;
+ }
+
+ pause(false);
+ --_updateNesting;
+ if( _updateNesting == 0 )
+ {
+ emit updateFinished();
+ }
+}
+
+
+
+void CatalogManagerView::pause(bool flag)
+{
+ if(flag)
+ {
+ _updateTimer->stop();
+ }
+ else
+ {
+ _updateTimer->start(10000);
+ }
+}
+
+
+void CatalogManagerView::stop(bool s)
+{
+ kdDebug(KBABEL_CATMAN) << "Stopping " << s << endl;
+ pause(s);
+ _stop=s;
+ PoInfo::stopStaticRead = true;
+}
+
+void CatalogManagerView::stopSearch()
+{
+ _stopSearch = true;
+}
+
+void CatalogManagerView::clear()
+{
+ pause(true);
+
+ // first clear up
+ if(_dirWatch)
+ delete _dirWatch;
+
+ _dirWatch= new KDirWatch();
+ connect(_dirWatch,SIGNAL(deleted(const QString&)),this
+ ,SLOT(directoryDeleted(const QString&)));
+ connect(_dirWatch,SIGNAL(dirty(const QString&)),this
+ ,SLOT(directoryChanged(const QString&)));
+ connect(_dirWatch,SIGNAL(created(const QString&)),this
+ ,SLOT(directoryChanged(const QString&)));
+
+ _dirList.clear();
+ _fileList.clear();
+
+ QListView::clear();
+}
+
+void CatalogManagerView::toggleAllMarks()
+{
+ _markerList.clear();
+
+ QListViewItemIterator it( this );
+ CatManListItem* item;
+
+ for ( ; it.current(); ++it )
+ {
+ item = (CatManListItem*) it.current();
+ if(item->isFile())
+ {
+ bool wasMarked=item->marked();
+ item->setMarked(!wasMarked);
+ if(!wasMarked)
+ {
+ _markerList.append(item->package());
+ }
+ else
+ {
+ _markerList.remove(item->package());
+ }
+ }
+ }
+
+ checkSelected();
+}
+
+void CatalogManagerView::clearAllMarks()
+{
+ _markerList.clear();
+ QDictIterator<CatManListItem> it( _fileList ); // iterator for dict
+
+ while ( it.current() )
+ {
+ CatManListItem* item=it.current();
+
+ if(item->marked())
+ _markerList.remove(item->package());
+
+ item->setMarked(false);
+ ++it;
+ }
+
+ checkSelected();
+}
+
+void CatalogManagerView::markModifiedFiles()
+{
+ QDictIterator<CatManListItem> it( _fileList );
+ while ( it.current() )
+ {
+ CatManListItem* item=it.current();
+ /*if(item->marked())
+ _markerList.remove(item->package());
+ */
+ if(item->isModified() && ! item->marked() ) {
+ item->setMarked(true);
+ _markerList.append(item->package( ));
+ }
+ ++it;
+ }
+
+ checkSelected();
+}
+
+void CatalogManagerView::loadMarks()
+{
+ const KURL url = KFileDialog::getOpenURL( QString(),"*.marklist", this );
+ if( url.isEmpty() ) return;
+
+ QString filename;
+#if KDE_IS_VERSION( 3, 2, 90 )
+ if (!KIO::NetAccess::download( url, filename, this ) )
+#else
+ if( !KIO::NetAccess::download( url, filename ) )
+#endif
+ {
+ KMessageBox::error(this,i18n(
+ "Error while trying to open file:\n %1").arg(url.prettyURL()));
+ return;
+ }
+
+ // now load from file
+ QStringList newMarkerList; // better create new list in case of problems
+ QFile f( filename );
+ if( f.open( IO_ReadOnly) )
+ {
+ QTextStream s(&f);
+
+ QString input;
+
+ s >> input ;
+ if( input == "[Markers]" )
+ {
+ while( !s.atEnd() )
+ {
+ s >> input;
+ newMarkerList.append(input);
+ }
+ }
+ else
+ {
+ KMessageBox::error(this
+ ,i18n("Error while trying to read file:\n %1\n"
+ "Maybe it is not a valid file with list of markings.").arg(url.prettyURL()));
+ f.close();
+ return;
+ }
+ f.close();
+ }
+ else
+ {
+ KMessageBox::error(this,i18n(
+ "Error while trying to open file:\n %1").arg(url.prettyURL()));
+ }
+
+ KIO::NetAccess::removeTempFile( filename );
+
+ // test validity of list items
+ QStringList testedList;
+ QStringList::const_iterator it;
+ for( it=newMarkerList.constBegin() ; it!=newMarkerList.constEnd() ; ++it )
+ if( _fileList[(*it)] != 0 ) testedList.append( (*it) );
+
+ // apply new list
+ for( it=_markerList.constBegin() ; it!=_markerList.constEnd() ; ++it )
+ {
+ CatManListItem* item = _fileList[(*it)];
+ if( item ) item->setMarked(false);
+ }
+
+ _markerList = testedList;
+ for( it=_markerList.constBegin() ; it!=_markerList.constEnd() ; ++it )
+ {
+ CatManListItem* item = _fileList[(*it)];
+ if( item ) item->setMarked(true);
+ }
+
+ checkSelected();
+}
+
+void CatalogManagerView::saveMarks()
+{
+ const KURL url2 = KFileDialog::getSaveURL( QString(), "*.marklist", this );
+ if( url2.isEmpty() ) return;
+
+ // ### FIXME: why is the file dialog not doing this?
+ if ( KIO::NetAccess::exists( url2, false, this ) )
+ {
+ if(KMessageBox::warningContinueCancel(this,QString("<qt>%1</qt>").arg(i18n("The file %1 already exists. "
+ "Do you want to overwrite it?").arg(url2.prettyURL())),i18n("Warning"),i18n("&Overwrite"))==KMessageBox::Cancel)
+ {
+ return;
+ }
+ }
+
+#if KDE_IS_VERSION( 3, 4, 92 )
+ // Support for partially remote KIO slave like media:
+ const KURL url ( KIO::NetAccess::mostLocalURL( url2, this ) );
+#else
+ const KURL url ( url2 );
+#endif
+ kdDebug() << "Saving marks: " << url2.prettyURL() << " most-local: " << url.prettyURL() << endl;
+
+ QFile* file = 0;
+ KTempFile* tempFile = 0;
+ QTextStream* stream = 0;
+ bool error = false;
+
+ const bool localFile = url.isLocalFile();
+ if ( localFile )
+ {
+ // We have a local file
+ file = new QFile( url.path() );
+ if ( file->open (IO_WriteOnly) )
+ {
+ stream = new QTextStream( file );
+ }
+ else
+ {
+ error = true;
+ }
+ }
+ else
+ {
+ tempFile = new KTempFile();
+ tempFile->setAutoDelete(true);
+ stream = tempFile->textStream();
+ error = !stream;
+ }
+ if ( !error )
+ {
+ // ### TODO: try to get a better file format for KDE4 (XML?), one working with real relative paths (no / at start) and working with UTF-8
+ *stream << "[Markers]" << endl;
+ for( QStringList::const_iterator it = _markerList.constBegin(); it!=_markerList.constEnd() ; ++it )
+ *stream << (*it) << endl;
+ }
+ if ( error )
+ {
+ // ### KDE4 FIXME: strip the final \n of the message
+ KMessageBox::error( this,
+ i18n( "An error occurred while trying to write to file:\n%1\n" ).arg( url.prettyURL()) );
+ }
+ else if ( !localFile )
+ {
+ tempFile->close();
+ if( !KIO::NetAccess::upload( tempFile->name(), url, this ) )
+ {
+ // ### KDE4 FIXME: strip the final \n of the message
+ KMessageBox::error(this,
+ i18n("An error occurred while trying to upload the file:\n%1\n").arg(url.prettyURL()));
+ }
+ }
+
+ // We have finished so clean up
+ if ( localFile )
+ {
+ delete stream;
+ file->close();
+ delete file;
+ }
+ else
+ {
+ delete tempFile;
+ }
+
+ checkSelected();
+}
+
+void CatalogManagerView::slotMarkPattern( )
+{
+ setPatternMarks(true);
+}
+
+void CatalogManagerView::slotUnmarkPattern( )
+{
+ setPatternMarks(false);
+}
+
+void CatalogManagerView::setPatternMarks(bool mark)
+{
+ CatManListItem * item = (CatManListItem*)currentItem( );
+ if (!item)
+ item = (CatManListItem*)_dirList["/"];
+ if (!item->isDir( ))
+ return;
+
+ if (!markPatternDialog)
+ markPatternDialog = new MarkPatternDialog(this);
+
+ markPatternDialog->setMode(mark);
+
+ if (markPatternDialog->exec( ) != KDialog::Accepted)
+ return;
+
+ QRegExp rx(markPatternDialog->pattern( ));
+ rx.setWildcard(!markPatternDialog->useRegExp( ));
+ rx.setCaseSensitive(markPatternDialog->isCaseSensitive( ));
+
+ QStringList fileList = item->allChildrenList(true);
+ for (QStringList::const_iterator it = fileList.constBegin( ); it != fileList.constEnd( ); ++it) {
+ CatManListItem * i = _fileList[*it];
+
+ QString matchName;
+ if (i->hasPo( ))
+ matchName = i->poFile( );
+ else if (i->hasPot( ) && markPatternDialog->includeTemplates( ))
+ matchName = i->potFile( );
+ matchName = QFileInfo(matchName).baseName( );
+
+ if (mark) {
+ if (!matchName.isEmpty( ) && rx.exactMatch(matchName) && !i->marked( )) {
+ i->setMarked(true);
+ _markerList.append(i->package( ));
+ }
+ } else {
+ if (!matchName.isEmpty( ) && rx.exactMatch(matchName) && i->marked( )) {
+ i->setMarked(false);
+ _markerList.remove(i->package( ));
+ }
+ }
+ }
+}
+
+void CatalogManagerView::statistics()
+{
+ CatManListItem* i=(CatManListItem*) currentItem();
+
+ if(!i)
+ i=(CatManListItem*)_dirList["/"];
+
+ if(isActive() && i->isDir())
+ {
+ if(KMessageBox::warningContinueCancel(this
+ ,i18n("The Catalog Manager is still updating information about the files.\n"
+"If you continue, it will try to update all necessary files, however this can take "
+"a long time and may lead to wrong results. Please wait until all files are updated."),i18n("Warning")
+ ,KStdGuiItem::cont()) == KMessageBox::Cancel)
+ {
+ return;
+ }
+ }
+
+ QStringList doList;
+
+ if( i->isFile() ) doList.append(i->package());
+ else doList = i->allChildrenList(true);
+
+ showStatistics( i, doList );
+}
+
+void CatalogManagerView::markedStatistics()
+{
+ CatManListItem* i=(CatManListItem*) currentItem();
+
+ if(!i)
+ i=(CatManListItem*)_dirList["/"];
+
+ if(isActive() && i->isDir())
+ {
+ if(KMessageBox::warningContinueCancel(this
+ ,i18n("The Catalog Manager is still updating information about the files.\n"
+"If you continue, it will try to update all necessary files, however this can take "
+"a long time and may lead to wrong results. Please wait until all files are updated."),i18n("Warning")
+ ,KStdGuiItem::cont()) == KMessageBox::Cancel)
+ {
+ return;
+ }
+ }
+
+ QStringList doList;
+
+ if( i->isFile() ) doList.append(i->package());
+ else doList = i->allChildrenList(true);
+
+ QStringList markedDoList;
+ QStringList::const_iterator it;
+ for( it = doList.constBegin(); it != doList.constEnd(); ++it )
+ {
+ CatManListItem* item = _fileList[(*it)];
+ if( item->marked() ) markedDoList.append(item->package());
+ }
+
+ showStatistics( i, markedDoList );
+}
+
+void CatalogManagerView::showStatistics( CatManListItem *i, QStringList &childrenList )
+{
+ KLocale *locale = KGlobal::locale();
+
+ QString msg;
+ int totalPackages=0;
+ int totalPo=0;
+ int totalNoPot=0;
+ int needworkPo=0;
+ int totalMsgid=0;
+ int totalFuzzy=0;
+ int totalUntranslated=0;
+
+ QStringList::const_iterator it;
+ for( it = childrenList.constBegin(); it != childrenList.constEnd(); ++it )
+ {
+ CatManListItem* item = _fileList[(*it)];
+
+ /*
+ KASSERT1(item,KDEBUG_FATAL,KBABEL_CATMAN,"CatalogManagerView::statistics: item not in list %s"
+ ,(*it).ascii());
+ */
+ // be sure, that the information is updated
+ _updateNesting++;
+ item->checkUpdate();
+ _updateNesting--;
+ if( _stop ) return;
+
+ totalPackages++;
+
+ int fuzzy=item->fuzzy();
+ int total=item->total();
+ int untrans=item->untranslated();
+
+ if(item->hasPo())
+ totalPo++;
+
+ if(!item->hasPot())
+ totalNoPot++;
+
+
+ if(fuzzy || untrans)
+ needworkPo++;
+
+ totalMsgid+=total;
+ totalFuzzy+=fuzzy;
+ totalUntranslated+=untrans;
+ }
+
+ double percent;
+
+ const QString name=i->package(false);
+ if(name.isEmpty())
+ msg = i18n("Statistics for all:\n");
+ else
+ msg = i18n("Statistics for %1:\n").arg(name);
+
+ msg+=i18n("Number of packages: %1\n").arg(locale->formatNumber(totalPackages, 0));
+
+ percent=100.0-((double)needworkPo*100.0)/totalPackages;
+ msg+=i18n("Complete translated: %1 % (%2)\n").arg(locale->formatNumber(percent,2)).arg(locale->formatNumber(totalPackages-needworkPo, 0));
+
+ percent=100.0-((double)totalPo*100.0)/totalPackages;
+ msg+=i18n("Only template available: %1 % (%2)\n").arg(locale->formatNumber(percent,2)).arg(locale->formatNumber(totalPackages-totalPo,0));
+ percent=((double)totalNoPot*100.0)/totalPackages;
+ msg+=i18n("Only PO file available: %1 % (%2)\n").arg(locale->formatNumber(percent,02)).arg(locale->formatNumber(totalNoPot, 0));
+
+ msg+=i18n("Number of messages: %1\n").arg(locale->formatNumber(totalMsgid, 0));
+
+ long int totalTranslated = totalMsgid - totalFuzzy - totalUntranslated;
+ percent=((double)totalTranslated*100.0)/totalMsgid;
+ msg+=i18n("Translated: %1 % (%2)\n").arg(locale->formatNumber(percent,2)).arg(locale->formatNumber(totalTranslated, 0));
+
+ percent=((double)totalFuzzy*100.0)/totalMsgid;
+ msg+=i18n("Fuzzy: %1 % (%2)\n").arg(locale->formatNumber(percent,2)).arg(locale->formatNumber(totalFuzzy, 0));
+
+ percent=((double)totalUntranslated*100.0)/totalMsgid;
+ msg+=i18n("Untranslated: %1 % (%2)\n").arg(locale->formatNumber(percent,2)).arg(locale->formatNumber(totalUntranslated, 0));
+
+ KMessageBox::information(this,msg,i18n("Statistics"));
+}
+
+void CatalogManagerView::checkSyntax()
+{
+ CatManListItem* item=(CatManListItem*) currentItem();
+
+ if(!item)
+ item=(CatManListItem*) _dirList["/"];
+
+ if(item->isFile())
+ {
+ if(!item->hasPo())
+ return;
+
+ Msgfmt::Status status;
+ QString output;
+ Msgfmt msgfmt;
+
+ status=msgfmt.checkSyntax(item->poFile(),output);
+
+ switch(status)
+ {
+ case Msgfmt::Ok:
+ {
+ KMessageBox::information(this,i18n("The file is syntactically correct.\nOutput of \"msgfmt --statistics\":")+"\n"+output);
+ break;
+ }
+ case Msgfmt::SyntaxError:
+ {
+ KMessageBox::information(this,i18n("The file has syntax errors.\nOutput of \"msgfmt --statistics\":")+"\n"+output);
+ break;
+ }
+ case Msgfmt::HeaderError:
+ {
+ KMessageBox::information(this,i18n("The file has header syntax error.\nOutput of \"msgfmt --statistics\":")+"\n"+output);
+ break;
+ }
+ case Msgfmt::Error:
+ {
+ KMessageBox::error(this,i18n("An error occurred while processing \"msgfmt --statistics\""));
+ break;
+ }
+ case Msgfmt::NoExecutable:
+ {
+ KMessageBox::sorry(this,i18n("Cannot execute msgfmt. Please make sure that you have msgfmt in your PATH."));
+ break;
+ }
+ case Msgfmt::Unsupported:
+ {
+ KMessageBox::sorry(this,i18n("You can use gettext tools only for checking PO files."));
+ break;
+ }
+ }
+
+ }
+ else
+ {
+ Msgfmt::Status status;
+ QString output;
+ Msgfmt msgfmt;
+
+ status=msgfmt.checkSyntaxInDir(item->poFile(), "*.po", output);
+
+ QString name=item->package(false);
+
+ switch(status)
+ {
+ case Msgfmt::Ok:
+ {
+ QString msg;
+ if(!name.isEmpty())
+ {
+ msg=i18n("All files in folder %1 are syntactically correct.\n"
+"Output of \"msgfmt --statistics\":\n").arg(name)+output;
+ }
+ else
+ {
+ msg=i18n("All files in the base folder are syntactically correct.\n"
+"Output of \"msgfmt --statistics\":\n")+output;
+ }
+ KMessageBox::information(this,msg);
+ break;
+ }
+ case Msgfmt::SyntaxError:
+ {
+ QString msg;
+ if(!name.isEmpty())
+ {
+ msg=i18n("At least one file in folder %1 has syntax errors.\n"
+"Output of \"msgfmt --statistics\":\n").arg(name)+output;
+ }
+ else
+ {
+ msg=i18n("At least one file in the base folder has syntax errors.\n"
+"Output of \"msgfmt --statistics\":\n")+output;
+ }
+ KMessageBox::information(this,msg);
+ break;
+ }
+ case Msgfmt::HeaderError:
+ {
+ QString msg;
+ if(!name.isEmpty())
+ {
+ msg=i18n("At least one file in folder %1 has header syntax errors.\n"
+"Output of \"msgfmt --statistics\":\n").arg(name)+output;
+ }
+ else
+ {
+ msg=i18n("At least one file in the base folder has header syntax errors.\n"
+"Output of \"msgfmt --statistics\":\n")+output;
+ }
+ KMessageBox::information(this,msg);
+ break;
+ }
+ case Msgfmt::Error:
+ {
+ QString msg;
+ if(!name.isEmpty())
+ {
+ msg=i18n("An error occurred while processing \"msgfmt --statistics *.po\" "
+"in folder %1").arg(name);
+ }
+ else
+ {
+ msg=i18n("An error occurred while processing \"msgfmt --statistics *.po\" "
+"in the base folder");
+ }
+ KMessageBox::error(this,msg);
+ break;
+ }
+ case Msgfmt::NoExecutable:
+ {
+ KMessageBox::sorry(this,i18n("Cannot execute msgfmt. Please make sure that you have msgfmt in your PATH."));
+ break;
+ }
+ case Msgfmt::Unsupported:
+ {
+ KMessageBox::sorry(this,i18n("You can use gettext tools only for checking PO files."));
+ break;
+ }
+ }
+ }
+}
+
+void CatalogManagerView::roughTranslation()
+{
+ QPtrList<CatManListItem> result;
+ CatManListItem *current = static_cast<CatManListItem *>(currentItem());
+ if( current->isDir() )
+ {
+ QStringList s = current->allChildrenList(true);
+ QStringList::const_iterator it;
+ for( it = s.constBegin() ; it != s.constEnd(); ++it )
+ {
+ CatManListItem *item = _fileList[(*it)];
+ if( item ) result.append( item );
+ }
+ }
+ else
+ {
+ result.append( current );
+ }
+
+ MultiRoughTransDlg* dialog=new MultiRoughTransDlg( _dictBox, result, this );
+ dialog->exec();
+ delete dialog;
+}
+
+void CatalogManagerView::markedRoughTranslation()
+{
+ if( _markerList.count() == 0 ) return;
+
+ QPtrList<CatManListItem> result;
+
+ QStringList::const_iterator it;
+ for( it = _markerList.constBegin() ; it != _markerList.constEnd(); ++it )
+ {
+ CatManListItem *item = _fileList[(*it)];
+ result.append( item );
+ }
+
+ MultiRoughTransDlg* dialog=new MultiRoughTransDlg( _dictBox, result, this );
+ dialog->exec();
+ delete dialog;
+}
+
+void CatalogManagerView::mailFiles()
+{
+ CatManListItem* item = (CatManListItem*)currentItem();
+ if(item->isDir()) {
+ QStringList filesToSend;
+ QStringList childrenList = item->allChildrenList(true);
+
+ QStringList::const_iterator it;
+ for (it = childrenList.constBegin(); it != childrenList.constEnd(); ++it) {
+ CatManListItem* i = _fileList[(*it)];
+ if (i->hasPo()) {
+ filesToSend << i->poFile();
+ }
+ }
+ mailer->sendFiles(filesToSend, item->text(0));
+ } else {
+ if (item->hasPo()) {
+ mailer->sendOneFile(item->poFile());
+ }
+ }
+}
+
+void CatalogManagerView::mailMarkedFiles()
+{
+ if (_markerList.count() == 0)
+ return;
+
+ QStringList filesToSend;
+ QStringList::const_iterator it;
+ for (it = _markerList.constBegin(); it != _markerList.constEnd(); ++it) {
+ CatManListItem* i = _fileList[(*it)];
+ if (i->hasPo()) {
+ filesToSend << i->poFile();
+ }
+ }
+ mailer->sendFiles(filesToSend);
+}
+
+void CatalogManagerView::packageFiles( )
+{
+ CatManListItem* item = (CatManListItem*)currentItem();
+ if(item->isDir()) {
+ QStringList filesToPackage;
+ QStringList childrenList = item->allChildrenList(true);
+
+ QStringList::const_iterator it;
+ for (it = childrenList.constBegin(); it != childrenList.constEnd(); ++it) {
+ CatManListItem* i = _fileList[(*it)];
+ if (i->hasPo()) {
+ filesToPackage << i->poFile();
+ }
+ }
+ QString packageFileName = KFileDialog::getSaveFileName(QString::null,"*.tar.bz2\n*.tar.gz",this);
+ mailer->buildArchive( filesToPackage, packageFileName, QString::null, false );
+ }
+ else {
+ if (item->hasPo()) {
+ QStringList fileToPackage(item->poFile());
+ QString packageFileName = KFileDialog::getSaveFileName(QString::null,"*.tar.bz2\n*.tar.gz",this);
+ mailer->buildArchive( fileToPackage, packageFileName, QString::null, false );
+ }
+ }
+}
+void CatalogManagerView::packageMarkedFiles( )
+{
+ if (_markerList.count() == 0)
+ return;
+
+ QStringList filesToPackage;
+ QStringList::const_iterator it;
+ for (it = _markerList.constBegin(); it != _markerList.constEnd(); ++it) {
+ CatManListItem* i = _fileList[(*it)];
+ if (i->hasPo()) {
+ filesToPackage << i->poFile();
+ }
+ }
+
+ QString packageFileName = KFileDialog::getSaveFileName(QString::null,"*.tar.bz2\n*.tar.gz",this);
+ mailer->buildArchive( filesToPackage, packageFileName, QString::null, false );
+}
+
+// CVS
+void CatalogManagerView::cvsUpdate( )
+{
+ doCVSCommand( CVS::Update );
+}
+
+void CatalogManagerView::cvsUpdateMarked( )
+{
+ doCVSCommand( CVS::Update, true );
+}
+
+void CatalogManagerView::cvsCommit( )
+{
+ doCVSCommand( CVS::Commit );
+}
+
+void CatalogManagerView::cvsCommitMarked( )
+{
+ doCVSCommand( CVS::Commit, true );
+}
+
+void CatalogManagerView::cvsStatus( )
+{
+ doCVSCommand( CVS::Status );
+}
+
+void CatalogManagerView::cvsStatusMarked( )
+{
+ doCVSCommand( CVS::Status, true );
+}
+
+void CatalogManagerView::cvsUpdateTemplate( )
+{
+ doCVSCommand( CVS::Update, false, true );
+}
+
+void CatalogManagerView::cvsUpdateMarkedTemplate( )
+{
+ doCVSCommand( CVS::Update, true, true );
+}
+
+void CatalogManagerView::cvsCommitTemplate( )
+{
+ doCVSCommand( CVS::Commit, false, true );
+}
+
+void CatalogManagerView::cvsCommitMarkedTemplate( )
+{
+ doCVSCommand( CVS::Commit, true, true );
+}
+
+void CatalogManagerView::cvsDiff( )
+{
+ doCVSCommand( CVS::Diff, false, false );
+}
+
+void CatalogManagerView::doCVSCommand( CVS::Command cmd, bool marked, bool templates )
+{
+ KSharedConfig* config = _project->sharedConfig();
+ if ( marked ) {
+ if ( _markerList.isEmpty() ) return;
+ QStringList fileList;
+ QStringList::const_iterator it;
+ for ( it = _markerList.constBegin( ); it != _markerList.constEnd( ); ++it ) {
+ CatManListItem * i = _fileList[(*it)];
+ if ( templates && i->hasPot( ) )
+ fileList << i->potFile( );
+ else if ( !templates && i->hasPo( ) )
+ fileList << i->poFile( );
+ }
+ cvshandler->execCVSCommand( this, cmd, fileList, templates, config );
+ } else {
+ const QString basedir = ( templates ? _settings.potBaseDir : _settings.poBaseDir );
+ QString cvsItem;
+ CatManListItem * item = (CatManListItem*)currentItem( );
+ if ( ( cmd == CVS::Commit || cmd == CVS::Diff ) && item->isDir( ) ) {
+ // all children including directories
+ QStringList cvsItems = item->allChildrenFileList (true, false, true);
+ if ( !cvsItems.isEmpty( ) )
+ cvshandler->execCVSCommand( this, cmd, cvsItems, templates, config );
+ } else {
+ if ( templates && item->hasPot( ) )
+ cvsItem = item->potFile( );
+ else if ( !templates && item->hasPo( ) )
+ cvsItem = item->poFile( );
+
+ if ( !cvsItem.isEmpty( ) )
+ cvshandler->execCVSCommand( this, cmd, cvsItem, templates, config );
+ }
+ }
+}
+
+//SVN
+void CatalogManagerView::svnUpdate( )
+{
+ doSVNCommand( SVN::Update );
+}
+
+void CatalogManagerView::svnUpdateMarked( )
+{
+ doSVNCommand( SVN::Update, true );
+}
+
+void CatalogManagerView::svnCommit( )
+{
+ doSVNCommand( SVN::Commit );
+}
+
+void CatalogManagerView::svnCommitMarked( )
+{
+ doSVNCommand( SVN::Commit, true );
+}
+
+void CatalogManagerView::svnStatusRemote( )
+{
+ doSVNCommand( SVN::StatusRemote );
+}
+
+void CatalogManagerView::svnStatusRemoteMarked( )
+{
+ doSVNCommand( SVN::StatusRemote, true );
+}
+
+void CatalogManagerView::svnStatusLocal( )
+{
+ doSVNCommand( SVN::StatusLocal );
+}
+
+void CatalogManagerView::svnStatusLocalMarked( )
+{
+ doSVNCommand( SVN::StatusLocal, true );
+}
+
+void CatalogManagerView::svnInfo()
+{
+ doSVNCommand( SVN::Info );
+}
+
+void CatalogManagerView::svnInfoMarked()
+{
+ doSVNCommand( SVN::Info, true );
+}
+
+void CatalogManagerView::svnUpdateTemplate( )
+{
+ doSVNCommand( SVN::Update, false, true );
+}
+
+void CatalogManagerView::svnUpdateMarkedTemplate( )
+{
+ doSVNCommand( SVN::Update, true, true );
+}
+
+void CatalogManagerView::svnCommitTemplate( )
+{
+ doSVNCommand( SVN::Commit, false, true );
+}
+
+void CatalogManagerView::svnCommitMarkedTemplate( )
+{
+ doSVNCommand( SVN::Commit, true, true );
+}
+
+void CatalogManagerView::svnDiff( )
+{
+ doSVNCommand( SVN::Diff, false, false );
+}
+
+void CatalogManagerView::doSVNCommand( SVN::Command cmd, bool marked, bool templates )
+{
+ KSharedConfig* config = _project->sharedConfig();
+ if ( marked ) {
+ if ( _markerList.isEmpty() ) return;
+ QStringList fileList;
+ QStringList::const_iterator it;
+ for ( it = _markerList.constBegin( ); it != _markerList.constEnd( ); ++it ) {
+ CatManListItem * i = _fileList[(*it)];
+ if ( templates && i->hasPot( ) )
+ fileList << i->potFile( );
+ else if ( !templates && i->hasPo( ) )
+ fileList << i->poFile( );
+ }
+ svnhandler->execSVNCommand( this, cmd, fileList, templates, config );
+ } else {
+ const QString basedir = ( templates ? _settings.potBaseDir : _settings.poBaseDir );
+ QString svnItem;
+ CatManListItem * item = (CatManListItem*)currentItem( );
+ if ( ( cmd == SVN::Commit || cmd == SVN::Diff ) && item->isDir( ) ) {
+ // all children including directories
+ QStringList svnItems = item->allChildrenFileList (true, false, true);
+ if ( !svnItems.isEmpty( ) )
+ svnhandler->execSVNCommand( this, cmd, svnItems, templates, config );
+ } else {
+ if ( templates && item->hasPot( ) )
+ svnItem = item->potFile( );
+ else if ( !templates && item->hasPo( ) )
+ svnItem = item->poFile( );
+
+ if ( !svnItem.isEmpty( ) )
+ svnhandler->execSVNCommand( this, cmd, svnItem, templates, config );
+ }
+ }
+}
+
+void CatalogManagerView::showLog()
+{
+ _logWindow->show();
+}
+
+QString CatalogManagerView::find( FindOptions &options, QStringList &rest )
+{
+ CatManListItem* i=(CatManListItem*) currentItem();
+
+ if(!i || options.inAllFiles)
+ i=(CatManListItem*)_dirList["/"];
+
+ QValueList<QString> foundFiles;
+ _stopSearch = false;
+
+ const QString search = options.findStr.lower().simplifyWhiteSpace();
+ QStringList searchWords = QStringList::split(' ', search);
+
+ QStringList childrenList;
+ if( i->isFile() ) childrenList.append(i->name());
+ else childrenList =i->allChildrenList(true);
+
+ emit prepareFindProgressBar(childrenList.size());
+
+ QStringList::const_iterator it;
+ for( it = childrenList.constBegin(); it != childrenList.constEnd(); ++it )
+ {
+ CatManListItem* item = _fileList[(*it)];
+
+ if( !item )
+ {
+ kdWarning(KBABEL_CATMAN) << "The file information not found, skipping" << endl;
+ continue;
+ }
+
+ // skip if not marked and we lookup in marked
+ if( options.inMarkedFiles && !item->marked() )
+ {
+ kdDebug(KBABEL_CATMAN) << "Skipping due marking " << item->name() << endl;
+ emit signalSearchedFile(1);
+ continue;
+ }
+
+ bool doSearch = options.isRegExp || options.inTemplates; // for regexp and templates we do not support index search
+ if( item->wordsUpdated() )
+ doSearch = doSearch || hasMatchingWords(item->wordList(), searchWords);
+ else doSearch = true; // we do not have index, we need to search
+ if( doSearch )
+ {
+ QString itemFile;
+ if( options.inTemplates )
+ {
+ if( item->hasPot() ) itemFile=item->potFile();
+ } else {
+ if( item->hasPo() ) itemFile=item->poFile();
+ }
+
+ if( itemFile.isNull() )
+ {
+ emit signalSearchedFile(1);
+ continue;
+ }
+
+ if( PoInfo::findInFile( itemFile , options ) )
+ {
+ emit signalSearchedFile(1);
+ rest.clear();
+ if( _stopSearch )
+ {
+ // if we are stopped, return what we found and clear the rest
+ _stopSearch = false;
+ return itemFile;
+ }
+ const QString foundItemFile = itemFile;
+
+ it++;
+ while( it != childrenList.constEnd() )
+ {
+ CatManListItem *item = _fileList[(*it)];
+
+ itemFile = QString::null;
+ if( options.inTemplates )
+ {
+ if( item->hasPot() ) itemFile=item->potFile();
+ } else {
+ if( item->hasPo() )itemFile=item->poFile();
+ }
+ if( options.inMarkedFiles && !item->marked() )
+ itemFile=QString::null;
+
+ if( !itemFile.isNull())
+ {
+ if( item->wordsUpdated() && !options.inTemplates )
+ {
+ if( options.isRegExp || hasMatchingWords(item->wordList(), searchWords) )
+ {
+ rest.append( itemFile );
+ }
+ else kdDebug(KBABEL_CATMAN) << "Don't try to lookup in " << itemFile << endl;
+ } else {
+ rest.append( itemFile ); // there is no word index, add the file
+ }
+ } else emit signalSearchedFile(1);
+
+ it++;
+ }
+ return foundItemFile;
+
+ }
+ } else kdDebug(KBABEL_CATMAN) << "Skipping " << item->poFile() << endl;
+ emit signalSearchedFile(1);
+ if( _stop || _stopSearch ) {
+ _stopSearch = false;
+ rest.clear();
+ if( _updateNesting == 0 && !_stop ) emit updateFinished();
+ return QString::null;
+ }
+ }
+ return QString::null;
+}
+
+bool CatalogManagerView::hasMatchingWords( QStringList &itemWords, QStringList &searchWords)
+{
+ for( QStringList::const_iterator it1 = searchWords.constBegin() ; it1 != searchWords.constEnd() ; ++it1 )
+ for( QStringList::const_iterator it2 = itemWords.constBegin() ; it2 != itemWords.constEnd() ; ++it2 )
+ if( *it1 == *it2
+ || (*it1).contains(*it2)
+ || (*it2).contains(*it1) ) return true;
+ return false;
+}
+
+void CatalogManagerView::showContentsMenu(QListViewItem *i, const QPoint &point, int)
+{
+ CatManListItem* item = (CatManListItem*) i;
+
+ if(!item)
+ return;
+
+ if(item->isDir())
+ {
+ _dirContentsMenu->exec(point);
+ }
+ else
+ {
+ _fileContentsMenu->exec(point);
+ }
+}
+
+void CatalogManagerView::checkSelected()
+{
+ CatManListItem* item=(CatManListItem*)selectedItem();
+ if(!item) return;
+
+ const uint actionValue =
+ NEEDS_PO * item->hasPo() + NEEDS_POT * item->hasPot() +
+ NEEDS_MARK * item->marked() + NEEDS_DIR * item->isDir() +
+ NEEDS_PO_CVS * m_validPOCVSRepository + NEEDS_POT_CVS * m_validPOTCVSRepository +
+ NEEDS_PO_SVN * m_validPOSVNRepository + NEEDS_POT_SVN * m_validPOTSVNRepository;
+
+ emit selectedChanged(actionValue);
+}
+
+void CatalogManagerView::activateItem(QListViewItem *)
+{
+ CatManListItem* item=(CatManListItem*) currentItem();
+
+ if(!item)
+ return;
+
+ if(item->isDir())
+ {
+ item->setOpen(!item->isOpen());
+ return;
+ }
+
+ if(item->hasPo())
+ {
+ emit openFile(item->poFile(),item->package());
+ }
+ else if(item->hasPot())
+ {
+ emit openTemplate(item->potFile(),item->poFile(),item->package());
+ }
+ else
+ {
+ kdError(KBABEL_CATMAN) << "CatalogManagerView::activateItem: item has no file?" << endl;
+ }
+
+}
+
+void CatalogManagerView::slotOpenFile()
+{
+ CatManListItem* item=(CatManListItem*) currentItem();
+
+ if(item && item->isFile())
+ {
+ activateItem(item);
+ }
+}
+
+void CatalogManagerView::slotOpenFileInNewWindow()
+{
+ CatManListItem* item=(CatManListItem*) currentItem();
+
+ if(item && item->isFile())
+ {
+ QString filename;
+ if(item->hasPo())
+ {
+ emit openFileInNewWindow(item->poFile(),item->package());
+ }
+ else if(item->hasPot())
+ {
+ emit openTemplateInNewWindow(item->potFile(),item->poFile(),item->package());
+ }
+ }
+}
+
+void CatalogManagerView::slotOpenTemplate()
+{
+ CatManListItem* item=(CatManListItem*) currentItem();
+
+ if(item && item->isFile())
+ {
+ emit openFile(item->potFile(),item->package());
+ }
+}
+
+void CatalogManagerView::slotDeleteFile()
+{
+ CatManListItem* item=(CatManListItem*) currentItem();
+
+ if(item && item->isFile() && item->hasPo() && !item->hasPot())
+ {
+ const QString msg=i18n("Do you really want to delete the file %1?").arg(item->poFile());
+ if(KMessageBox::warningContinueCancel(this,msg,i18n("Warning"),KGuiItem( i18n("Delete"), "editdelete"))== KMessageBox::Continue)
+ {
+ if(!QFile::remove(item->poFile()))
+ {
+ KMessageBox::sorry(this,i18n("Was not able to delete the file %1!").arg(item->poFile()));
+ }
+ }
+ }
+}
+
+void CatalogManagerView::toggleMark()
+{
+ CatManListItem* i = (CatManListItem*) currentItem();
+ if( i && i->isDir() ) slotToggleMarksInDir();
+ else slotToggleMark();
+}
+
+void CatalogManagerView::slotToggleMark()
+{
+ CatManListItem* item=(CatManListItem*) currentItem();
+
+ if(item && item->isFile())
+ {
+ bool wasMarked=item->marked();
+ item->setMarked(!wasMarked);
+
+ if(wasMarked)
+ {
+ _markerList.remove(item->package());
+ }
+ else
+ {
+ _markerList.append(item->package());
+ }
+ }
+
+ checkSelected();
+}
+
+void CatalogManagerView::slotToggleMarksInDir()
+{
+ CatManListItem* i=(CatManListItem*) currentItem();
+
+ if(i && i->isDir())
+ {
+ const QStringList contentList = i->allChildrenList(true);
+
+ QStringList::const_iterator it;
+ for( it = contentList.constBegin(); it != contentList.constEnd(); ++it )
+ {
+ CatManListItem* item = _fileList[(*it)];
+
+ if ( item == 0 )
+ kdFatal(KBABEL_CATMAN) << "CatalogManagerView::slotToggleMarkInDir: item not in list" << endl;
+
+ const bool wasMarked=item->marked();
+ item->setMarked(!wasMarked);
+
+ if(wasMarked)
+ {
+ _markerList.remove(item->package());
+ }
+ else
+ {
+ _markerList.append(item->package());
+ }
+ }
+ }
+
+ checkSelected();
+}
+
+
+void CatalogManagerView::slotClearMarksInDir()
+{
+ CatManListItem* i=(CatManListItem*) currentItem();
+
+ if(i && i->isDir())
+ {
+ const QStringList contentList=i->contentsList(true);
+
+ QStringList::const_iterator it;
+ for( it = contentList.constBegin(); it != contentList.constEnd(); ++it )
+ {
+ CatManListItem* item = _fileList[(*it)];
+
+ if ( item == 0 )
+ kdFatal(KBABEL_CATMAN) << "CatalogManagerView::slotClearMarkInDir: item not in list" << endl;
+
+ if(item->marked())
+ {
+ _markerList.remove(item->package());
+ }
+ item->setMarked(false);
+ }
+ }
+
+ checkSelected();
+}
+
+
+void CatalogManagerView::slotDirCommand(int index)
+{
+ CatManListItem* item=(CatManListItem*) currentItem();
+
+
+ if(index>=0 && item && item->isDir())
+ {
+ QString cmd=*(_settings.dirCommands).at(index);
+ cmd.replace("@PACKAGE@",item->name());
+ cmd.replace("@PODIR@",item->poFile());
+ cmd.replace("@POTDIR@",item->potFile());
+ cmd.replace("@POFILES@",current().join(" "));
+ cmd.replace("@MARKEDPOFILES@",marked().join(" "));
+
+ kdDebug(KBABEL_CATMAN) << cmd << endl;
+
+ KProcess* proc = new KShellProcess();
+ _pendingProcesses.append(proc);
+
+ connect( proc,SIGNAL( processExited(KProcess *) ), this
+ ,SLOT( processEnded(KProcess*) ) );
+ connect( proc,SIGNAL( receivedStdout(KProcess*,char*,int) ), this
+ ,SLOT( showOutput(KProcess*,char*,int) ) );
+ connect( proc,SIGNAL( receivedStderr(KProcess*,char*,int) ), this
+ ,SLOT( showOutput(KProcess*,char*,int) ) );
+
+ *proc << "cd" << item->poFile() << ";" << cmd;
+ proc->start(KProcess::NotifyOnExit,KProcess::AllOutput);
+ }
+}
+
+void CatalogManagerView::slotFileCommand(int index)
+{
+ CatManListItem* item=(CatManListItem*) currentItem();
+
+ if(index>=0 && item && item->isFile())
+ {
+ CatManListItem* parent = (CatManListItem*)item->parent();
+
+ QString cmd=*(_settings.fileCommands).at(index);
+ cmd.replace("@PACKAGE@",item->name());
+ cmd.replace("@POFILE@",item->poFile());
+ cmd.replace("@POTFILE@",item->potFile());
+ cmd.replace("@PODIR@",parent->poFile());
+ cmd.replace("@POTDIR@",parent->potFile());
+ cmd.replace("@POEMAIL@",item->text(COL_TRANSLATOR));
+
+ kdDebug(KBABEL_CATMAN) << cmd << endl;
+
+ KProcess* proc = new KShellProcess();
+ _pendingProcesses.append(proc);
+
+ connect( proc,SIGNAL( processExited(KProcess *) ), this
+ ,SLOT( processEnded(KProcess*) ) );
+ connect( proc,SIGNAL( receivedStdout(KProcess*,char*,int) ), this
+ ,SLOT( showOutput(KProcess*,char*,int) ) );
+ connect( proc,SIGNAL( receivedStderr(KProcess*,char*,int) ), this
+ ,SLOT( showOutput(KProcess*,char*,int) ) );
+
+ *proc << "cd" << parent->poFile() << ";" << cmd;
+ proc->start(KProcess::NotifyOnExit,KProcess::AllOutput);
+ }
+
+}
+
+
+void CatalogManagerView::updateFile(QString fileWithPath, bool force)
+{
+ QString relFile;
+ if(fileWithPath.startsWith(_settings.poBaseDir))
+ {
+ relFile=fileWithPath.mid(_settings.poBaseDir.length());
+ }
+ else if(fileWithPath.startsWith(_settings.potBaseDir))
+ {
+ relFile=fileWithPath.mid(_settings.potBaseDir.length());
+ }
+ else
+ {
+ return;
+ }
+
+ if(relFile.endsWith(".pot"))
+ {
+ relFile.truncate(relFile.length()-4);
+ }
+ else if(relFile.endsWith(".po"))
+ {
+ relFile.truncate(relFile.length()-3);
+ }
+
+ CatManListItem* item=_fileList[relFile];
+
+ if(item)
+ {
+ _updateNesting++;
+ if( force ) item->forceUpdate();
+ else item->checkUpdate();
+ _updateNesting--;
+ }
+
+}
+
+void CatalogManagerView::updateAfterSave(QString fileWithPath, PoInfo &newInfo)
+{
+ QString relFile;
+ if(fileWithPath.startsWith(_settings.poBaseDir))
+ {
+ relFile=fileWithPath.mid(_settings.poBaseDir.length());
+ }
+ else if(fileWithPath.startsWith(_settings.potBaseDir))
+ {
+ relFile=fileWithPath.mid(_settings.potBaseDir.length());
+ }
+ else
+ {
+ return;
+ }
+
+ if(relFile.endsWith(".pot"))
+ {
+ relFile.truncate(relFile.length()-4);
+ }
+ else if(relFile.endsWith(".po"))
+ {
+ relFile.truncate(relFile.length()-3);
+ }
+
+ CatManListItem* item=_fileList[relFile];
+
+ if(item)
+ {
+ item->updateAfterSave(newInfo);
+ }
+
+}
+
+void CatalogManagerView::buildTree()
+{
+ // in case we were called after settings update
+ disconnect( this, SIGNAL( updateFinished() ), this, SLOT(buildTree() ) );
+
+ emit signalBuildTree(false); // announce start of building
+
+ clear();
+
+ if(isActive())
+ return;
+
+ _updateNesting++;
+
+ _active=true;
+ _stop=false;
+
+
+ CatManListItem* root = new CatManListItem(this, this,_settings.poBaseDir,_settings.potBaseDir);
+ _dirList.insert("/",root);
+ //root->setSelectable(false);
+
+ QFileInfo fileInfo(_settings.poBaseDir);
+ if(!fileInfo.isDir())
+ {
+ KMessageBox::error(this,i18n("You have not specified a valid folder "
+"for the base folder of the PO files:\n%1\n"
+"Please check your settings in the project settings dialog.").arg(_settings.poBaseDir));
+
+ _active=false;
+ _updateNesting--;
+ if( _updateNesting == 0 ) emit updateFinished();
+ return;
+ }
+
+ cvshandler->setPOBaseDir( _settings.poBaseDir );
+ svnhandler->setPOBaseDir( _settings.poBaseDir );
+ mailer->setPOBaseDir(_settings.poBaseDir);
+
+ fileInfo.setFile(_settings.potBaseDir);
+ if(!fileInfo.isDir() && !_settings.potBaseDir.isEmpty())
+ {
+ KMessageBox::error(this,i18n("You have not specified a valid folder "
+"for the base folder of the PO template files:\n%1\n"
+"Please check your settings in the project settings dialog.").arg(_settings.potBaseDir));
+ }
+
+ cvshandler->setPOTBaseDir( _settings.potBaseDir );
+ svnhandler->setPOTBaseDir( _settings.potBaseDir );
+
+ setCursor(KCursor::waitCursor());
+
+ //"/" is the root item
+ buildDir("/",true); // build dir without updating the items...
+
+ if( _stop ) {
+ _active = false;
+ _updateNesting--;
+ if( _updateNesting == 0 ) emit updateFinished();
+ return;
+ }
+
+ _dirWatch->addDir(_settings.poBaseDir);
+ if(!_settings.potBaseDir.isEmpty())
+ _dirWatch->addDir(_settings.potBaseDir);
+
+ emit signalBuildTree(true); // announce beginning of tree building
+
+ unsetCursor();
+
+ if( _stop ) {
+ _active = false;
+ _updateNesting--;
+ if( _updateNesting == 0 ) emit updateFinished();
+ return;
+ }
+
+ updateMarkerList();
+
+ const int files=_fileList.count()+_dirList.count();
+
+ _readInfoCount = 0;
+
+ emit prepareProgressBar(i18n("Reading file information"),files);
+
+ root->setOpen(true);
+
+ if( _stop ) {
+ _active = false;
+ _updateNesting--;
+ if( _updateNesting == 0 ) emit updateFinished();
+ return;
+ }
+
+ // first read information about the files...
+ QDictIterator<CatManListItem> it( _fileList ); // iterator for dict
+
+ int i=0;
+ while ( it.current() && !_stop)
+ {
+ it.current()->checkUpdate(true);
+ ++i;
+ ++it;
+ }
+
+ // ...then update directories
+ QDictIterator<CatManListItem> dit( _dirList ); // iterator for dict
+
+ while ( dit.current() && !_stop)
+ {
+ dit.current()->checkUpdate();
+ ++i;
+ ++dit;
+ }
+
+ emit clearProgressBar();
+
+ _dirWatch->startScan();
+ pause(false);
+
+ _active=false;
+
+ _updateNesting--;
+
+ if( _updateNesting == 0 )
+ {
+ emit updateFinished();
+ }
+}
+
+bool CatalogManagerView::buildDir(QString relDir,bool fast)
+{
+ if( _stop ) return false;
+
+ bool haveTemplateDir=true;
+ QFileInfo fileInfo;
+
+ fileInfo.setFile(_settings.potBaseDir);
+ if(!fileInfo.isDir())
+ {
+ haveTemplateDir=false;
+ }
+
+ bool potHasFiles=false;
+ if(haveTemplateDir)
+ potHasFiles=buildDir(_settings.potBaseDir,relDir,".pot",fast);
+
+ bool poHasFiles=buildDir(_settings.poBaseDir,relDir,".po",fast);
+
+ return (poHasFiles | potHasFiles);
+}
+
+
+bool CatalogManagerView::buildDir(const QString& baseDir,const QString& relDir
+ , const QString extension , bool fast)
+{
+ if( _stop ) return false;
+
+ bool havePoFiles=false;
+
+ CatManListItem* thisItem=_dirList[relDir];
+ if(!thisItem)
+ {
+ kdFatal(KBABEL_CATMAN) << "null pointer to this item" << endl;
+ return false;
+ }
+
+ const QString poBaseDir=_settings.poBaseDir;
+ const QString potBaseDir=_settings.potBaseDir;
+
+ // traverse directory in poBaseDir
+ QDir dir(baseDir+relDir);
+ QStringList entryList=dir.entryList("*"+extension,QDir::Files,QDir::Name);
+
+ QStringList::const_iterator it;
+
+ for ( it = entryList.constBegin(); it != entryList.constEnd() && !_stop ; ++it )
+ {
+ if( _stop ) return false;
+
+ havePoFiles=true;
+
+ QString file=relDir+(*it);
+ file.remove(QRegExp(extension+"$"));
+ CatManListItem* item = _fileList[file];
+ if(!item)
+ {
+ item = new CatManListItem(this,thisItem,poBaseDir+file+".po",potBaseDir+file+".pot",file);
+ _fileList.insert(file,item);
+ _readInfoFileList.prepend(file);
+
+ if(_markerList.contains(file))
+ {
+ item->setMarked(true);
+ }
+
+ if(!fast)
+ {
+ item->checkUpdate();
+ }
+ }
+ }
+
+ entryList=dir.entryList(QDir::Dirs,QDir::Name);
+
+ for ( it = entryList.constBegin(); it != entryList.constEnd() && !_stop ; ++it )
+ {
+ if( _stop ) return false;
+
+ if((*it)=="." || (*it)=="..")
+ {
+ continue;
+ }
+
+ QString subDir=relDir+(*it)+"/";
+ if(!_dirWatch->contains(baseDir+subDir))
+ {
+ _dirWatch->addDir(baseDir+subDir);
+ }
+
+ bool otherHasFiles=true;
+
+ CatManListItem* item = _dirList[subDir];
+ if(!item && !_stop)
+ {
+ item = new CatManListItem(this, thisItem,poBaseDir+subDir,potBaseDir+subDir,subDir);
+ _dirList.insert(subDir,item);
+
+ otherHasFiles=false;
+ }
+
+ if( _stop ) return false;
+
+ // recursive call
+ if(!buildDir(baseDir,subDir,extension,fast) && !otherHasFiles)
+ {
+ kdDebug(KBABEL_CATMAN) << "skipping " << subDir << endl;
+ deleteDirItem(subDir);
+ item=0;
+ }
+ else
+ havePoFiles=true;
+
+ } // end looking up directories in po base dir
+
+ return havePoFiles;
+}
+
+
+void CatalogManagerView::updateDir(QString relDir)
+{
+ if( _stop ) return;
+
+ kdDebug(KBABEL_CATMAN) << "updating dir " << relDir << endl;
+
+ bool havePoFiles=false;
+
+ CatManListItem* thisItem=_dirList[relDir];
+ if(!thisItem)
+ {
+ kdFatal(KBABEL_CATMAN) << "null pointer to this item" << endl;
+ return;
+ }
+
+ QStringList contentList = thisItem->contentsList(true);
+
+ const QString poBaseDir=_settings.poBaseDir;
+ const QString potBaseDir=_settings.potBaseDir;
+
+ // first lookup template directory
+ QDir dir(potBaseDir+relDir);
+ QStringList entryList=dir.entryList("*.pot",QDir::Files,QDir::Name);
+
+ QStringList::const_iterator it;
+
+ for ( it = entryList.constBegin(); it != entryList.constEnd(); ++it )
+ {
+ if( _stop ) return;
+
+ havePoFiles=true;
+
+ QString file=relDir+(*it);
+ file.remove(QRegExp(".pot$"));
+ CatManListItem* item = _fileList[file];
+ if(!item)
+ {
+ item = new CatManListItem(this, thisItem,poBaseDir+file+".po",potBaseDir+file+".pot",file);
+ _fileList.insert(file,item);
+
+ if(_markerList.contains(file))
+ {
+ item->setMarked(true);
+ }
+
+ item->checkUpdate();
+ }
+ else
+ {
+ item->checkUpdate();
+ }
+
+ contentList.remove(file);
+ }
+
+ entryList=dir.entryList(QDir::Dirs,QDir::Name);
+
+ for ( it = entryList.constBegin(); it != entryList.constEnd(); ++it )
+ {
+ if( _stop ) return;
+
+ if((*it)=="." || (*it)=="..")
+ {
+ continue;
+ }
+
+ bool newDirAdded=false;
+
+ QString subDir=relDir+(*it)+"/";
+ if(!_dirWatch->contains(potBaseDir+subDir))
+ {
+ _dirWatch->addDir(potBaseDir+subDir);
+
+ newDirAdded=true;
+ }
+
+ CatManListItem* item = _dirList[subDir];
+ if(!item && newDirAdded)
+ {
+ item = new CatManListItem(this, thisItem,poBaseDir+subDir,potBaseDir+subDir,subDir);
+ _dirList.insert(subDir,item);
+
+ if(!buildDir(subDir,false))
+ {
+ kdDebug(KBABEL_CATMAN) << "skipping " << subDir << endl;
+ deleteDirItem(subDir);
+ item=0;
+ }
+ }
+ else if(newDirAdded)
+ {
+ updateDir(subDir);
+ }
+
+
+ // if directory was already here, but no item
+ // -> directory contains no files
+ if(item && !newDirAdded)
+ {
+ havePoFiles=true;
+ }
+
+ } // end looking up directories in template dir
+
+ // now traverse directory in poBaseDir
+ dir.setPath(poBaseDir+relDir);
+ entryList=dir.entryList("*.po",QDir::Files,QDir::Name);
+
+ for ( it = entryList.constBegin(); it != entryList.constEnd(); ++it )
+ {
+ havePoFiles=true;
+
+ if( _stop ) return;
+
+ QString file=relDir+(*it);
+ file.remove(QRegExp(".po$"));
+ CatManListItem* item = _fileList[file];
+ if(!item)
+ {
+ item = new CatManListItem(this, thisItem,poBaseDir+file+".po",potBaseDir+file+".pot",file);
+ _fileList.insert(file,item);
+
+ if(_markerList.contains(file))
+ {
+ item->setMarked(true);
+ }
+
+ item->checkUpdate();
+ }
+ else
+ {
+ item->checkUpdate();
+ }
+
+ contentList.remove(file);
+ }
+
+ entryList=dir.entryList(QDir::Dirs,QDir::Name);
+
+ for ( it = entryList.constBegin(); it != entryList.constEnd(); ++it )
+ {
+ if( _stop ) return;
+
+ if((*it)=="." || (*it)=="..")
+ {
+ continue;
+ }
+
+ bool newDirAdded=false;
+
+ QString subDir=relDir+(*it)+"/";
+ if(!_dirWatch->contains(poBaseDir+subDir))
+ {
+ _dirWatch->addDir(poBaseDir+subDir);
+ newDirAdded=true;
+ }
+
+ CatManListItem* item = _dirList[subDir];
+
+ bool templateHasFiles=(bool)item;
+
+ if(!item && newDirAdded)
+ {
+ item = new CatManListItem(this, thisItem,poBaseDir+subDir,potBaseDir+subDir,subDir);
+ _dirList.insert(subDir,item);
+
+ if(!buildDir(subDir,false) && !templateHasFiles)
+ {
+ kdDebug(KBABEL_CATMAN) << "skipping " << subDir << endl;
+ deleteDirItem(subDir);
+ item=0;
+ }
+ }
+ else if(newDirAdded)
+ {
+ updateDir(subDir);
+ }
+
+ // if directory was already here, but no item
+ // -> directory contains no files
+ if(item && !newDirAdded)
+ {
+ havePoFiles=true;
+ }
+
+
+ } // end looking up directories in po base dir
+
+
+ // check, if something in the directory has been deleted
+ // but only if we traversed also the template directory
+ if(contentList.count()>0)
+ {
+ QStringList::const_iterator it;
+ for( it = contentList.constBegin(); it != contentList.constEnd(); ++it )
+ {
+ QFileInfo po(poBaseDir+(*it));
+ QFileInfo pot(potBaseDir+(*it));
+
+ if(!po.exists() && !pot.exists())
+ {
+ CatManListItem* item = _fileList[(*it)];
+ if(item)
+ {
+ if(item->marked())
+ _markerList.remove(item->package());
+
+ _fileList.remove((*it));
+ delete item;
+ }
+ }
+ }
+ }
+
+ if(!havePoFiles)
+ {
+ deleteDirItem(relDir);
+
+ // if this directory has to be removed, check, if
+ // the parent directory has to be removed too
+ const int index=relDir.findRev("/",relDir.length()-2);
+ if(index<0)
+ {
+ relDir="/";
+ }
+ relDir=relDir.left(index+1);
+ updateDir(relDir);
+ }
+}
+
+void CatalogManagerView::directoryChanged(const QString& dir)
+{
+ pause(true);
+
+ QString relDir, relDirPo, relDirPot;
+ if(dir.startsWith(_settings.poBaseDir))
+ {
+ relDirPo=dir.mid(_settings.poBaseDir.length());
+ }
+ if(dir.startsWith(_settings.potBaseDir))
+ {
+ relDirPot=dir.mid(_settings.potBaseDir.length());
+ }
+
+ if( relDirPo.isEmpty() )
+ {
+ // use POT
+ relDir = relDirPot;
+ }
+ else if( relDirPot.isEmpty() )
+ {
+ // use PO
+ relDir = relDirPo;
+ }
+ else
+ {
+ // both PO and POT usable, find out the correct one
+ if( relDirPo.left(1) == "/" )
+ {
+ relDir = relDirPo;
+ }
+ else
+ {
+ relDir = relDirPot;
+ }
+ }
+
+ if(relDir.right(1)!="/")
+ {
+ relDir+="/";
+ }
+
+ kdDebug(KBABEL_CATMAN) << "directory changed: " << relDir << endl;
+
+ QFileInfo fileInfo(_settings.potBaseDir);
+
+ CatManListItem* thisItem=_dirList[relDir];
+ if(!thisItem)
+ {
+ // if this item is not in the list search for next existing parent item
+ QString prevRelDir;
+ do
+ {
+ prevRelDir=relDir;
+ const int index=relDir.findRev("/",relDir.length()-2);
+ if(index<0)
+ {
+ relDir="/";
+ }
+ relDir=relDir.left(index+1);
+
+ thisItem=_dirList[relDir];
+ }
+ while(relDir!="/" && !thisItem);
+
+ if(!thisItem)
+ {
+ kdFatal(KBABEL_CATMAN) << "null pointer to this item: " << relDir << endl;
+ return;
+ }
+ else
+ {
+ // if a parent item dir is found, create the needed item in this dir
+ // and build the tree from this item on
+ kdDebug(KBABEL_CATMAN) << "building dir: " << prevRelDir << endl;
+ CatManListItem* item = new CatManListItem(this, thisItem,_settings.poBaseDir+prevRelDir
+ ,_settings.potBaseDir+prevRelDir,prevRelDir);
+ _dirList.insert(prevRelDir,item);
+
+
+ if(!buildDir(prevRelDir,false))
+ {
+ deleteDirItem(prevRelDir);
+ }
+ }
+ }
+ else
+ {
+ updateDir(relDir);
+ }
+
+ pause(false);
+}
+
+
+void CatalogManagerView::directoryDeleted(const QString& dir)
+{
+ pause(true);
+
+ QString relDir, relDirPo, relDirPot;
+ if(dir.startsWith(_settings.poBaseDir))
+ {
+ relDirPo=dir.mid(_settings.poBaseDir.length());
+ }
+ if(dir.startsWith(_settings.potBaseDir))
+ {
+ relDirPot=dir.mid(_settings.potBaseDir.length());
+ }
+
+ if( relDirPo.isEmpty() )
+ {
+ // use POT
+ relDir = relDirPot;
+ }
+ else if( relDirPot.isEmpty() )
+ {
+ // use PO
+ relDir = relDirPo;
+ }
+ else
+ {
+ // both PO and POT usable, find out the correct one
+ if( relDirPo.left(1) == "/" )
+ {
+ relDir = relDirPo;
+ }
+ else
+ {
+ relDir = relDirPot;
+ }
+ }
+
+ if(relDir.right(1)!="/")
+ {
+ relDir+="/";
+ }
+
+ kdDebug(KBABEL_CATMAN) << "directory deleted: " << relDir << endl;
+
+ CatManListItem* thisItem=_dirList[relDir];
+ if(thisItem)
+ {
+ // we have to take care, if one directory still exists
+ const bool poDeleted=!thisItem->hasPo();
+ const bool potDeleted=!thisItem->hasPot();
+
+ // if neither the po- nor the pot-directory exists any more
+ // delete all sub items
+ if(poDeleted && potDeleted)
+ {
+ deleteDirItem(relDir);
+ }
+ else
+ {
+ QStringList childList = thisItem->contentsList();
+
+ CatManListItem* item;
+ QStringList::const_iterator it;
+ for( it = childList.constBegin();it != childList.constEnd(); ++it )
+ {
+ item=_fileList[(*it)];
+ if(item)
+ {
+ if( (poDeleted && !item->hasPot()) ||
+ (potDeleted && !item->hasPo()) )
+ {
+ _fileList.remove((*it));
+ delete item;
+ }
+ else
+ {
+ item->checkUpdate();
+ }
+ }
+ else
+ {
+ item=_dirList[(*it)];
+ if(item)
+ {
+ if( (poDeleted && !item->hasPot()) ||
+ (potDeleted && !item->hasPo()) )
+ {
+ deleteDirItem((*it));
+ }
+ }
+ else
+ {
+ kdDebug(KBABEL_CATMAN) << "directoryDeleted: don't have item "
+ << (*it) << endl;
+ }
+ }
+ }
+ }
+ }
+
+ pause(false);
+}
+
+void CatalogManagerView::fileInfoRead( QString filename )
+{
+ if( _readInfoFileList.find( filename ) != _readInfoFileList.end() ) {
+ emit progress( ++_readInfoCount);
+ _readInfoFileList.remove( filename );
+ }
+
+ if( _readInfoFileList.isEmpty() ) emit clearProgressBar();
+}
+
+void CatalogManagerView::setSettings(CatManSettings newSettings)
+{
+ CatManSettings oldSettings=_settings;
+ _settings=newSettings;
+
+ if(_settings.poBaseDir.right(1)=="/")
+ _settings.poBaseDir.truncate(_settings.poBaseDir.length()-1);
+ if(_settings.potBaseDir.right(1)=="/")
+ _settings.potBaseDir.truncate(_settings.potBaseDir.length()-1);
+
+ _dirCommandsMenu->clear();
+ int counter=0;
+ for ( QStringList::const_iterator it = _settings.dirCommandNames.constBegin()
+ ; it != _settings.dirCommandNames.constEnd(); ++it )
+ {
+ _dirCommandsMenu->insertItem((*it),counter);
+ counter++;
+ }
+ _dirCommandsMenu->insertSeparator();
+ _dirCommandsMenu->insertItem(i18n("Log Window"),this,SLOT(showLog()));
+
+ _fileCommandsMenu->clear();
+ counter=0;
+ for ( QStringList::const_iterator it = _settings.fileCommandNames.constBegin()
+ ; it != _settings.fileCommandNames.constEnd(); ++it )
+ {
+ _fileCommandsMenu->insertItem((*it),counter);
+ counter++;
+ }
+ _fileCommandsMenu->insertSeparator();
+ _fileCommandsMenu->insertItem(i18n("Log Window"),this,SLOT(showLog()));
+
+ const bool pathChanged = (oldSettings.poBaseDir!=_settings.poBaseDir)
+ || (oldSettings.potBaseDir!=_settings.potBaseDir);
+
+ if(pathChanged)
+ {
+ if( !isActive() ) {
+ QTimer::singleShot(100,this,SLOT(buildTree()));
+ } else {
+ stop();
+ connect( this, SIGNAL( updateFinished() ), this, SLOT(buildTree() ) );
+ }
+ }
+
+ toggleColumn( COL_MARKER, _settings.flagColumn );
+ toggleColumn( COL_FUZZY, _settings.fuzzyColumn );
+ toggleColumn( COL_UNTRANS, _settings.untranslatedColumn );
+ toggleColumn( COL_TOTAL, _settings.totalColumn );
+ // FIXME: follow CVS/SVN status
+ toggleColumn( COL_CVS_OR_SVN, _settings.cvsColumn );
+ toggleColumn( COL_REVISION, _settings.revisionColumn );
+ toggleColumn( COL_TRANSLATOR, _settings.translatorColumn );
+}
+
+
+CatManSettings CatalogManagerView::settings() const
+{
+ return _settings;
+}
+
+
+void CatalogManagerView::hideEvent(QHideEvent*)
+{
+ pause(true);
+
+ if(_dirWatch)
+ _dirWatch->stopScan();
+}
+
+void CatalogManagerView::showEvent(QShowEvent*)
+{
+ QTimer::singleShot(1,this,SLOT(checkUpdate()));
+
+ pause(false);
+
+ if(_dirWatch)
+ _dirWatch->startScan(true);
+}
+
+void CatalogManagerView::contentsMousePressEvent(QMouseEvent* event)
+{
+ if(event->button() == LeftButton)
+ _pressPos=event->pos();
+
+ QListView::contentsMousePressEvent( event );
+}
+
+void CatalogManagerView::contentsMouseMoveEvent(QMouseEvent* event)
+{
+ if(event->state() & LeftButton)
+ {
+ const int delay = KGlobalSettings::dndEventDelay();
+ if(QABS( event->pos().x() - _pressPos.x() ) >= delay ||
+ QABS( event->pos().y() - _pressPos.y() ) >= delay)
+ {
+ CatManListItem* item = (CatManListItem*)itemAt(contentsToViewport(_pressPos));
+ if(item && item->isFile())
+ {
+ // always add the po-file and if existing the pot-file to the drag and
+ // let the user decide what to do, when dropping into kbabel
+ QStrList uri;
+ uri.append(QUriDrag::localFileToUri(item->poFile()));
+ if(item->hasPot())
+ uri.append(QUriDrag::localFileToUri(item->potFile()));
+
+ QUriDrag* drag = new QUriDrag(uri,this);
+ QPixmap icon=KGlobal::iconLoader()->loadIcon("txt",KIcon::Desktop);
+ drag->setPixmap(icon,QPoint(icon.width()/2,icon.height()/2));
+ drag->drag();
+ }
+ else
+ {
+ QListView::contentsMouseMoveEvent(event);
+ }
+ }
+ else
+ {
+ QListView::contentsMouseMoveEvent(event);
+ }
+ }
+ else
+ {
+ QListView::contentsMouseMoveEvent(event);
+ }
+}
+
+void CatalogManagerView::readMarker( KConfig* config)
+{
+ KConfigGroupSaver cs(config,"CatalogManager");
+
+ _markerList = config->readListEntry("Marker");
+}
+
+void CatalogManagerView::saveMarker( KConfig* config) const
+{
+ KConfigGroupSaver cs(config,"CatalogManager");
+
+ config->writeEntry("Marker",_markerList);
+ config->sync();
+}
+
+
+void CatalogManagerView::deleteDirItem(QString relDir)
+{
+ CatManListItem* thisItem=_dirList[relDir];
+
+ if(!thisItem)
+ return;
+
+ _dirList.remove(relDir);
+
+ QStringList childList = thisItem->allChildrenList();
+
+ QStringList::const_iterator it;
+ for( it = childList.constBegin();it != childList.constEnd(); ++it )
+ {
+ if(!_fileList.remove((*it)))
+ _dirList.remove((*it));
+ }
+
+
+ // delete the item with all sub item
+ delete thisItem;
+}
+
+
+
+void CatalogManagerView::processEnded(KProcess* proc)
+{
+ _pendingProcesses.removeRef(proc);
+}
+
+
+void CatalogManagerView::showOutput(KProcess*, char *buffer, int buflen)
+{
+ const QCString output(buffer,buflen+1);
+
+ _logView->insert(output);
+}
+
+void CatalogManagerView::columnClicked(QListViewItem * item, const QPoint &, int c)
+{
+ if( item && c == COL_MARKER )
+ {
+ slotToggleMark();
+ }
+}
+
+CatManListItem *CatalogManagerView::itemBelow( CatManListItem *item )
+{
+ if( item->isDir() )
+ {
+ if( item->firstChild() )
+ return static_cast<CatManListItem *>( item->firstChild() );
+ else
+ {
+ while( !static_cast<CatManListItem *>( item->nextSibling() ) )
+ {
+ item = static_cast<CatManListItem *>( item->parent() );
+ if( !item ) return item;
+ }
+ return static_cast<CatManListItem *>( item->nextSibling() );
+ }
+ }
+ else
+ {
+ while( !static_cast<CatManListItem *>( item->nextSibling() ) )
+ {
+ item = static_cast<CatManListItem *>( item->parent());
+ if( !item ) return item;
+ }
+ return static_cast<CatManListItem *>( item->nextSibling() );
+ }
+}
+
+CatManListItem *CatalogManagerView::itemAbove( CatManListItem *item )
+{
+ if( item->isDir() )
+ {
+ if( item->firstChild() )
+ return static_cast<CatManListItem *>( item->lastChild() );
+ else
+ {
+ while( !static_cast<CatManListItem *>( item->previousSibling() ) )
+ {
+ item = static_cast<CatManListItem *>( item->parent() );
+ if( !item ) return item;
+ }
+ return static_cast<CatManListItem *>( item->previousSibling() );
+ }
+ }
+ else
+ {
+ while( !static_cast<CatManListItem *>( item->previousSibling() ) )
+ {
+ item = static_cast<CatManListItem *>( item->parent());
+ if( !item ) return item;
+ }
+ return static_cast<CatManListItem *>( item->previousSibling() );
+ }
+}
+
+void CatalogManagerView::gotoNextUntranslated()
+{
+ CatManListItem *i;
+ CatManListItem *current = static_cast<CatManListItem *>(currentItem());
+ while( ( i = itemBelow(current)) )
+ {
+ if( i->untranslated() > 0 )
+ {
+ setCurrentItem(i);
+ ensureItemVisible(i);
+ return;
+ } else current = i;
+ }
+}
+
+void CatalogManagerView::gotoPreviousUntranslated()
+{
+ CatManListItem *i;
+ CatManListItem *current = static_cast<CatManListItem *>(currentItem());
+ while( (i = itemAbove(current)) )
+ {
+ if( i->untranslated() > 0 )
+ {
+ setCurrentItem(i);
+ ensureItemVisible(i);
+ return;
+ } else current = i;
+ }
+}
+
+void CatalogManagerView::gotoNextFuzzy()
+{
+ CatManListItem *i;
+ CatManListItem *current = static_cast<CatManListItem *>(currentItem());
+ while( ( i = itemBelow(current)) )
+ {
+ if( i->fuzzy() > 0 )
+ {
+ setCurrentItem(i);
+ ensureItemVisible(i);
+ return;
+ } else current = i;
+ }
+}
+
+void CatalogManagerView::gotoPreviousFuzzy()
+{
+ CatManListItem *i;
+ CatManListItem *current = static_cast<CatManListItem *>(currentItem());
+ while( (i = itemAbove(current)) )
+ {
+ if( i->fuzzy() > 0 )
+ {
+ setCurrentItem(i);
+ ensureItemVisible(i);
+ return;
+ } else current = i;
+ }
+}
+
+void CatalogManagerView::gotoNextFuzzyOrUntranslated()
+{
+ CatManListItem *i;
+ CatManListItem *current = static_cast<CatManListItem *>(currentItem());
+ while( ( i = itemBelow(current)) )
+ {
+ if( i->untranslated() > 0 || i->fuzzy() > 0 )
+ {
+ setCurrentItem(i);
+ ensureItemVisible(i);
+ return;
+ } else current = i;
+ }
+}
+
+void CatalogManagerView::gotoPreviousFuzzyOrUntranslated()
+{
+ CatManListItem *i;
+ CatManListItem *current = static_cast<CatManListItem *>(currentItem());
+ while( (i = itemAbove(current)) )
+ {
+ if( i->untranslated() > 0 || i->fuzzy() > 0 )
+ {
+ setCurrentItem(i);
+ ensureItemVisible(i);
+ return;
+ } else current = i;
+ }
+}
+
+void CatalogManagerView::gotoNextError()
+{
+ CatManListItem *i;
+ CatManListItem *current = static_cast<CatManListItem *>(currentItem());
+ while( ( i = itemBelow(current)) )
+ {
+ if( i->hasErrors() )
+ {
+ setCurrentItem(i);
+ ensureItemVisible(i);
+ return;
+ } else current = i;
+ }
+}
+
+void CatalogManagerView::gotoPreviousError()
+{
+ CatManListItem *i;
+ CatManListItem *current = static_cast<CatManListItem *>(currentItem());
+ while( (i = itemAbove(current)) )
+ {
+ if( i->hasErrors() )
+ {
+ setCurrentItem(i);
+ ensureItemVisible(i);
+ return;
+ } else current = i;
+ }
+}
+
+void CatalogManagerView::gotoNextTemplate()
+{
+ CatManListItem *i;
+ CatManListItem *current = static_cast<CatManListItem *>(currentItem());
+ while( ( i = itemBelow(current)) )
+ {
+ if( i->hasPot() && !i->hasPo() )
+ {
+ setCurrentItem(i);
+ ensureItemVisible(i);
+ return;
+ } else current = i;
+ }
+}
+
+void CatalogManagerView::gotoPreviousTemplate()
+{
+ CatManListItem *i;
+ CatManListItem *current = static_cast<CatManListItem *>(currentItem());
+ while( (i = itemAbove(current)) )
+ {
+ if( i->hasPot() && !i->hasPo() )
+ {
+ setCurrentItem(i);
+ ensureItemVisible(i);
+ return;
+ } else current = i;
+ }
+}
+
+void CatalogManagerView::gotoNextPo()
+{
+ CatManListItem *i;
+ CatManListItem *current = static_cast<CatManListItem *>(currentItem());
+ while( ( i = itemBelow(current)) )
+ {
+ if( i->hasPo() )
+ {
+ setCurrentItem(i);
+ ensureItemVisible(i);
+ return;
+ } else current = i;
+ }
+}
+
+void CatalogManagerView::gotoPreviousPo()
+{
+ CatManListItem *i;
+ CatManListItem *current = static_cast<CatManListItem *>(currentItem());
+ while( (i = itemAbove(current)) )
+ {
+ if( i->hasPo() )
+ {
+ setCurrentItem(i);
+ ensureItemVisible(i);
+ return;
+ } else current = i;
+ }
+}
+
+void CatalogManagerView::gotoNextMarked()
+{
+ CatManListItem *i;
+ CatManListItem *current = static_cast<CatManListItem *>(currentItem());
+ while( ( i = itemBelow(current)) )
+ {
+ if( i->marked() )
+ {
+ setCurrentItem(i);
+ ensureItemVisible(i);
+ return;
+ } else current = i;
+ }
+}
+
+void CatalogManagerView::gotoPreviousMarked()
+{
+ CatManListItem *i;
+ CatManListItem *current = static_cast<CatManListItem *>(currentItem());
+ while( (i = itemAbove(current)) )
+ {
+ if( i->marked() )
+ {
+ setCurrentItem(i);
+ ensureItemVisible(i);
+ return;
+ } else current = i;
+ }
+}
+
+QStringList CatalogManagerView::current()
+{
+ QStringList result;
+ CatManListItem *current = static_cast<CatManListItem *>(currentItem());
+ if( current->isDir() )
+ {
+ QStringList s = current->allChildrenList(true);
+ QStringList::const_iterator it;
+ for( it = s.constBegin() ; it != s.constEnd(); ++it )
+ {
+ CatManListItem *item = _fileList[(*it)];
+ result.append( item->poFile() );
+ }
+ }
+ else
+ {
+ if( current->hasPo() ) result.append( current->poFile() );
+ }
+ return result;
+}
+
+QStringList CatalogManagerView::marked()
+{
+ QStringList result;
+
+ QStringList::const_iterator it;
+ for( it = _markerList.constBegin() ; it != _markerList.constEnd(); ++it )
+ {
+ CatManListItem *item = _fileList[(*it)];
+ result.append( item->poFile() );
+ }
+ return result;
+}
+
+void CatalogManagerView::updateCurrent()
+{
+ CatManListItem *current = static_cast<CatManListItem *>(currentItem());
+ if( !current->hasPo() && !current->hasPot() )
+ {
+ if( current->isFile() )
+ {
+ _fileList.remove(current->package());
+ delete current;
+ }
+ else
+ {
+ directoryDeleted(current->package());
+ }
+ }
+ else
+ {
+ if( current->isDir() )
+ {
+ directoryChanged(current->poFile() );
+ }
+
+ // check, if the item didn't get lost by the update in directoryChanged()
+ CatManListItem *new_current = static_cast<CatManListItem *>(currentItem());
+ if (new_current == current)
+ {
+ current->forceUpdate();
+ }
+ }
+}
+
+void CatalogManagerView::updateFiles( const QStringList& files )
+{
+ QStringList::ConstIterator it;
+ for ( it = files.constBegin( ); it != files.constEnd( ); ++it ) {
+ updateFile( *it, true );
+ }
+}
+
+CVSHandler * CatalogManagerView::cvsHandler( )
+{
+ return cvshandler;
+}
+
+SVNHandler * CatalogManagerView::svnHandler( )
+{
+ return svnhandler;
+}
+
+void CatalogManagerView::validateUsingTool( const KDataToolInfo &tool, const QString& command )
+{
+ QStringList result;
+ CatManListItem *current = static_cast<CatManListItem *>(currentItem());
+ if( current->isDir() )
+ {
+ const QStringList s = current->allChildrenList(true);
+ QStringList::const_iterator it;
+ for( it = s.constBegin() ; it != s.constEnd(); ++it )
+ {
+ CatManListItem *item = _fileList[(*it)];
+ if( item && item->hasPo() ) result.append( item->package() );
+ }
+ }
+ else
+ {
+ result.append( current->package() );
+ }
+
+ validate_internal( result, tool, command );
+}
+
+void CatalogManagerView::validateMarkedUsingTool( const KDataToolInfo &tool, const QString& command )
+{
+ validate_internal( _markerList, tool, command );
+}
+
+void CatalogManagerView::validate_internal( const QStringList& files, const KDataToolInfo &tool, const QString& )
+{
+ if( files.isEmpty() ) return;
+
+ KDataTool* t = tool.createTool();
+
+ if( !t )
+ {
+ KMessageBox::error( this, i18n("Cannot instantiate a validation tool.\n"
+ "Please check your installation."), i18n("Validation Tool Error") );
+ return;
+ }
+
+ // setup options
+ if( !_validateOptionsDlg )
+ {
+ _validateOptionsDlg = new KDialogBase( this, "validation options",
+ true, i18n("Validation Options"), KDialogBase::Ok|KDialogBase::Cancel);
+ _validateOptions = new ValidationOptions(_validateOptionsDlg);
+ _validateOptionsDlg->setMainWidget( _validateOptions );
+ _validateOptions->resize( _validateOptions->sizeHint() );
+
+ // setup stored values
+ _validateOptions->markAsFuzzy->setChecked( _markAsFuzzy );
+ _validateOptions->ignoreFuzzy->setChecked( _ignoreFuzzy );
+ }
+
+ if( _validateOptionsDlg->exec() != QDialog::Accepted )
+ {
+ delete t;
+
+ return;
+ }
+
+ if( !_validateDialog )
+ {
+ _validateDialog = new ValidateProgressDialog(_settings.ignoreURL, this);
+ connect( _validateDialog, SIGNAL( errorDoubleClicked(const QString,const int)),
+ this, SLOT(showError( const QString, const int )));
+ }
+
+ _markAsFuzzy = _validateOptions->markAsFuzzy->isChecked();
+ _ignoreFuzzy = _validateOptions->ignoreFuzzy->isChecked();
+
+ _validateDialog->setMarkAsFuzzy(_markAsFuzzy);
+ _validateDialog->setIgnoreFuzzy(_ignoreFuzzy);
+
+ QPtrList<CatManListItem> fileitems;
+
+ for( QValueListConstIterator<QString> it=files.begin() ; it!=files.end() ; ++it )
+ {
+ CatManListItem* item=_fileList[ (*it) ];
+ if( item ) {
+ fileitems.append(item);
+ } else kdDebug(KBABEL_CATMAN) << "Cannot find the file item for " << (*it) << endl;
+ }
+
+ _validateDialog->validate(tool, fileitems);
+
+ delete t;
+}
+
+void CatalogManagerView::showError( const QString package, const int num )
+{
+ CatManListItem* item = _fileList[ package];
+ if( !item )
+ {
+ kdWarning() << "Can not find error package: " << package << endl;
+ return;
+ }
+
+ emit gotoFileEntry( item->poFile(), package, num );
+}
+
+void CatalogManagerView::updateMarkerList()
+{
+ QStringList newMarkers;
+
+ for( QStringList::const_iterator it = _markerList.constBegin(); it != _markerList.constEnd(); ++it ) {
+ if( _fileList[ (*it) ] )
+ newMarkers.append( (*it) );
+ }
+
+ _markerList = newMarkers;
+}
+
+void CatalogManagerView::slotValidPOCVSRepository( bool valid )
+{
+ m_validPOCVSRepository = valid;
+ slotToggleCVSOrSVNColumn(valid);
+ // set initial state for CVS menu entries
+ emit selectedChanged(NEEDS_PO + NEEDS_PO_CVS * m_validPOCVSRepository);
+}
+
+void CatalogManagerView::slotValidPOSVNRepository( bool valid )
+{
+ m_validPOSVNRepository = valid;
+ slotToggleCVSOrSVNColumn(valid);
+ // set initial state for SVN menu entries
+ emit selectedChanged(NEEDS_PO + NEEDS_PO_SVN * m_validPOSVNRepository);
+}
+
+void CatalogManagerView::slotValidPOTCVSRepository( bool valid )
+{
+ m_validPOTCVSRepository = valid;
+ // set initial state for CVS menu entries
+ // ### TODO: something missing here?
+}
+
+void CatalogManagerView::slotValidPOTSVNRepository( bool valid )
+{
+ m_validPOTSVNRepository = valid;
+ // set initial state for SVN menu entries
+ // ### TODO: something missing here?
+}
+
+void CatalogManagerView::slotToggleCVSOrSVNColumn( bool show )
+{
+#if 0
+ toggleColumn( COL_CVS_OR_SVN, show );
+#else
+ // ### HACK
+ toggleColumn( COL_CVS_OR_SVN, m_validPOCVSRepository || m_validPOSVNRepository );
+
+#endif
+}
+
+void CatalogManagerView::toggleColumn( uint column, bool show )
+{
+ if ( show ) {
+ setColumnWidthMode( column, Maximum );
+ setColumnWidth( column, -1 );
+ // ensure that the column heading is always fully visible
+ setColumnText( column, COLTEXT(column));
+ } else {
+ setColumnWidthMode( column, Manual );
+ setColumnWidth( column, 0 );
+ }
+}
+
+#include "catalogmanagerview.moc"
+// kate: space-indent on; indent-width 4; replace-tabs on;
diff --git a/kbabel/catalogmanager/catalogmanagerview.h b/kbabel/catalogmanager/catalogmanagerview.h
new file mode 100644
index 00000000..e4421973
--- /dev/null
+++ b/kbabel/catalogmanager/catalogmanagerview.h
@@ -0,0 +1,474 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2001-2004 by Stanislav Visnovsky <visnovsky@kde.org>
+ Copyright (C) 2005, 2006 by Nicolas GOUTTE <goutte@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef CATALOGMANAGERVIEW_H
+#define CATALOGMANAGERVIEW_H
+
+#include <qdict.h>
+#include <qlistview.h>
+#include <qdatetime.h>
+#include <qtimer.h>
+#include <qfileinfo.h>
+#include <qguardedptr.h>
+
+#include <kdialogbase.h>
+#include <kdirwatch.h>
+#include <kprocess.h>
+#include <qptrlist.h>
+
+#include "kbproject.h"
+#include "projectsettings.h"
+#include "findoptions.h"
+#include "cvsresources.h"
+#include "svnresources.h"
+
+class CatManListItem;
+class QPixmap;
+class QPopupMenu;
+class KBabelDictBox;
+class CatManPreferences;
+class QTextEdit;
+class KProgress;
+class KConfig;
+class KDataToolInfo;
+class ValidateProgressDialog;
+class CVSHandler;
+class SVNHandler;
+class MarkPatternDialog;
+class ValidationOptions;
+
+namespace KBabel
+{
+ class KBabelMailer;
+ class PoInfo;
+}
+
+class CatalogManagerView : public QListView
+{
+ Q_OBJECT
+public:
+ CatalogManagerView(KBabel::Project::Ptr project, QWidget* parent=0, const char* name=0);
+ virtual ~CatalogManagerView();
+
+ KBabel::CatManSettings settings() const;
+ /** clears the tree */
+ virtual void clear();
+
+ /** pauses the update timer */
+ void pause(bool);
+
+ /** if file fileWithPath exists in the treeview, this is updated */
+ void updateFile(QString fileWithPath, bool force = false);
+
+ void updateAfterSave(QString fileWithPath, KBabel::PoInfo &info);
+
+ bool isActive() const {return _active;}
+ bool isStopped() const {return _stop;}
+
+ void restoreView(KConfig *config);
+ void saveView(KConfig *config) const;
+
+ void setRMBMenuFile( QPopupMenu *m);
+ void setRMBMenuDir( QPopupMenu *m);
+ void setDirCommandsMenu( QPopupMenu *m);
+ void setFileCommandsMenu( QPopupMenu *m);
+
+ CVSHandler * cvsHandler();
+ SVNHandler * svnHandler();
+
+public slots:
+ void setSettings(KBabel::CatManSettings newSettings);
+ void toggleMark();
+ /**
+ * removes all marks in directory of current item (must be a directory)
+ */
+ void slotClearMarksInDir();
+ void clearAllMarks();
+ void toggleAllMarks();
+ void markModifiedFiles();
+ void loadMarks();
+ void saveMarks();
+ void slotMarkPattern( );
+ void slotUnmarkPattern( );
+ /**
+ * traverses all childs in the directory of the current item
+ * (including all subdirectories) and displays some statistics
+ * about the translations. If the item is a file, its
+ * parent directory is used instead.
+ */
+ void statistics();
+ /**
+ * traverses all marked childs in the directory of the current item
+ * (including all subdirectories) and displays some statistics
+ * about the translations. If the item is a file, its
+ * parent directory is used instead.
+ */
+ void markedStatistics();
+ /**
+ * calls @ref Msgfmt::checkSyntax, to check the po-file of
+ * the selected item
+ */
+ void checkSyntax();
+
+ void roughTranslation();
+ void markedRoughTranslation();
+
+ /** Send the selected item as a compressed mail attachment. If the
+ * selected item is a directory send the items contained in the
+ * directory.
+ */
+ void mailFiles();
+ /** Send the marked items as a compressed mail attachment.
+ */
+ void mailMarkedFiles();
+
+ void packageFiles();
+ void packageMarkedFiles();
+
+ void cvsUpdate( );
+ void cvsUpdateMarked( );
+ void cvsCommit( );
+ void cvsCommitMarked( );
+ void cvsStatus( );
+ void cvsStatusMarked( );
+ void cvsUpdateTemplate( );
+ void cvsUpdateMarkedTemplate( );
+ void cvsCommitTemplate( );
+ void cvsCommitMarkedTemplate( );
+ void cvsDiff( );
+
+ void svnUpdate( );
+ void svnUpdateMarked( );
+ void svnCommit( );
+ void svnCommitMarked( );
+ void svnStatusRemote();
+ void svnStatusRemoteMarked();
+ void svnStatusLocal();
+ void svnStatusLocalMarked();
+ void svnUpdateTemplate( );
+ void svnUpdateMarkedTemplate( );
+ void svnCommitTemplate( );
+ void svnCommitMarkedTemplate( );
+ void svnDiff( );
+ void svnInfo();
+ void svnInfoMarked();
+
+ QString find(KBabel::FindOptions &options, QStringList &rest);
+
+ void showLog();
+
+ void stop(bool s = true);
+
+ /**
+ * Stop searching, do not try to proceed to the next file
+ * @ref @find will return clear list of rest to be searched
+ * and @ref QString::null, if search string was not is the last searched file
+ */
+ void stopSearch();
+
+ /**
+ * Information for this file has been read. If the file is in
+ * @ref @_readInfoFileList, it will update progress bar by emitting @ref @progress
+ */
+ void fileInfoRead( QString file );
+
+ void gotoNextUntranslated();
+ void gotoPreviousUntranslated();
+ void gotoNextFuzzy();
+ void gotoPreviousFuzzy();
+ void gotoNextFuzzyOrUntranslated();
+ void gotoPreviousFuzzyOrUntranslated();
+ void gotoNextError();
+ void gotoPreviousError();
+ void gotoNextTemplate();
+ void gotoPreviousTemplate();
+ void gotoNextPo();
+ void gotoPreviousPo();
+ void gotoNextMarked();
+ void gotoPreviousMarked();
+
+ void validateUsingTool( const KDataToolInfo &, const QString& );
+ void validateMarkedUsingTool( const KDataToolInfo &, const QString& );
+
+ void showError( const QString package, const int num);
+
+ void updateCurrent();
+
+ /**
+ * An update for more than one file has become necessary. For instance
+ * after 'cvs commit' or 'svn commit' the file contents have not changed
+ * but the CVS/SVN file status could have changed.
+ */
+ void updateFiles( const QStringList& files );
+
+ /**
+ * Returns the list of all currently selected files. If current selection is dir,
+ * it returns list of all its children.
+ */
+ QStringList current();
+ /**
+ * Returns the list of all currently marked files.
+ */
+ QStringList marked();
+
+signals:
+ void openFile(QString filename,QString package);
+ void openFileInNewWindow(QString filename,QString package);
+ void openTemplate(QString openFilename,QString saveFileName,QString package);
+ void openTemplateInNewWindow(QString openFilename,QString saveFileName,QString package);
+ void gotoFileEntry(QString filename,QString package,int msgid);
+ void prepareProgressBar(QString msg,int max);
+ void progress(int);
+ void clearProgressBar();
+ void prepareFindProgressBar(int max);
+ void signalBuildTree(bool done);
+ void signalSearchedFile(int count);
+
+ void newValidationFile(QString);
+ void newValidationTool(QString);
+ void setValidationProgressBar(int);
+ void advanceValidationFileProgressBar(int);
+ void setMaxValidationProgressBar(int);
+ void setMaxValidationFileProgressBar(int);
+
+ /**
+ * The selected item in the tree view has changed.
+ * This signal emits the corresponding action value for this item.
+ * @param actionValue Action value for the selected item.
+ */
+ void selectedChanged(uint actionValue);
+
+signals:
+ void updateFinished();
+
+protected:
+ /**
+ * builds the tree under dir relDir, but does not update any files
+ * this functions always traverses all subdirs
+ *
+ * @param relDir the relative dir under the po- and pot- base directories
+ * @param fast if true, no files will be updated
+ *
+ * @return true, if the directory contains any po or pot-files
+ * @see CatalogManagerView::buildDir
+ * @see CatalogManagerView::updateDir
+ */
+ bool buildDir(QString relDir,bool fast=true);
+
+ /**
+ * This function is traversing the real directory on the
+ * disc using baseDir as the
+ * base directory and starts at baseDir+relDir
+ * @param extension the extension of the files in this directory
+ * @param fast if true, no file will be updated
+ *
+ * @return true, if the directory contains any po or pot-files
+ * @see CatalogManagerView::buildDir
+ * @see CatalogManagerView::updateDir
+ */
+ bool buildDir(const QString& baseDir,const QString& relDir, const QString extension,bool fast=true);
+
+ /**
+ * updates dir relDir and if any new subdir is added
+ * builds this with @ref buildDir
+ *
+ * This function doesn't enters subdirs except when a new subdir is added.
+ * @see CatalogManagerView::buildDir
+ */
+ void updateDir(QString relDir);
+
+ /**
+ * stops the update timer and the dirwatch
+ * @see KDirWatch::stop
+ * @see QTimer::stop
+ */
+ virtual void hideEvent(QHideEvent*);
+ /**
+ * restarts the update timer and the dirwatch
+ * @see KDirWatch::start
+ * @see QTimer::start
+ */
+ virtual void showEvent(QShowEvent*);
+
+ /** used for dragging */
+ virtual void contentsMousePressEvent(QMouseEvent* e);
+ /** used for dragging */
+ virtual void contentsMouseMoveEvent(QMouseEvent* e);
+
+ void showStatistics( CatManListItem *i, QStringList &packages);
+
+protected slots:
+ /** rebuilds the tree*/
+ void buildTree();
+ /**
+ * recurse all visible files and updates them if necessary
+ * @see CatManListItem::checkUpdate
+ */
+ void checkUpdate();
+
+ /** this is called from KDirWatch when a directory has changed */
+ void directoryChanged(const QString& dir);
+ /** this is called from KDirWatch when a directory has been deleted */
+ void directoryDeleted(const QString& dir);
+
+ void showContentsMenu(QListViewItem *, const QPoint &, int col);
+ /** does the default action on the currently selected item*/
+ void activateItem(QListViewItem *);
+ /** emits the state of the selected item using selectedChanged*/
+ void checkSelected();
+ /** calls @ref activateItem with the selected item as argument*/
+ void slotOpenFile();
+ void slotOpenFileInNewWindow();
+ /** emits signal @ref openTemplate */
+ void slotOpenTemplate();
+ /** deletes the po-file on the disc, that belongs to the selected item */
+ void slotDeleteFile();
+ /** toggles the mark of the selected item */
+ void slotToggleMark();
+ /**
+ * toggles all marks in directory of current item (must be a directory)
+ */
+ void slotToggleMarksInDir();
+ void slotDirCommand(int);
+ void slotFileCommand(int);
+
+private slots:
+ void showOutput(KProcess *proc, char *buffer, int buflen);
+ void processEnded(KProcess *proc);
+ void columnClicked(QListViewItem * item, const QPoint & pnt, int c);
+
+ void slotToggleCVSOrSVNColumn( bool );
+
+ void slotValidPOCVSRepository( bool );
+ void slotValidPOSVNRepository( bool );
+ void slotValidPOTCVSRepository( bool );
+ void slotValidPOTSVNRepository( bool );
+
+private:
+ void toggleColumn( uint id, bool show);
+
+ void readMarker(KConfig *config);
+ void saveMarker(KConfig *config) const;
+ /**
+ * remove marked entries, which are not in the current file list
+ */
+ void updateMarkerList();
+
+ /**
+ * Mark or unmark entries.
+ *
+ * @param mark If true the items are marked, if false the marks are removed.
+ */
+ void setPatternMarks(bool mark);
+
+ /**
+ * deletes item with package name (relative directory) relDir
+ * and makes sure, that all subitems are removed from the lists
+ */
+ void deleteDirItem(QString relDir);
+
+ bool hasMatchingWords( QStringList &itemWords, QStringList &searchWords);
+
+ CatManListItem *itemBelow( CatManListItem *item );
+ CatManListItem *itemAbove( CatManListItem *item );
+
+ void validate_internal( const QStringList&, const KDataToolInfo &, const QString& );
+
+ void doCVSCommand( CVS::Command cmd, bool marked = false, bool templates = false );
+ void doSVNCommand( SVN::Command cmd, bool marked = false, bool templates = false );
+
+private:
+ QDict<CatManListItem> _dirList;
+ QDict<CatManListItem> _fileList;
+
+ KDirWatch *_dirWatch;
+ QTimer *_updateTimer;
+
+ // list of files for which was calculated the progress bar for reading file info
+ QStringList _readInfoFileList;
+ // current count of already read files in @ref @_readInfoFileList.
+ int _readInfoCount;
+
+ KBabel::CatManSettings _settings;
+
+ QStringList _markerList;
+
+ bool _active;
+ // stopping, application quit
+ bool _stop;
+ // stop searching, do not proceed to the next file
+ bool _stopSearch;
+ int _updateNesting;
+
+ QPtrList<KProcess> _pendingProcesses;
+
+ QTextEdit* _logView;
+ KDialogBase* _logWindow;
+ QPopupMenu* _fileContentsMenu;
+ QPopupMenu* _dirContentsMenu;
+ QPopupMenu* _dirCommandsMenu;
+ QPopupMenu* _fileCommandsMenu;
+
+ /** used for starting a drag */
+ QPoint _pressPos;
+
+ KBabelDictBox* _dictBox;
+
+ KBabel::KBabelMailer* mailer;
+
+ CVSHandler* cvshandler;
+ SVNHandler* svnhandler;
+
+ /// Is the PO path a valid CVS repository?
+ bool m_validPOCVSRepository;
+ /// Is the POT path a valid CVS repository?
+ bool m_validPOTCVSRepository;
+ /// Is the PO path a valid SVN repository?
+ bool m_validPOSVNRepository;
+ /// Is the POT path a valid SVN repository?
+ bool m_validPOTSVNRepository;
+
+ MarkPatternDialog * markPatternDialog;
+
+ //validation
+ ValidateProgressDialog* _validateDialog;
+ ValidationOptions* _validateOptions;
+ KDialogBase* _validateOptionsDlg;
+ bool _markAsFuzzy;
+ bool _ignoreFuzzy;
+
+ KBabel::Project::Ptr _project;
+};
+
+#endif // CATALOGMANAGERVIEW_H
diff --git a/kbabel/catalogmanager/catmanlistitem.cpp b/kbabel/catalogmanager/catmanlistitem.cpp
new file mode 100644
index 00000000..249cb053
--- /dev/null
+++ b/kbabel/catalogmanager/catmanlistitem.cpp
@@ -0,0 +1,932 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2001-2003 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#include "catmanresource.h"
+#include "catmanlistitem.h"
+#include "catalogmanagerview.h"
+#include "catalog.h"
+
+#include "resources.h"
+
+#include <klocale.h>
+
+#include <qfileinfo.h>
+#include <qdir.h>
+#include <qbitmap.h>
+#include <qlabel.h>
+#include <qpainter.h>
+
+#include <cvshandler.h>
+#include <svnhandler.h>
+
+using namespace KBabel;
+
+CatManListItem::CatManListItem(CatalogManagerView *view, QListViewItem* parent,QString fullPath,QString fullPotPath,QString package)
+ : QListViewItem(parent)
+{
+ _view = view;
+ init(fullPath,fullPotPath,package);
+}
+
+CatManListItem::CatManListItem(CatalogManagerView *view, QListView* parent,QString fullPath,QString fullPotPath)
+ : QListViewItem(parent)
+{
+ _primary=QFileInfo(fullPath);
+ _template=QFileInfo(fullPotPath);
+ _package="/";
+ _type=Dir;
+ _marked=false;
+ _view = view;
+
+ _hasPo=false;
+ _hasPot=false;
+ _hasErrors=false;
+
+ _primary.setCaching(false);
+ _template.setCaching(false);
+
+ setText(COL_NAME,i18n("Message Catalogs"));
+ setPixmap(COL_NAME,ICON_FOLDER_CLOSED_OK);
+}
+
+
+void CatManListItem::init(const QString& fullPath, const QString& fullPotPath, const QString& package)
+{
+ _primary=QFileInfo(fullPath);
+ _template=QFileInfo(fullPotPath);
+ _package=package;
+ _marked=false;
+
+ _hasPo=false;
+ _hasPot=false;
+ _hasErrors=false;
+
+ _primary.setCaching(false);
+ _template.setCaching(false);
+
+ // set
+ _lastUpdated=QDate(1900,1,1);
+
+ _wordList.clear();
+ _wordListUpdated = false;
+
+ update(parent()->isOpen(),false,true);
+
+ if( !isDir() ) setPixmap(COL_MARKER,ICON_NOFLAG);
+}
+
+void CatManListItem::setMarked(bool on)
+{
+ if(on)
+ {
+ setPixmap(COL_MARKER,ICON_FLAG);
+ }
+ else
+ {
+ setPixmap(COL_MARKER,ICON_NOFLAG);
+ }
+
+ _marked=on;
+}
+
+bool CatManListItem::marked() const
+{
+ if( isFile() ) return _marked;
+ else if( isDir() )
+ {
+ CatManListItem * myChild = (CatManListItem*)firstChild();
+ while( myChild )
+ {
+ if(myChild->isFile() && myChild->marked() ) return true;
+ else if(myChild->isDir() && myChild->marked() ) return true;
+ myChild = (CatManListItem*)myChild->nextSibling();
+ }
+
+ }
+ return false;
+}
+
+void CatManListItem::setOpen(bool open)
+{
+ bool needWork = needsWork();
+ QListViewItem::setOpen(open);
+
+ if(open && _type==Dir)
+ {
+ QPixmap icon;
+ icon = needWork ? ICON_FOLDER_OPEN_WORK : ICON_FOLDER_OPEN_OK;
+
+ if(!_template.exists())
+ {
+ icon=paintExclamation(&icon);
+ }
+
+ setPixmap(COL_NAME,icon);
+
+ CatManListItem * myChild = (CatManListItem*)firstChild();
+ while( myChild )
+ {
+ myChild->checkUpdate();
+ myChild = (CatManListItem*)myChild->nextSibling();
+ }
+ }
+ else
+ {
+ QPixmap icon;
+
+ if(needsWork())
+ icon = ICON_FOLDER_CLOSED_WORK;
+ else
+ icon = ICON_FOLDER_CLOSED_OK;
+
+ if(!_template.exists())
+ {
+ icon=paintExclamation(&icon);
+ }
+
+ setPixmap(COL_NAME,icon);
+ }
+
+}
+
+QStringList CatManListItem::allChildrenList(bool onlyFiles) const
+{
+ QStringList childrenList;
+
+ CatManListItem * myChild = (CatManListItem*)firstChild();
+ while( myChild )
+ {
+ QString name=myChild->package();
+
+ if(myChild->isFile())
+ {
+ childrenList.append(name);
+ }
+ else if(myChild->isDir())
+ {
+ if(!onlyFiles)
+ childrenList.append(name);
+
+ childrenList+=myChild->allChildrenList(onlyFiles);
+ }
+
+ myChild = (CatManListItem*)myChild->nextSibling();
+ }
+
+ return childrenList;
+}
+
+
+QStringList CatManListItem::allChildrenFileList(bool onlyFiles, bool emptyDirs, bool onlyModified) const
+{
+ QStringList childrenList;
+
+ CatManListItem * myChild = (CatManListItem*)firstChild();
+ while( myChild )
+ {
+ if(myChild->isFile() && myChild->hasPo() &&
+ !(!myChild->isModified() && onlyModified))
+ {
+ childrenList.append(myChild->poFile());
+ }
+ else if(myChild->isDir())
+ {
+ if(!onlyFiles && (emptyDirs || myChild->_primary.exists() ))
+ {
+ childrenList.append(myChild->poFile());
+ }
+
+ childrenList+=myChild->allChildrenFileList(onlyFiles,false,onlyModified);
+ }
+
+ myChild = (CatManListItem*)myChild->nextSibling();
+ }
+
+ return childrenList;
+}
+
+
+QStringList CatManListItem::contentsList(bool onlyFiles) const
+{
+ QStringList childList;
+
+ CatManListItem * myChild = (CatManListItem*)firstChild();
+ while( myChild )
+ {
+ QString name=myChild->package();
+
+ if(onlyFiles)
+ {
+ if(myChild->isFile())
+ {
+ childList.append(name);
+ }
+ }
+ else
+ {
+ childList.append(name);
+ }
+
+ myChild = (CatManListItem*)myChild->nextSibling();
+ }
+
+ return childList;
+}
+
+
+void CatManListItem::forceUpdate()
+{
+ update(true,true,false);
+}
+
+void CatManListItem::checkUpdate(bool noParents)
+{
+ // if a file has disappeared or is new
+ if(_hasPo != hasPo() || _hasPot != hasPot())
+ {
+ update(true,false,noParents);
+ }
+ else if(!isFile())
+ {
+ update(true,false,noParents);
+ }
+ else if(_hasPo && _lastUpdated < _primary.lastModified())
+ {
+ update(true,false,noParents);
+ }
+ else if(_hasPot && _lastUpdated < _template.lastModified())
+ {
+ update(true,false,noParents);
+ }
+}
+
+QString CatManListItem::key(int col, bool) const
+{
+ // show directories first
+ QString key=text(col);
+
+ if(col==COL_NAME)
+ {
+ if(_type==Dir)
+ {
+ key="a"+key;
+ }
+ else
+ {
+ key="b"+key;
+ }
+ }
+ // fuzzy, untranslated, total
+ else if(col==COL_FUZZY || col ==COL_TOTAL || col==COL_UNTRANS)
+ {
+ key=key.rightJustify(10,'0');
+ }
+ // marked po's
+ else if(col==COL_MARKER)
+ {
+ if(_marked)
+ {
+ key="1";
+ }
+ else
+ {
+ key="0";
+ }
+ }
+
+ return key;
+}
+
+void CatManListItem::update(bool showPoInfo,bool includeChildren
+ , bool noParents)
+{
+ if( _view->isStopped() ) return; // if parent view is stopped, we should stop as well
+
+ bool updateWordList = _view->settings().indexWords;
+
+ // flag, if something has changed and parent has to be updated
+ bool updateParent=false;
+
+ // update flags for files...
+ const bool hadPo=_hasPo;
+ _hasPo = hasPo();
+ const bool hadPot = _hasPot;
+ _hasPot = hasPot();
+
+ // and check if something changed
+ if(hadPo != _hasPo || hadPot != _hasPot)
+ updateParent=true;
+
+
+ if(_package!="/") // don't update root item
+ {
+ if(_primary.exists())
+ {
+ if(_primary.isDir())
+ {
+ QDir dir=_primary.dir();
+ setText(COL_NAME,dir.dirName());
+
+ // count the childen numbers
+ int fuzzy = 0;
+ int untrans = 0;
+ int total = 0;
+
+ CatManListItem* ch = static_cast<CatManListItem*>(firstChild ());
+
+ while (ch)
+ {
+ fuzzy += ch->fuzzy ();
+ untrans += ch->untranslated ();
+ total += ch->total ();
+ ch = static_cast<CatManListItem*>(ch->nextSibling());
+ }
+
+ setText(COL_FUZZY,QString::number(fuzzy));
+ setText(COL_UNTRANS,QString::number(untrans));
+ setText(COL_TOTAL,QString::number(total));
+
+ //setSelectable(false);
+ _type=Dir;
+
+ bool needWork = needsWork();
+ QPixmap icon;
+ if(!isOpen())
+ {
+ if( needWork )
+ icon = ICON_FOLDER_CLOSED_WORK;
+ else
+ icon = ICON_FOLDER_CLOSED_OK;
+ }
+ else
+ {
+ icon = needWork ? ICON_FOLDER_OPEN_WORK : ICON_FOLDER_OPEN_OK;
+ }
+
+ // check if the same directory exists also in the
+ // template directory
+ if(_template.isDir())
+ {
+ setPixmap( COL_NAME, icon );
+ }
+ else
+ {
+ QPixmap folder = icon;
+ icon=paintExclamation(&folder);
+
+ setPixmap(COL_NAME,folder);
+ }
+ }
+ else // primary is file
+ {
+ _type=File;
+ QString name=_primary.fileName();
+ setText(COL_NAME,name.left(name.length()-3));
+
+ if(showPoInfo)
+ {
+ _lastUpdated=QDateTime::currentDateTime();
+
+ bool neededWork=needsWork();
+ bool needWork=false;
+
+ PoInfo poInfo;
+ QPixmap icon = ICON_UPDATING;
+ setPixmap(COL_NAME,icon);
+ if ( PoInfo::info( _primary.absFilePath(), poInfo, _wordList, updateWordList, true, true ) == OK )
+ {
+ if( _view->isStopped() ) return;
+ if( updateWordList) _wordListUpdated = true;
+
+ _hasErrors=false;
+
+ const CVSHandler* cvsHandler = _view->cvsHandler();
+ const SVNHandler* svnHandler = _view->svnHandler();
+
+ const CVSHandler::FileStatus cvsFileStatus = cvsHandler->fstatus( poFile() );
+ const SVNHandler::FileStatus svnFileStatus = svnHandler->fstatus( poFile() );
+
+ _isModified = cvsHandler->isConsideredModified( cvsFileStatus )
+ || svnHandler->isConsideredModified( svnFileStatus );
+
+ QString versionControl;
+ if ( cvsFileStatus != CVSHandler::NO_REPOSITORY )
+ versionControl = cvsHandler->fileStatus( cvsFileStatus );
+ else if ( svnFileStatus != SVNHandler::NO_REPOSITORY )
+ versionControl = svnHandler->fileStatus( svnFileStatus );
+ else
+ versionControl = i18n("No version control");
+
+ setText(COL_FUZZY,QString::number(poInfo.fuzzy));
+ setText(COL_UNTRANS,QString::number(poInfo.untranslated));
+ setText(COL_TOTAL,QString::number(poInfo.total));
+ setText( COL_CVS_OR_SVN, versionControl );
+ setText(COL_REVISION,poInfo.revision);
+ setText(COL_TRANSLATOR,poInfo.lastTranslator);
+
+ if(needsWork())
+ {
+ icon=ICON_NEEDWORK;
+ needWork = true;
+ }
+ else
+ {
+ icon = ICON_OK;
+ needWork=false;
+ }
+ }
+ else
+ {
+ kdDebug(KBABEL_CATMAN) << "This file is broken" << endl;
+ if( _view->isStopped() ) return;
+ _hasErrors=true;
+ icon = ICON_BROKEN;
+ needWork=true;
+ }
+
+ if(!_template.exists())
+ {
+ icon=paintExclamation(&icon);
+ }
+
+ setPixmap(COL_NAME,icon);
+
+ updateParent=true;
+ }
+ }
+ }
+ // only the template exists
+ else if(_template.exists())
+ {
+ if(_template.isDir())
+ {
+ QDir dir=_template.dir();
+ setText(COL_NAME,dir.dirName());
+ //setSelectable(false);
+ _type=Dir;
+
+ // count the childen numbers
+ int total = 0;
+
+ CatManListItem* ch = static_cast<CatManListItem*>(firstChild ());
+
+ while (ch)
+ {
+ total += ch->total ();
+ ch = static_cast<CatManListItem*>(ch->nextSibling());
+ }
+
+ setText(COL_TOTAL,QString::number(total));
+
+
+ QPixmap icon;
+ if(!isOpen())
+ {
+ icon = ICON_FOLDER_CLOSED_WORK;
+ }
+ else
+ {
+ icon = needsWork() ? ICON_FOLDER_OPEN_WORK : ICON_FOLDER_OPEN_OK;
+ }
+
+ setPixmap(COL_NAME, icon );
+ }
+ // item is file
+ else
+ {
+ _type=File;
+ QString name=_primary.fileName();
+ setText(COL_NAME,name.left(name.length()-3));
+
+ if(showPoInfo)
+ {
+ _lastUpdated=QDateTime::currentDateTime();
+
+ // clean previous state information
+ setText(COL_FUZZY,QString::null);
+ setText(COL_UNTRANS,QString::null);
+ setText(COL_TOTAL,QString::null);
+ setText(COL_CVS_OR_SVN, QString::null);
+ setText(COL_REVISION, QString::null);
+ setText(COL_TRANSLATOR, QString::null);
+
+ setPixmap(COL_NAME,ICON_UPDATING);
+
+ PoInfo poInfo;
+ if ( PoInfo::info( _template.absFilePath(), poInfo, _wordList, false, true, true ) == OK )
+ {
+ if( _view->isStopped() ) return;
+ setText(COL_TOTAL,QString::number(poInfo.total));
+ }
+ if( _view->isStopped() ) return;
+ }
+ setPixmap(COL_NAME,ICON_MISSING);
+
+ updateParent = true;
+ }
+ }
+ else
+ {
+ kdWarning(KBABEL_CATMAN) << "whether po nor pot exists: " << _package << endl;
+ }
+ }
+
+ _view->fileInfoRead( package() );
+
+ if( _view->isStopped() ) return;
+
+ if(updateParent && !noParents)
+ {
+ updateParents();
+ }
+
+ if( _view->isStopped() ) return;
+
+ if(includeChildren)
+ {
+ CatManListItem *myChild = (CatManListItem*)firstChild();
+ while( myChild )
+ {
+ myChild->update(showPoInfo,includeChildren);
+ myChild = (CatManListItem*)myChild->nextSibling();
+ }
+ }
+
+ // HACK to get the signal emitted
+ if (isSelected( )) {
+ listView( )->setSelected(this, false);
+ listView( )->setSelected(this, true);
+ }
+}
+
+// we know that this item was saved and PoInfo contains new information
+// about this item, the item is file
+// however, is can be saved template or translation!!! - only translation is handled???
+void CatManListItem::updateAfterSave( PoInfo &poInfo )
+{
+ // flag, if something has changed and parent has to be updated
+ bool updateParent=false;
+
+ // update flags for files...
+ const bool hadPo=_hasPo;
+ _hasPo = hasPo();
+ const bool hadPot = _hasPot;
+ _hasPot = hasPot();
+
+ // and check if something changed
+ if(hadPo != _hasPo || hadPot != _hasPot)
+ updateParent=true;
+
+ if(_primary.exists())
+ {
+ // primary is existent file
+
+ _type=File;
+ QString name=_primary.fileName();
+ setText(COL_NAME,name.left(name.length()-3));
+
+ _lastUpdated=QDateTime::currentDateTime();
+
+ bool neededWork=needsWork();
+ bool needWork=false;
+
+ QPixmap icon;
+ _hasErrors=false;
+
+ const CVSHandler::FileStatus cvsFileStatus = _view->cvsHandler()->fstatus(poFile());
+ const SVNHandler::FileStatus svnFileStatus = _view->svnHandler()->fstatus(poFile());
+
+ QString versionControl;
+ if ( cvsFileStatus != CVSHandler::NO_REPOSITORY )
+ versionControl = _view->cvsHandler()->fileStatus( cvsFileStatus );
+ else if ( svnFileStatus != SVNHandler::NO_REPOSITORY )
+ versionControl = _view->svnHandler()->fileStatus( svnFileStatus );
+ else
+ versionControl = i18n("No version control");
+
+ setText(COL_FUZZY,QString::number(poInfo.fuzzy));
+ setText(COL_UNTRANS,QString::number(poInfo.untranslated));
+ setText(COL_TOTAL,QString::number(poInfo.total));
+ setText( COL_CVS_OR_SVN, versionControl );
+ setText(COL_REVISION,poInfo.revision);
+ setText(COL_TRANSLATOR,poInfo.lastTranslator);
+
+ if(needsWork())
+ {
+ icon=ICON_NEEDWORK;
+ needWork = true;
+ }
+ else
+ {
+ icon = ICON_OK;
+ needWork=false;
+ }
+
+ if(!_template.exists())
+ {
+ icon=paintExclamation(&icon);
+ }
+
+ setPixmap(COL_NAME,icon);
+
+ // if the status changed, update the parent item
+ if(needWork != neededWork)
+ {
+ updateParent=true;
+ }
+ }
+
+ if(updateParent)
+ {
+ updateParents();
+ }
+}
+
+
+void CatManListItem::updateParents()
+{
+ CatManListItem *item = (CatManListItem*)parent();
+ while( item && !_view->isStopped())
+ {
+ item->update(false,false);
+ item = (CatManListItem*)item->parent();
+ }
+}
+
+bool CatManListItem::hasPo() const
+{
+ return _primary.exists();
+}
+
+bool CatManListItem::hasPot() const
+{
+ return _template.exists();
+}
+
+bool CatManListItem::isModified() const
+{
+ return _isModified;
+}
+
+int CatManListItem::fuzzy() const
+{
+ bool success;
+ int number=text(COL_FUZZY).toInt(&success);
+ if(!success)
+ number=0;
+
+ return number;
+}
+
+int CatManListItem::untranslated() const
+{
+ bool success;
+ int number;
+ if( !hasPo() )
+ {
+ number=total();
+ }
+ else
+ {
+ number=text(COL_UNTRANS).toInt(&success);
+ if(!success)
+ number=0;
+ }
+
+ return number;
+}
+
+int CatManListItem::total() const
+{
+ bool success;
+ int number=text(COL_TOTAL).toInt(&success);
+ if(!success)
+ number=0;
+
+ return number;
+}
+
+bool CatManListItem::needsWork() const
+{
+ bool flag=false;
+
+ if(isFile())
+ {
+ if(!hasPo() || fuzzy() > 0 || untranslated() > 0 || _hasErrors)
+ flag=true;
+ }
+ else
+ {
+ CatManListItem *myChild = (CatManListItem*)firstChild();
+ while( myChild )
+ {
+ if( myChild->needsWork() )
+ {
+ flag=true;
+ myChild=0;
+ }
+ else
+ {
+ myChild = (CatManListItem*)myChild->nextSibling();
+ }
+ }
+ }
+
+ return flag;
+}
+
+bool CatManListItem::isDir() const
+{
+ return type()==Dir;
+}
+
+bool CatManListItem::isFile() const
+{
+ return type()==File;
+}
+
+QString CatManListItem::poFile() const
+{
+ return _primary.absFilePath();
+}
+
+QString CatManListItem::potFile() const
+{
+ return _template.absFilePath();
+}
+
+QString CatManListItem::package(bool rootSlash) const
+{
+ if(rootSlash)
+ return _package;
+ else
+ {
+ return _package.right(_package.length()-1);
+ }
+}
+
+QString CatManListItem::packageDir( ) const
+{
+ return ( _type == Dir ? _package : QString::null );
+}
+
+QString CatManListItem::name() const
+{
+ int index = _package.findRev("/");
+ return _package.right(_package.length()-index-1);
+}
+
+QPixmap CatManListItem::paintExclamation(QPixmap* pixmap)
+{
+ if(!pixmap || pixmap->isNull())
+ return QPixmap(0,0);
+
+ if(_package=="/" && _template.filePath().isEmpty())
+ return *pixmap;
+
+ if(isDir() && _package == _template.filePath())
+ return *pixmap;
+
+ if(isFile() && _package+".pot" == _template.filePath())
+ return *pixmap;
+
+ int width=pixmap->width();
+ int height=pixmap->height();
+
+ int diameter=QMIN(width,height);
+
+ QBitmap mask=pixmap->createHeuristicMask();
+
+ QPainter mp(&mask);
+ mp.setPen(QPen(Qt::color1,1));
+ mp.drawEllipse(width-diameter,height-diameter,diameter,diameter);
+
+ QPixmap result(width,height);
+
+ QPainter p(&result);
+ p.drawPixmap(0,0,*pixmap);
+ p.setPen( QPen(red,1) );
+ p.drawEllipse(width-diameter,height-diameter,diameter,diameter);
+
+ result.setMask(mask);
+
+ return result;
+}
+
+QListViewItem *CatManListItem::previousSibling()
+{
+ QListViewItem * i = parent();
+ if( !i ) return i;
+ i = i->firstChild();
+ if( !i ) return i;
+ if( i == this ) return 0;
+ while( i->nextSibling()!=this ) i = i->nextSibling();
+ return i;
+}
+
+QListViewItem *CatManListItem::lastChild()
+{
+ QListViewItem * i = firstChild();
+ if( !i ) return i;
+ while( i->nextSibling() ) i = i->nextSibling();
+ return i;
+}
+
+void CatManListItem::checkErrors(KDataTool* tool, QObject* progressSignalHandler, bool ignoreFuzzy, bool markAsFuzzy)
+{
+ bool hasError=false;
+ _errors.clear();
+ Catalog* cat = new Catalog();
+
+ QObject::connect( cat, SIGNAL( signalProgress(int) ), progressSignalHandler, SIGNAL( setValidationProgressBar(int)));
+ QObject::connect( cat, SIGNAL( signalResetProgressBar(QString, int) ), progressSignalHandler, SLOT( setupFileProgressBar(QString, int)));
+
+ if( cat->openURL(KURL( poFile() )) == OK )
+ {
+ kdDebug(KBABEL_CATMAN) << "File opened succesfully" << endl;
+ if( !cat->checkUsingTool(tool,true) )
+ {
+ hasError = true;
+ } else forceUpdate(); // no error, find out the new state
+ } else {
+ kdDebug(KBABEL_CATMAN) << "File not opened !!!!!" << endl;
+ hasError=true;
+ }
+
+ if( hasError )
+ {
+ QString errortext;
+ _hasErrors = true;
+
+ DocPosition dummy;
+ IgnoreItem i;
+ i.fileURL = poFile();
+
+ if( cat->hasError(0,dummy) && (!ignoreFuzzy || !cat->isFuzzy(0)))
+ {
+ i.msgid = cat->msgid(0);
+ i.msgstr = cat->msgstr(0);
+ i.index = 0;
+ _errors.append( i );
+
+ if( markAsFuzzy ) cat->setFuzzy(0, true);
+ }
+
+ int index=0;
+ do
+ {
+ index=cat->nextError(index,dummy);
+ if( index != -1 && (!ignoreFuzzy || !cat->isFuzzy(index) ) )
+ {
+ i.msgid = cat->msgid(index);
+ i.msgstr = cat->msgstr(index);
+ i.index = index;
+ _errors.append( i );
+ if( markAsFuzzy ) cat->setFuzzy(index, true);
+ }
+ } while(index>=0);
+
+ // change icon only if there were non-ignored errors
+ if( !_errors.isEmpty() )
+ {
+ setPixmap(COL_NAME, ICON_ERROR);
+ }
+
+ // if we changed fuzzy flags, save the result
+ if( cat->isModified() ) cat->saveFile();
+ }
+
+ delete cat;
+}
diff --git a/kbabel/catalogmanager/catmanlistitem.h b/kbabel/catalogmanager/catmanlistitem.h
new file mode 100644
index 00000000..a5f41e2f
--- /dev/null
+++ b/kbabel/catalogmanager/catmanlistitem.h
@@ -0,0 +1,238 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2001-2003 by Stanislav Visnovsky <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef CATMANLISTITEM_H
+#define CATMANLISTITEM_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qstringlist.h>
+#include <qlistview.h>
+#include <qdatetime.h>
+#include <qfileinfo.h>
+
+#include "validateprogress.h"
+
+class CatalogManagerView;
+class QPixmap;
+class KDataTool;
+
+namespace KBabel
+{
+ class PoInfo;
+}
+
+class CatManListItem : public QListViewItem
+{
+public:
+ /** the type of this item */
+ enum Type{File,Dir};
+
+ CatManListItem(CatalogManagerView *view, QListViewItem* parent,QString fullPath
+ ,QString fullPotPath,QString package);
+
+ /** creates the toplevel root item with package name "/" */
+ CatManListItem(CatalogManagerView *view, QListView* parent,QString fullPath, QString fullPotPath);
+
+ /**
+ * returns the package names (including relative path) of the
+ * children of this item
+ */
+ QStringList contentsList(bool onlyFiles=false) const;
+ /**
+ * returns the package names of all children of this item
+ * (including all subdirectries)
+ * @param onlyFiles flag, if only the names of files should be returned
+ * @see CatManListItem::contentsList
+ */
+ QStringList allChildrenList(bool onlyFiles=false) const;
+
+ /**
+ * returns the relative file names of all children of this item
+ * (including all subdirectries)
+ * @param onlyFiles flag, if only the names of files should be returned
+ * @param emptyDirs flag, if the empty dirs (dirs without PO files in them) should be returned
+ * @param onlyModified, if only modified files should be returned
+ * @see CatManListItem::contentsList
+ */
+ QStringList allChildrenFileList(bool onlyFiles=false, bool emptyDirs=false, bool onlyModified=false) const;
+
+ void setMarked(bool on);
+ bool marked() const;
+ /**
+ * checks if the file on the disc has changed,
+ * reads information about the file and displays it
+ * @param noParents flag, if the update has to include the parent
+ * of the item, if the status has changed. Since at the first build of
+ * the tree, the status of every item changes, this is not useful then.
+ */
+ void checkUpdate(bool noParents=false);
+ void forceUpdate();
+
+ /**
+ * checks the corresponding PO file using validation tool. On
+ * errors it fills the list of errors, which can be accessed
+ * using @see errors().
+ * @param validator instance of KDataTool to be used for checking
+ * @param progressSignalHangler widget, to which the checks should send progress signals
+ * @param ignoreFuzzy flag, whether fuzzy messages in the file should be not checked
+ * @param markAsFuzzy flag, whether the error messages should be marked as fuzzy (this alters the PO file)
+ */
+ void checkErrors(KDataTool* validator, QObject* progressSignalHandler, bool ignoreFuzzy, bool markAsFuzzy);
+
+ /** return the absolute filename of the po-File */
+ QString poFile() const;
+ /** return the absolute filename of the pot-File */
+ QString potFile() const;
+ /** returns the package name (inlcuding relative path to base-directory) */
+ QString package(bool rootSlash=true) const;
+
+ /** returns the relative path of a dir or QString::null if not a dir. */
+ QString packageDir( ) const;
+
+ /** returns the package name (without path) */
+ QString name() const;
+
+ /**
+ * returns the type of this item
+ * @see CatManListItem::Type
+ */
+ Type type() const{return _type;}
+ bool isDir() const;
+ bool isFile() const;
+ /** returns true, if the po-file exists*/
+ bool hasPo() const;
+ /** returns true, if the pot-file exists*/
+ bool hasPot() const;
+ bool isModified() const;
+ /**
+ * @return the number of fuzzy messages in the po-file,
+ * 0 if no po-file exists
+ */
+ int fuzzy() const;
+ /**
+ * @return the number of untranslated messages in the po-file,
+ * @ref total if no po-file exists
+ */
+ int untranslated() const;
+ /** @return number of messages in the po- or pot-file */
+ int total() const;
+ /**
+ * @return true, if there are untranslated or fuzzy items.
+ * If this item is a directory, it returns true, if a subitem
+ * contains untranslated or fuzzy items
+ */
+ bool needsWork() const;
+ /**
+ * @return true, if there were errors while parsing the file
+ */
+ bool hasErrors() const {return _hasErrors;}
+ QValueList<IgnoreItem> errors() const {return _errors;}
+
+ virtual QString key(int col,bool) const;
+ virtual void setOpen(bool);
+
+ /** paints the marking, if this package has no template */
+ QPixmap paintExclamation(QPixmap*);
+
+ void updateAfterSave( KBabel::PoInfo &po);
+
+ QStringList &wordList() { return _wordList; }
+ bool wordsUpdated() { return _wordListUpdated; }
+
+ /** These are not in Qt, so we need to implement it ourselves*/
+ QListViewItem *previousSibling();
+ QListViewItem *lastChild();
+
+private:
+ void init(const QString& fullPath, const QString& fullPotPath,const QString& package);
+ /**
+ * updates the item
+ * @param showPoInfo if true, reads information about the
+ * file using @ref Catalog::info
+ * ( slow for big files )
+ * @param includeChildren flag, if possible children should be updated,too
+ * @param noParents flag, if parents should be updated, when state
+ * of the item has changed
+ */
+ void update(bool showPoInfo=true,bool includeChildren=false
+ , bool noParents=false );
+ void updateParents();
+
+private:
+ /**
+ * holds the date and the time this item was
+ * last updated. This is used to check, if the file
+ * on the disc has changed since last update.
+ */
+ QDateTime _lastUpdated;
+
+ /** the po-file */
+ QFileInfo _primary;
+ /** the pot-file */
+ QFileInfo _template;
+ /**
+ * The package name, includes the relative path beginning
+ * at the base directory.
+ * The package name begins with "/" and if this is a directory it end with "/"
+ * The root item has the package name "/"
+ * @see CatManListItem::CatManListItem
+ */
+ QString _package;
+ Type _type;
+ bool _marked;
+
+ /** flag, to detect if file has been deleted or is new */
+ bool _hasPo;
+ /** flag, to detect if file has been deleted or is new */
+ bool _hasPot;
+
+ bool _isModified;
+ /** flag, to detect if file has been modified or new */
+
+ /** flag, if the PO-file has a syntax error */
+ bool _hasErrors;
+ /** a list of errors found by validation tool*/
+ QValueList<IgnoreItem> _errors;
+
+ /** parent view for this item, used for stopping the activity */
+ CatalogManagerView *_view;
+
+ /** index of words, but it does not contain any useful information as values */
+ QStringList _wordList;
+ bool _wordListUpdated;
+};
+
+#endif // CATMANLISTITEM_H
diff --git a/kbabel/catalogmanager/catmanresource.h b/kbabel/catalogmanager/catmanresource.h
new file mode 100644
index 00000000..06b3ac33
--- /dev/null
+++ b/kbabel/catalogmanager/catmanresource.h
@@ -0,0 +1,73 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2001-2002 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#ifndef CATMANRESOURCE_H
+#define CATMANRESOURCE_H
+
+#include <kiconloader.h>
+
+#define COL_NAME 0
+#define COL_MARKER 1
+#define COL_FUZZY 2
+#define COL_UNTRANS 3
+#define COL_TOTAL 4
+#define COL_CVS_OR_SVN 5
+#define COL_REVISION 6
+#define COL_TRANSLATOR 7
+
+#define ICON_OK UserIcon("ok",KIcon::DefaultState)
+#define ICON_MISSING UserIcon("missing",KIcon::DefaultState)
+#define ICON_NEEDWORK UserIcon("needwork",KIcon::DefaultState)
+#define ICON_BROKEN UserIcon("broken",KIcon::DefaultState)
+#define ICON_UPDATING SmallIcon("reload")
+#define ICON_FLAG SmallIcon("flag")
+#define ICON_FOLDER_CLOSED_OK SmallIcon("folder_green")
+#define ICON_FOLDER_CLOSED_WORK SmallIcon("folder_red")
+#define ICON_FOLDER_OPEN_OK SmallIcon("folder_green_open")
+#define ICON_FOLDER_OPEN_WORK SmallIcon("folder_red_open")
+#define ICON_ERROR UserIcon("error",KIcon::DefaultState)
+#define ICON_NOFLAG UserIcon("noflag",KIcon::DefaultState)
+
+// Needed for determining which actions should be enabled and which not.
+#define NEEDS_PO 1
+#define NEEDS_POT 2
+#define NEEDS_MARK 4
+#define NEEDS_DIR 8
+#define NEEDS_PO_CVS 16
+#define NEEDS_POT_CVS 32
+#define NEEDS_PO_SVN 64
+#define NEEDS_POT_SVN 128
+
+#endif
diff --git a/kbabel/catalogmanager/findinfilesdialog.cpp b/kbabel/catalogmanager/findinfilesdialog.cpp
new file mode 100644
index 00000000..b11a20d8
--- /dev/null
+++ b/kbabel/catalogmanager/findinfilesdialog.cpp
@@ -0,0 +1,229 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include "findinfilesdialog.h"
+
+#include <qcheckbox.h>
+#include <qgroupbox.h>
+#include <qlayout.h>
+#include <qwhatsthis.h>
+
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <klocale.h>
+
+using namespace KBabel;
+
+FindInFilesDialog::FindInFilesDialog(bool forReplace, QWidget* parent)
+ :FindDialog(forReplace, parent)
+{
+ QGroupBox* box = new QGroupBox(2, Qt::Horizontal, i18n("File Options"), mainWidget());
+ mainWidget()->layout()->add(box);
+
+ _inAllFiles = new QCheckBox(i18n("&In all files"),box);
+ _inMarked = new QCheckBox(i18n("&Marked files"),box);
+ _inTemplates = new QCheckBox(i18n("In &templates"),box);
+ _askForNextFile = new QCheckBox(i18n("Ask before ne&xt file"),box);
+ _askForSave = new QCheckBox(i18n("Save &without asking"),box);
+
+ QWhatsThis::add(box,i18n("<qt><p><b>File Options</b></p>"
+ "<p>Here you can finetune where to find:"
+ "<ul><li><b>In all files</b>: search in all files, otherwise searched "
+ "is the selected file or files in the selected folder</li>"
+ "<li><b>Ask before next file</b>: show a dialog asking to proceed to the next file</li>"
+ "</ul></qt>"));
+
+ readSettings();
+}
+
+FindInFilesDialog::~FindInFilesDialog()
+{
+ saveSettings();
+}
+
+int FindInFilesDialog::show(QString initialStr)
+{
+
+ FindDialog::show(initialStr);
+
+ int r = result();
+
+ if( r == QDialog::Accepted ) {
+ if( isReplaceDialog() ) {
+ ReplaceOptions options = replaceOpts();
+ options.inAllFiles = _inAllFiles->isChecked();
+ options.inMarkedFiles = _inMarked->isChecked();
+ options.inTemplates = _inTemplates->isChecked();
+ options.askForNextFile = _askForNextFile->isChecked();
+ options.askForSave = !_askForSave->isChecked();
+ FindDialog::setReplaceOpts(options);
+ }
+ else {
+ FindOptions options = findOpts();
+ options.inAllFiles = _inAllFiles->isChecked();
+ options.inMarkedFiles = _inMarked->isChecked();
+ options.inTemplates = _inTemplates->isChecked();
+ options.askForNextFile = _askForNextFile->isChecked();
+ options.askForSave = !_askForSave->isChecked();
+ FindDialog::setFindOpts( options );
+ }
+ }
+
+ return r;
+}
+
+int FindInFilesDialog::exec(QString initialStr)
+{
+ FindDialog::exec(initialStr);
+
+ int r = result();
+
+ if( r == QDialog::Accepted ) {
+ if(isReplaceDialog()) {
+ ReplaceOptions options = replaceOpts();
+ options.inAllFiles = _inAllFiles->isChecked();
+ options.inMarkedFiles = _inMarked->isChecked();
+ options.inTemplates = _inTemplates->isChecked();
+ options.askForNextFile = _askForNextFile->isChecked();
+ options.askForSave = !_askForSave->isChecked();
+ FindDialog::setReplaceOpts(options);
+ }
+ else {
+ FindOptions options = findOpts();
+ options.inAllFiles = _inAllFiles->isChecked();
+ options.inMarkedFiles = _inMarked->isChecked();
+ options.inTemplates = _inTemplates->isChecked();
+ options.askForNextFile = _askForNextFile->isChecked();
+ options.askForSave = !_askForSave->isChecked();
+ FindDialog::setFindOpts( options );
+ }
+ }
+
+ return r;
+}
+
+void FindInFilesDialog::setFindOpts(FindOptions options)
+{
+ FindDialog::setFindOpts(options);
+
+ _inAllFiles->setChecked(options.inAllFiles);
+ _inTemplates->setChecked(options.inTemplates);
+ _inMarked->setChecked(options.inMarkedFiles);
+ _askForNextFile->setChecked(options.askForNextFile);
+ _askForSave->setChecked(!options.askForSave);
+}
+
+void FindInFilesDialog::setReplaceOpts(ReplaceOptions options)
+{
+ FindDialog::setReplaceOpts(options);
+
+ _inAllFiles->setChecked(options.inAllFiles);
+ _inTemplates->setChecked(options.inTemplates);
+ _inMarked->setChecked(options.inMarkedFiles);
+ _askForNextFile->setChecked(options.askForNextFile);
+ _askForSave->setChecked(!options.askForSave);
+}
+
+void FindInFilesDialog::readSettings()
+{
+ KConfig* config = KGlobal::config();
+
+ if(isReplaceDialog()) {
+ KConfigGroupSaver cgs(config,"ReplaceDialog");
+
+ ReplaceOptions options = replaceOpts();
+
+ options.inAllFiles = config->readBoolEntry("AllFiles", false);
+ options.inTemplates = config->readBoolEntry("InTemplates", false);
+ options.inMarkedFiles = config->readBoolEntry("InMarked", false);
+ options.askForNextFile = config->readBoolEntry("AskForNextFile", true);
+ options.askForSave = config->readBoolEntry("AskForSave", true);
+
+ _inAllFiles->setChecked(options.inAllFiles);
+ _inTemplates->setChecked(options.inTemplates);
+ _inMarked->setChecked(options.inMarkedFiles);
+ _askForNextFile->setChecked(options.askForNextFile);
+ _askForSave->setChecked(!options.askForSave);
+
+ FindDialog::setReplaceOpts(options);
+ }
+ else {
+ KConfigGroupSaver cgs(config,"FindDialog");
+
+ FindOptions options = findOpts();
+
+ options.inAllFiles = config->readBoolEntry("AllFiles", false);
+ options.inTemplates = config->readBoolEntry("InTemplates", false);
+ options.inMarkedFiles = config->readBoolEntry("InMarked", false);
+ options.askForNextFile = config->readBoolEntry("AskForNextFile", true);
+ options.askForSave = config->readBoolEntry("AskForSave", true);
+
+ _inAllFiles->setChecked(options.inAllFiles);
+ _inTemplates->setChecked(options.inTemplates);
+ _inMarked->setChecked(options.inMarkedFiles);
+ _askForNextFile->setChecked(options.askForNextFile);
+ _askForSave->setChecked(!options.askForSave);
+
+ FindDialog::setFindOpts(options);
+ }
+
+}
+
+void FindInFilesDialog::saveSettings()
+{
+ KConfig* config = KGlobal::config();
+
+ if(isReplaceDialog()) {
+ KConfigGroupSaver cgs(config,"ReplaceDialog");
+ ReplaceOptions options = replaceOpts();
+
+ config->writeEntry("AllFiles", options.inAllFiles);
+ config->writeEntry("InMarked", options.inMarkedFiles);
+ config->writeEntry("InTemplates", options.inTemplates);
+ config->writeEntry("AskForNextFile",options.askForNextFile);
+ config->writeEntry("AskForSave",options.askForSave);
+ }
+ else {
+ KConfigGroupSaver cgs(config,"FindDialog");
+
+ FindOptions options = findOpts();
+
+ config->writeEntry("AllFiles", options.inAllFiles);
+ config->writeEntry("InMarked", options.inMarkedFiles);
+ config->writeEntry("InTemplates", options.inTemplates);
+ config->writeEntry("AskForNextFile",options.askForNextFile);
+ config->writeEntry("AskForSave",options.askForSave);
+ }
+}
+
+#include "findinfilesdialog.moc"
diff --git a/kbabel/catalogmanager/findinfilesdialog.h b/kbabel/catalogmanager/findinfilesdialog.h
new file mode 100644
index 00000000..fd25f845
--- /dev/null
+++ b/kbabel/catalogmanager/findinfilesdialog.h
@@ -0,0 +1,85 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef FINDINFILESDIALOG_H
+#define FINDINFILESDIALOG_H
+
+#include "findoptions.h"
+#include "finddialog.h"
+
+class QCheckBox;
+
+class FindInFilesDialog : public FindDialog
+{
+ Q_OBJECT
+public:
+ /**
+ * Constructor
+ * @param replaceDlg flag, if this is a replace dialog
+ */
+ FindInFilesDialog(bool replaceDlg, QWidget* parent);
+ ~FindInFilesDialog();
+
+ /**
+ * shows the dialog
+ * @param initialStr string to display in find field.
+ * If empty, the last used string is used.
+ *
+ * @return the result code of the dialog
+ */
+ int show(QString initialStr);
+
+ /**
+ * executes the dialog as modal
+ * @param initialStr string to display in find field.
+ * If empty, the last used string is used.
+ *
+ * @return the result code of the dialog
+ */
+ int exec(QString initialStr);
+
+ void setFindOpts(KBabel::FindOptions options);
+ void setReplaceOpts(KBabel::ReplaceOptions options);
+
+protected:
+ void readSettings();
+ void saveSettings();
+
+private:
+ QCheckBox *_inAllFiles;
+ QCheckBox *_inTemplates;
+ QCheckBox *_inMarked;
+ QCheckBox *_askForNextFile;
+ QCheckBox *_askForSave;
+};
+
+#endif // FINDDIALOG_H
diff --git a/kbabel/catalogmanager/future.cpp b/kbabel/catalogmanager/future.cpp
new file mode 100644
index 00000000..4c9c8a90
--- /dev/null
+++ b/kbabel/catalogmanager/future.cpp
@@ -0,0 +1,17 @@
+// This files holds a few user-visible messages that will be needed by the SVN support
+
+// Misc. messages already existing in the kbabel-svn branch
+i18n("SVN");
+i18n( "CVS/SVN Status" );
+
+// Messages for further SVN functions
+i18n( "Resolved" );
+i18n( "Resolved for Marked" );
+i18n( "Revert" );
+i18n( "Revert for Marked" );
+i18n( "Cleanup" );
+i18n( "Cleanup for Marked" );
+
+// Messages that will probably not be needed
+i18n( "No repository" );
+
diff --git a/kbabel/catalogmanager/hi16-app-catalogmanager.png b/kbabel/catalogmanager/hi16-app-catalogmanager.png
new file mode 100644
index 00000000..c2a3ef67
--- /dev/null
+++ b/kbabel/catalogmanager/hi16-app-catalogmanager.png
Binary files differ
diff --git a/kbabel/catalogmanager/hi22-app-catalogmanager.png b/kbabel/catalogmanager/hi22-app-catalogmanager.png
new file mode 100644
index 00000000..3b9dfecc
--- /dev/null
+++ b/kbabel/catalogmanager/hi22-app-catalogmanager.png
Binary files differ
diff --git a/kbabel/catalogmanager/hi32-app-catalogmanager.png b/kbabel/catalogmanager/hi32-app-catalogmanager.png
new file mode 100644
index 00000000..3601807e
--- /dev/null
+++ b/kbabel/catalogmanager/hi32-app-catalogmanager.png
Binary files differ
diff --git a/kbabel/catalogmanager/hi48-app-catalogmanager.png b/kbabel/catalogmanager/hi48-app-catalogmanager.png
new file mode 100644
index 00000000..8d5090ea
--- /dev/null
+++ b/kbabel/catalogmanager/hi48-app-catalogmanager.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/Makefile.am b/kbabel/catalogmanager/icons/Makefile.am
new file mode 100644
index 00000000..f6ca354f
--- /dev/null
+++ b/kbabel/catalogmanager/icons/Makefile.am
@@ -0,0 +1,5 @@
+# Add all of your pixmaps here
+icons_ICON = AUTO
+
+# This is where it will all be installed
+iconsdir = $(kde_datadir)/kbabel/icons
diff --git a/kbabel/catalogmanager/icons/hi16-action-nextmarked.png b/kbabel/catalogmanager/icons/hi16-action-nextmarked.png
new file mode 100644
index 00000000..1e71607f
--- /dev/null
+++ b/kbabel/catalogmanager/icons/hi16-action-nextmarked.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/hi16-action-nextpo.png b/kbabel/catalogmanager/icons/hi16-action-nextpo.png
new file mode 100644
index 00000000..650ec8e9
--- /dev/null
+++ b/kbabel/catalogmanager/icons/hi16-action-nextpo.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/hi16-action-nexttemplate.png b/kbabel/catalogmanager/icons/hi16-action-nexttemplate.png
new file mode 100644
index 00000000..8422a3c6
--- /dev/null
+++ b/kbabel/catalogmanager/icons/hi16-action-nexttemplate.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/hi16-action-prevmarked.png b/kbabel/catalogmanager/icons/hi16-action-prevmarked.png
new file mode 100644
index 00000000..880e694d
--- /dev/null
+++ b/kbabel/catalogmanager/icons/hi16-action-prevmarked.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/hi16-action-prevpo.png b/kbabel/catalogmanager/icons/hi16-action-prevpo.png
new file mode 100644
index 00000000..f5e668c4
--- /dev/null
+++ b/kbabel/catalogmanager/icons/hi16-action-prevpo.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/hi16-action-prevtemplate.png b/kbabel/catalogmanager/icons/hi16-action-prevtemplate.png
new file mode 100644
index 00000000..4b799896
--- /dev/null
+++ b/kbabel/catalogmanager/icons/hi16-action-prevtemplate.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/hi16-action-statistics.png b/kbabel/catalogmanager/icons/hi16-action-statistics.png
new file mode 100644
index 00000000..456be360
--- /dev/null
+++ b/kbabel/catalogmanager/icons/hi16-action-statistics.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/hi16-action-syntax.png b/kbabel/catalogmanager/icons/hi16-action-syntax.png
new file mode 100644
index 00000000..221c3b87
--- /dev/null
+++ b/kbabel/catalogmanager/icons/hi16-action-syntax.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/hi22-action-nextmarked.png b/kbabel/catalogmanager/icons/hi22-action-nextmarked.png
new file mode 100644
index 00000000..020ead66
--- /dev/null
+++ b/kbabel/catalogmanager/icons/hi22-action-nextmarked.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/hi22-action-nextpo.png b/kbabel/catalogmanager/icons/hi22-action-nextpo.png
new file mode 100644
index 00000000..8579fefd
--- /dev/null
+++ b/kbabel/catalogmanager/icons/hi22-action-nextpo.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/hi22-action-nexttemplate.png b/kbabel/catalogmanager/icons/hi22-action-nexttemplate.png
new file mode 100644
index 00000000..064ab5bd
--- /dev/null
+++ b/kbabel/catalogmanager/icons/hi22-action-nexttemplate.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/hi22-action-prevmarked.png b/kbabel/catalogmanager/icons/hi22-action-prevmarked.png
new file mode 100644
index 00000000..38113a73
--- /dev/null
+++ b/kbabel/catalogmanager/icons/hi22-action-prevmarked.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/hi22-action-prevpo.png b/kbabel/catalogmanager/icons/hi22-action-prevpo.png
new file mode 100644
index 00000000..883ca21a
--- /dev/null
+++ b/kbabel/catalogmanager/icons/hi22-action-prevpo.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/hi22-action-prevtemplate.png b/kbabel/catalogmanager/icons/hi22-action-prevtemplate.png
new file mode 100644
index 00000000..0def2356
--- /dev/null
+++ b/kbabel/catalogmanager/icons/hi22-action-prevtemplate.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/hi22-action-statistics.png b/kbabel/catalogmanager/icons/hi22-action-statistics.png
new file mode 100644
index 00000000..aff3294f
--- /dev/null
+++ b/kbabel/catalogmanager/icons/hi22-action-statistics.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/hi22-action-syntax.png b/kbabel/catalogmanager/icons/hi22-action-syntax.png
new file mode 100644
index 00000000..d0c7decc
--- /dev/null
+++ b/kbabel/catalogmanager/icons/hi22-action-syntax.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/hi32-action-nextmarked.png b/kbabel/catalogmanager/icons/hi32-action-nextmarked.png
new file mode 100644
index 00000000..32cd2f48
--- /dev/null
+++ b/kbabel/catalogmanager/icons/hi32-action-nextmarked.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/hi32-action-nextpo.png b/kbabel/catalogmanager/icons/hi32-action-nextpo.png
new file mode 100644
index 00000000..2320ecf8
--- /dev/null
+++ b/kbabel/catalogmanager/icons/hi32-action-nextpo.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/hi32-action-nexttemplate.png b/kbabel/catalogmanager/icons/hi32-action-nexttemplate.png
new file mode 100644
index 00000000..be6e8c04
--- /dev/null
+++ b/kbabel/catalogmanager/icons/hi32-action-nexttemplate.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/hi32-action-prevmarked.png b/kbabel/catalogmanager/icons/hi32-action-prevmarked.png
new file mode 100644
index 00000000..b9c85a05
--- /dev/null
+++ b/kbabel/catalogmanager/icons/hi32-action-prevmarked.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/hi32-action-prevpo.png b/kbabel/catalogmanager/icons/hi32-action-prevpo.png
new file mode 100644
index 00000000..28d31e80
--- /dev/null
+++ b/kbabel/catalogmanager/icons/hi32-action-prevpo.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/hi32-action-prevtemplate.png b/kbabel/catalogmanager/icons/hi32-action-prevtemplate.png
new file mode 100644
index 00000000..0f9e9c0c
--- /dev/null
+++ b/kbabel/catalogmanager/icons/hi32-action-prevtemplate.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/hi32-action-statistics.png b/kbabel/catalogmanager/icons/hi32-action-statistics.png
new file mode 100644
index 00000000..5f428a65
--- /dev/null
+++ b/kbabel/catalogmanager/icons/hi32-action-statistics.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/hi32-action-syntax.png b/kbabel/catalogmanager/icons/hi32-action-syntax.png
new file mode 100644
index 00000000..0be5c2db
--- /dev/null
+++ b/kbabel/catalogmanager/icons/hi32-action-syntax.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/lo16-action-nextmarked.png b/kbabel/catalogmanager/icons/lo16-action-nextmarked.png
new file mode 100644
index 00000000..fdbb9664
--- /dev/null
+++ b/kbabel/catalogmanager/icons/lo16-action-nextmarked.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/lo16-action-nextpo.png b/kbabel/catalogmanager/icons/lo16-action-nextpo.png
new file mode 100644
index 00000000..b9d0ce11
--- /dev/null
+++ b/kbabel/catalogmanager/icons/lo16-action-nextpo.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/lo16-action-nexttemplate.png b/kbabel/catalogmanager/icons/lo16-action-nexttemplate.png
new file mode 100644
index 00000000..979ba277
--- /dev/null
+++ b/kbabel/catalogmanager/icons/lo16-action-nexttemplate.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/lo16-action-prevmarked.png b/kbabel/catalogmanager/icons/lo16-action-prevmarked.png
new file mode 100644
index 00000000..b712b63c
--- /dev/null
+++ b/kbabel/catalogmanager/icons/lo16-action-prevmarked.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/lo16-action-prevpo.png b/kbabel/catalogmanager/icons/lo16-action-prevpo.png
new file mode 100644
index 00000000..3736c141
--- /dev/null
+++ b/kbabel/catalogmanager/icons/lo16-action-prevpo.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/lo16-action-prevtemplate.png b/kbabel/catalogmanager/icons/lo16-action-prevtemplate.png
new file mode 100644
index 00000000..62b3746d
--- /dev/null
+++ b/kbabel/catalogmanager/icons/lo16-action-prevtemplate.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/lo16-action-statistics.png b/kbabel/catalogmanager/icons/lo16-action-statistics.png
new file mode 100644
index 00000000..1c298a5b
--- /dev/null
+++ b/kbabel/catalogmanager/icons/lo16-action-statistics.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/lo16-action-syntax.png b/kbabel/catalogmanager/icons/lo16-action-syntax.png
new file mode 100644
index 00000000..79fea79a
--- /dev/null
+++ b/kbabel/catalogmanager/icons/lo16-action-syntax.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/lo22-action-statistics.png b/kbabel/catalogmanager/icons/lo22-action-statistics.png
new file mode 100644
index 00000000..00ee1475
--- /dev/null
+++ b/kbabel/catalogmanager/icons/lo22-action-statistics.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/lo22-action-syntax.png b/kbabel/catalogmanager/icons/lo22-action-syntax.png
new file mode 100644
index 00000000..801b8cc4
--- /dev/null
+++ b/kbabel/catalogmanager/icons/lo22-action-syntax.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/lo32-action-nextmarked.png b/kbabel/catalogmanager/icons/lo32-action-nextmarked.png
new file mode 100644
index 00000000..ded540c2
--- /dev/null
+++ b/kbabel/catalogmanager/icons/lo32-action-nextmarked.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/lo32-action-nextpo.png b/kbabel/catalogmanager/icons/lo32-action-nextpo.png
new file mode 100644
index 00000000..e0fcc825
--- /dev/null
+++ b/kbabel/catalogmanager/icons/lo32-action-nextpo.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/lo32-action-nexttemplate.png b/kbabel/catalogmanager/icons/lo32-action-nexttemplate.png
new file mode 100644
index 00000000..da024779
--- /dev/null
+++ b/kbabel/catalogmanager/icons/lo32-action-nexttemplate.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/lo32-action-prevmarked.png b/kbabel/catalogmanager/icons/lo32-action-prevmarked.png
new file mode 100644
index 00000000..942587eb
--- /dev/null
+++ b/kbabel/catalogmanager/icons/lo32-action-prevmarked.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/lo32-action-prevpo.png b/kbabel/catalogmanager/icons/lo32-action-prevpo.png
new file mode 100644
index 00000000..55cb73a3
--- /dev/null
+++ b/kbabel/catalogmanager/icons/lo32-action-prevpo.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/lo32-action-prevtemplate.png b/kbabel/catalogmanager/icons/lo32-action-prevtemplate.png
new file mode 100644
index 00000000..eb485afc
--- /dev/null
+++ b/kbabel/catalogmanager/icons/lo32-action-prevtemplate.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/lo32-action-statistics.png b/kbabel/catalogmanager/icons/lo32-action-statistics.png
new file mode 100644
index 00000000..298e4577
--- /dev/null
+++ b/kbabel/catalogmanager/icons/lo32-action-statistics.png
Binary files differ
diff --git a/kbabel/catalogmanager/icons/lo32-action-syntax.png b/kbabel/catalogmanager/icons/lo32-action-syntax.png
new file mode 100644
index 00000000..4292ffaf
--- /dev/null
+++ b/kbabel/catalogmanager/icons/lo32-action-syntax.png
Binary files differ
diff --git a/kbabel/catalogmanager/libcvs/Makefile.am b/kbabel/catalogmanager/libcvs/Makefile.am
new file mode 100644
index 00000000..e3e4f9ac
--- /dev/null
+++ b/kbabel/catalogmanager/libcvs/Makefile.am
@@ -0,0 +1,11 @@
+noinst_LTLIBRARIES = libcatalogmanagercvs.la
+
+# set the include path for X, qt and KDE
+INCLUDES = -I.. -I../../common $(all_includes)
+
+libcatalogmanagercvs_la_SOURCES = cvshandler.cpp cvsdialog.cpp
+
+noinst_HEADERS = cvshandler.h cvsdialog.h cvsresources.h
+
+# let automoc handle all of the meta source files (moc)
+METASOURCES = AUTO
diff --git a/kbabel/catalogmanager/libcvs/cvsdialog.cpp b/kbabel/catalogmanager/libcvs/cvsdialog.cpp
new file mode 100644
index 00000000..af76d9d0
--- /dev/null
+++ b/kbabel/catalogmanager/libcvs/cvsdialog.cpp
@@ -0,0 +1,423 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002-2003 by Marco Wegner <mail@marcowegner.de>
+ Copyright (C) 2005, 2006 by Nicolas GOUTTE <goutte@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+// Qt include files
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qfileinfo.h>
+#include <qframe.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qlistbox.h>
+#include <qpushbutton.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qtextedit.h>
+#include <qtextcodec.h>
+// KDE include files
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kprocess.h>
+#include <ktempfile.h>
+#include <kmessagebox.h>
+#include <kstringhandler.h>
+#include <kcombobox.h>
+#include <kcharsets.h>
+// Project specific include files
+#include "cvsdialog.h"
+
+
+CVSDialog::CVSDialog( CVS::Command cmd, QWidget * parent, KSharedConfig* config )
+ : KDialog( parent, "CVSDIALOG", true ), m_config( config )
+{
+ _cmd = cmd;
+ p=0L;
+ setCaption( i18n( "CVS Dialog" ) );
+
+ QString temp;
+
+ QVBoxLayout * layout = new QVBoxLayout( this, 6, 6, "MAIN LAYOUT" );
+
+ // Set the label's text depending on the CVS command.
+ switch ( cmd ) {
+ case CVS::Update:
+ temp = i18n( "Update the following files:" );
+ break;
+ case CVS::Commit:
+ temp = i18n( "Commit the following files:" );
+ break;
+ case CVS::Status:
+ temp = i18n( "Get status for the following files:" );
+ break;
+ case CVS::Diff:
+ temp = i18n( "Get diff for the following files:" );
+ break;
+ }
+ layout->addWidget( new QLabel( temp, this ) );
+
+ // Widget for showing the list of files.
+ filebox = new QListBox( this );
+ layout->addWidget( filebox );
+
+ // Add special widgets for 'cvs commit'.
+ if ( cmd == CVS::Commit ) {
+ QLabel * label;
+
+ // Combobox for displaying old log messages.
+ label = new QLabel( i18n( "&Old messages:" ), this );
+ oldMessages = new QComboBox( this );
+ oldMessages->setDuplicatesEnabled( false );
+ label->setBuddy( oldMessages );
+ layout->addWidget( label );
+ layout->addWidget( oldMessages );
+
+ // Textfield for entering a log message.
+ label = new QLabel( i18n( "&Log message:" ), this );
+ logedit = new QTextEdit( this );
+ label->setBuddy( logedit );
+ layout->addWidget( label );
+ layout->addWidget( logedit );
+
+ label = new QLabel( i18n( "E&ncoding:" ), this );
+ m_encodingComboBox = new KComboBox( this );
+ label->setBuddy( m_encodingComboBox );
+ layout->addWidget( label );
+ layout->addWidget( m_encodingComboBox );
+ QStringList encodingList;
+ // The last encoding will be added at the top of the list, when the seetings will be read.
+ encodingList << i18n( "Descriptive encoding name", "Recommended ( %1 )" ).arg( "UTF-8" );
+ encodingList << i18n( "Descriptive encoding name", "Locale ( %1 )" ).arg( QTextCodec::codecForLocale()->mimeName() );
+ encodingList += KGlobal::charsets()->descriptiveEncodingNames();
+ m_encodingComboBox->insertStringList( encodingList );
+
+ connect( oldMessages, SIGNAL( activated( int ) ),
+ this, SLOT( slotComboActivated( int ) ) );
+ }
+
+ QHBoxLayout * buttons = new QHBoxLayout( 0, 0, 6, "BUTTON LAYOUT" );
+ // Add special buttons for 'cvs commit'.
+ if ( cmd == CVS::Commit ) {
+ autoAddBox = new QCheckBox( i18n( "Auto&matically add files if necessary" ), this );
+ buttons->addWidget( autoAddBox );
+ }
+ buttons->addItem( new QSpacerItem( 1, 0, QSizePolicy::Expanding, QSizePolicy::Minimum ) );
+
+ // Set the main button's text depending on the CVS comand.
+ switch ( cmd ) {
+ case CVS::Update:
+ temp = i18n( "&Update" );
+ break;
+ case CVS::Commit:
+ temp = i18n( "&Commit" );
+ break;
+ case CVS::Status:
+ temp = i18n( "&Get Status" );
+ break;
+ case CVS::Diff:
+ temp = i18n( "&Get Diff" );
+ break;
+ }
+ mainBtn = new QPushButton( temp, this );
+ mainBtn->setDefault( true );
+ buttons->addWidget( mainBtn );
+
+ cancelBtn = new QPushButton( i18n( "C&ancel" ), this );
+ buttons->addWidget( cancelBtn );
+ layout->addLayout( buttons );
+
+ QFrame * line = new QFrame( this );
+ line->setFrameStyle( QFrame::HLine | QFrame::Sunken );
+ layout->addWidget( line );
+
+ layout->addWidget( new QLabel( i18n( "Command output:" ), this ) );
+
+ output = new QTextEdit( this );
+ output->setReadOnly( true );
+ layout->addWidget( output );
+
+ resize( QSize( 600, 450 ).expandedTo( minimumSizeHint( ) ) );
+
+ if ( cmd == CVS::Commit )
+ logedit->setFocus( );
+
+ readSettings( );
+
+ connect( mainBtn, SIGNAL( clicked( ) ), this, SLOT( slotExecuteCommand( ) ) );
+ connect( cancelBtn, SIGNAL( clicked( ) ), this, SLOT( reject( ) ) );
+}
+
+void CVSDialog::slotComboActivated( int index )
+{
+ if ( index < 0 || index >= m_logMessages.count() )
+ return;
+ logedit->setText( m_logMessages[index] );
+}
+
+CVSDialog::~CVSDialog()
+{
+ delete p;
+}
+
+void CVSDialog::accept( )
+{
+ saveSettings( );
+ KDialog::accept( );
+}
+
+void CVSDialog::setFiles( const QStringList& files )
+{
+ filebox->insertStringList( files );
+}
+
+void CVSDialog::setCommandLine( const QString& command )
+{
+ _commandLine = command;
+}
+
+void CVSDialog::setAddCommand( const QString& command )
+{
+ _addCommand = command;
+}
+
+void CVSDialog::slotExecuteCommand( )
+{
+ // Nothing to do here.
+ if ( _commandLine.isEmpty( ) ) return;
+
+ kdDebug() << "Preparing KProcess" << endl;
+
+ // Create a new shell process
+ p = new KProcess;
+ p->setUseShell( true, "/bin/sh" );
+
+ if ( _cmd == CVS::Commit ) {
+ // Include command for 'cvs add'.
+ if ( autoAddBox->isChecked( ) && !_addCommand.isEmpty( ) )
+ _commandLine.prepend( _addCommand );
+
+ const QString msg( logedit->text() );
+
+ if ( msg.isEmpty() )
+ {
+ // A good commit should never have an empty comment, so ask the user if he really wants it.
+ const int res = KMessageBox::warningContinueCancel( this,
+ i18n( "The commit log message is empty. Do you want to continue?" ) );
+ if ( res != KMessageBox::Continue )
+ return;
+ }
+
+ m_encoding = KGlobal::charsets()->encodingForName( m_encodingComboBox->currentText() );
+ QTextCodec* codec = QTextCodec::codecForName( m_encoding.utf8() );
+
+ if ( !codec )
+ {
+ KMessageBox::error( this, i18n( "Cannot find encoding: %1" ).arg( m_encoding ) );
+ return;
+ }
+ else if ( !codec->canEncode( msg ) )
+ {
+ const int res = KMessageBox::warningContinueCancel( this,
+ i18n( "The commit log message cannot be encoded in the selected encoding: %1.\n"
+ "Do you want to continue?" ).arg( m_encoding ) );
+ if ( res != KMessageBox::Continue )
+ return;
+ }
+
+ // Write the commit log message from the input field to a temporary file
+ m_tempFile = new KTempFile;
+ m_tempFile->setAutoDelete( true );
+ QTextStream* stream = m_tempFile->textStream();
+ if ( !stream )
+ {
+ kdError() << "Could not create QTextStream for file " << m_tempFile->name();
+ delete m_tempFile;
+ m_tempFile = 0;
+ KMessageBox::error( this, i18n( "Cannot open temporary file for writing. Aborting.") );
+ return;
+ }
+ stream->setCodec( codec );
+ *stream << msg;
+ m_tempFile->close();
+
+ if ( m_tempFile->status() )
+ {
+ kdError() << "Could not write to file " << m_tempFile->name();
+ delete m_tempFile;
+ m_tempFile = 0;
+ KMessageBox::error( this, i18n( "Cannot write to temporary file. Aborting.") );
+ return;
+ }
+
+ // Change the command line to have the real name of the temporary file
+ _commandLine.replace( "@LOG@FILE@", KProcess::quote( m_tempFile->name() ) );
+
+ // Update the list of log messages
+ if ( !msg.isEmpty() ) {
+ const QString shortLog = KStringHandler::csqueeze( msg, 80 );
+
+
+ // Remove the message from the list if it already exists
+ m_logMessages.remove( msg );
+ // Prepend the current message to the list
+ m_logMessages.prepend( msg );
+
+ // At this time of the process, we do not need the combobox anymore, so we do not squeeze the changed strings.
+ }
+ }
+
+ // Set the KProcess' command line.
+ *p << _commandLine;
+
+ connect( p, SIGNAL( receivedStdout( KProcess*, char*, int ) ),
+ this, SLOT ( slotProcessStdout( KProcess*, char*, int ) ) );
+ connect( p, SIGNAL( receivedStderr( KProcess*, char*, int ) ),
+ this, SLOT ( slotProcessStderr( KProcess*, char*, int ) ) );
+ connect( p, SIGNAL( processExited( KProcess* ) ),
+ this, SLOT( slotProcessExited( KProcess* ) ) );
+
+ output->append( i18n( "[ Starting command ]" ) );
+
+ if ( p->start( KProcess::NotifyOnExit, KProcess::Communication( KProcess::AllOutput ) ) ) {
+ // Disable the main button (and the log edit if in commit mode) to
+ // indicate activity.
+ mainBtn->setEnabled( false );
+ if ( _cmd == CVS::Commit )
+ logedit->setEnabled( false );
+ } else
+ {
+ kdError() << "Process could not be started." << endl;
+ KMessageBox::error( this, i18n( "The process could not be started." ) );
+ }
+}
+
+void CVSDialog::slotProcessStdout( KProcess*, char * buffer, int len )
+{
+ output->append( QString::fromLocal8Bit( buffer, len ) );
+ // Set the cursor's position at the end of the output.
+ output->setCursorPosition( output->lines( ), 0 );
+
+ // If the command is 'cvs status' or 'cvs diff' collect the output of stdout.
+ if ( (_cmd == CVS::Status) || (_cmd == CVS::Diff) )
+ _statusOutput += QString::fromLocal8Bit( buffer, len );
+}
+
+void CVSDialog::slotProcessStderr( KProcess*, char * buffer, int len )
+{
+ // If an error occurs while executing the command display stderr in
+ // another color.
+ QColor oldColor( output->color( ) );
+ output->setColor( Qt::red );
+ output->append( QString::fromLocal8Bit( buffer, len ) );
+ output->setColor( oldColor );
+ output->setCursorPosition( output->lines( ), 0 );
+}
+
+void CVSDialog::slotProcessExited( KProcess * p )
+{
+ if ( p->exitStatus( ) )
+ output->append( i18n( "[ Exited with status %1 ]" ).arg( p->exitStatus( ) ) );
+ else
+ output->append( i18n( "[ Finished ]" ) );
+
+ // The command is finished. Now we can reconnect the main button.
+ disconnect( mainBtn, 0, 0, 0 );
+ if ( _cmd == CVS::Diff )
+ mainBtn->setText( i18n( "&Show Diff" ) );
+ else
+ mainBtn->setText( i18n( "&Close" ) );
+ connect( mainBtn, SIGNAL( clicked( ) ), this, SLOT( accept( ) ) );
+
+ // Reenable the button and the log edit now that the process is finished.
+ mainBtn->setEnabled( true );
+ if ( _cmd == CVS::Commit )
+ logedit->setEnabled( true );
+}
+
+QString CVSDialog::statusOutput( )
+{
+ return _statusOutput;
+}
+
+void CVSDialog::readSettings( )
+{
+ KSharedConfig * config = m_config;
+ config->setGroup( "CVSSupport" );
+
+ if ( _cmd == CVS::Commit ) {
+ autoAddBox->setChecked( config->readBoolEntry( "AutoAddFiles", true ) );
+
+ // Fill the combobox with old messages.
+ m_logMessages.clear();
+ m_squeezedLogMessages.clear();
+ for ( int cnt = 0; cnt < 10; cnt++ )
+ if ( config->hasKey( QString( "CommitLogMessage%1" ).arg( cnt ) ) )
+ {
+ const QString logMessage = config->readEntry( QString( "CommitLogMessage%1" ).arg( cnt ) );
+ if ( !logMessage.isEmpty() )
+ {
+ // If the message is too long, cut it to 80 characters (or the combo box becomes too wide)
+ // ### FIXME: if the string matches the squeezed 80 chars, it might overwrite another entry
+ const QString shortLog = KStringHandler::csqueeze( logMessage );
+ m_logMessages.append( logMessage );
+ m_squeezedLogMessages.append( shortLog );
+ oldMessages->insertItem( shortLog );
+ }
+ }
+
+ m_encoding = config->readEntry( "CVSEncoding", "UTF-8" );
+ m_encodingComboBox->insertItem( i18n( "Descriptive encoding name", "Last choice ( %1 )" ).arg( m_encoding ), 0);
+ }
+}
+
+void CVSDialog::saveSettings( )
+{
+ KSharedConfig * config = m_config;
+ config->setGroup( "CVSSupport" );
+ if ( _cmd == CVS::Commit ) {
+ config->writeEntry( "AutoAddFiles", autoAddBox->isChecked( ) );
+
+ // Write the log messages to the config file.
+ int cnt = 0;
+ QStringList::const_iterator it;
+ for ( it = m_logMessages.constBegin( ); it != m_logMessages.constEnd( ) && cnt < 10 ; ++it, ++cnt )
+ config->writeEntry( QString( "CommitLogMessage%1" ).arg( cnt ), *it );
+
+ config->writeEntry( "CVSEncoding", m_encoding );
+ }
+ m_config->sync();
+}
+
+#include "cvsdialog.moc"
diff --git a/kbabel/catalogmanager/libcvs/cvsdialog.h b/kbabel/catalogmanager/libcvs/cvsdialog.h
new file mode 100644
index 00000000..658e9883
--- /dev/null
+++ b/kbabel/catalogmanager/libcvs/cvsdialog.h
@@ -0,0 +1,158 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002-2003 by Marco Wegner <mail@marcowegner.de>
+ Copyright (C) 2005, 2006 by Nicolas GOUTTE <goutte@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#ifndef CVSDIALOG_H
+#define CVSDIALOG_H
+
+// KDE include files
+#include <kdialog.h>
+// Project specific include files
+#include "cvsresources.h"
+// Forwarding Qt classes
+class QCheckBox;
+class QComboBox;
+class QListBox;
+class QPushButton;
+class QString;
+class QStringList;
+class QTextEdit;
+// Forwarding KDE classes
+class KProcess;
+class KTempFile;
+class KComboBox;
+
+/**
+ * This class represents the dialog which is used for executing CVS commands
+ * in KBabel's Catalog Manager. The dialog shows the list of files to be
+ * processed as well as the output from the command.
+ *
+ * In Commit mode there is also an option for automatically executing
+ * 'cvs add' if necessary.
+ *
+ * @short Dialog for CVS support in Catalog Manager
+ * @author Marco Wegner <mail@marcowegner.de>
+ */
+class CVSDialog : public KDialog
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Constructor for creating the dialog.
+ * @param cmd The type of command to be executed.
+ */
+ CVSDialog( CVS::Command cmd, QWidget * parent, KSharedConfig* config );
+ ~CVSDialog();
+ /**
+ * Set the list of files which will be used for the CVS command.
+ * @param files The list of files.
+ */
+ void setFiles( const QStringList& files );
+ /**
+ * Set the command line for the execution of the CVS command.
+ * @param command The command line.
+ */
+ void setCommandLine( const QString& command );
+ /**
+ * Set the command line for adding files to the CVS repository.
+ * This method is only used together with a 'cvs commit' for automatically
+ * adding files which are not yet in the repository.
+ * @param command The command line.
+ */
+ void setAddCommand( const QString& command );
+ /**
+ * Return the output of a 'cvs status' command.
+ * @returns The complete output.
+ */
+ QString statusOutput( );
+
+ protected:
+ /**
+ * This method is overwritten so that the settings can be saved after
+ * pressing the 'Close' button.
+ */
+ virtual void accept( );
+ /** Read the dialog's settings. */
+ void readSettings( );
+ /** Save the dialog's settings. */
+ void saveSettings( );
+
+ protected slots:
+ /** Slot for executing the CVS Command. */
+ void slotExecuteCommand( );
+ /** Slot for processing the stdout of the CVS Command. */
+ void slotProcessStdout( KProcess*, char * buffer, int len );
+ /** Slot for processing the stderr of the CVS Command. */
+ void slotProcessStderr( KProcess*, char * buffer, int len );
+ /** Slot for post-processing after the CVS command is fninished. */
+ void slotProcessExited( KProcess * p );
+ /// Slot for combox having been activated
+ void slotComboActivated( int );
+
+ private:
+ CVS::Command _cmd;
+
+ QPushButton * mainBtn;
+ QPushButton * cancelBtn;
+ QListBox * filebox;
+ QComboBox * oldMessages;
+ QTextEdit * logedit;
+ QTextEdit * output;
+ QCheckBox * autoAddBox;
+
+ KProcess * p;
+
+ QString _commandLine;
+ QString _addCommand;
+ QString _statusOutput;
+
+ /// Log messages (long version)
+ QStringList m_logMessages;
+ /// Log messages (short version)
+ QStringList m_squeezedLogMessages;
+
+ /// Temporary file (for commits)
+ KTempFile* m_tempFile;
+
+ /// Encoding for the commit log message
+ QString m_encoding;
+
+ /// Combo box for the encoding
+ KComboBox* m_encodingComboBox;
+
+ /// Configuration data (of the KBabel project)
+ KSharedConfig* m_config;
+};
+
+#endif // CVSDIALOG_H
diff --git a/kbabel/catalogmanager/libcvs/cvshandler.cpp b/kbabel/catalogmanager/libcvs/cvshandler.cpp
new file mode 100644
index 00000000..d3f2ae18
--- /dev/null
+++ b/kbabel/catalogmanager/libcvs/cvshandler.cpp
@@ -0,0 +1,398 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002-2003 by Marco Wegner <mail@marcowegner.de>
+ Copyright (C) 2005, 2006 by Nicolas GOUTTE <goutte@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+// System include files
+#include <sys/stat.h>
+#include <time.h>
+#include <unistd.h>
+// Qt include files
+#include <qdir.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qregexp.h>
+#include <qstring.h>
+#include <qstringlist.h>
+// KDE include files
+#include <kapplication.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <ktempfile.h>
+// project specific include files
+#include "cvshandler.h"
+
+
+CVSHandler::CVSHandler( const QString& poBaseDir, const QString& potBaseDir )
+{
+ setPOBaseDir( poBaseDir );
+ setPOTBaseDir( potBaseDir );
+ _autoUpdateTemplates = false;
+}
+
+void CVSHandler::setPOBaseDir( const QString& dir )
+{
+ // check if 'CVS/Entries' exists in the PO base directory
+ if ( QFileInfo( dir + "/CVS/Entries" ).exists( ) ) {
+ _isPORepository = true;
+ _poBaseDir = dir;
+ } else
+ _isPORepository = false;
+ emit signalIsPORepository( _isPORepository );
+}
+
+void CVSHandler::setPOTBaseDir( const QString& dir )
+{
+ // check if 'CVS/Entries' exists in the POT base directory
+ if ( QFileInfo( dir + "/CVS/Entries" ).exists( ) ) {
+ _isPOTRepository = true;
+ _potBaseDir = dir;
+ } else
+ _isPOTRepository = false;
+ emit signalIsPOTRepository( _isPOTRepository );
+}
+
+QString CVSHandler::fileStatus( const FileStatus status ) const
+{
+ switch ( status ) {
+ case NO_REPOSITORY:
+ return i18n( "No CVS repository" );
+ break;
+ case NOT_IN_CVS:
+ return i18n( "Not in CVS" );
+ break;
+ case LOCALLY_ADDED:
+ return i18n( "Locally added" );
+ break;
+ case LOCALLY_REMOVED:
+ return i18n( "Locally removed" );
+ break;
+ case LOCALLY_MODIFIED:
+ return i18n( "Locally modified" );
+ break;
+ case UP_TO_DATE:
+ return i18n( "Up-to-date" );
+ break;
+ case CONFLICT:
+ return i18n( "Conflict" );
+ break;
+ default:
+ return i18n( "Unknown" );
+ break;
+ }
+}
+
+CVSHandler::FileStatus CVSHandler::fstatus( const QString& filename ) const
+{
+ // no valid repository
+ if ( !_isPORepository )
+ return NO_REPOSITORY;
+
+ QString fn( filename );
+ fn = fn.remove( QRegExp( "/$" ) );
+
+ QFileInfo info( fn );
+
+ // check if 'CVS/Entries' exists and can be read
+ QFile entries( info.dir( true ).path( ) + "/CVS/Entries" );
+ if ( !entries.open( IO_ReadOnly ) )
+ return NOT_IN_CVS; // we already know that it's a repository
+
+ // ### FIXME: it does not take care of CVS/Entries.Log
+ // a line in CVS/Entries has the following format:
+ // [D]/NAME/REVISION/[CONFLICT+]TIMESTAMP/OPTIONS/TAGDATE
+ QRegExp rx( QString( "^D?/%1/" ).arg( info.fileName( ) ) );
+
+ QString temp;
+ QTextStream stream( &entries );
+
+ bool isInRepository = false;
+ while ( !stream.atEnd() ) {
+ temp = stream.readLine( );
+ if ( temp.find( rx ) == 0 ) {
+ isInRepository = true;
+ break;
+ }
+ }
+ entries.close( );
+
+ // no entry found
+ if ( !isInRepository )
+ return NOT_IN_CVS;
+
+ const QStringList fields = QStringList::split( '/', temp, true );
+ // bool isDir = ( fields[0] == "D" );
+ const QString cvsname( fields[1] );
+ const QString revision( fields[2] );
+ const QString timestamp( fields[3] );
+ // ignore the other fields for now
+
+ if ( revision == "0" && timestamp == "dummy timestamp" )
+ return LOCALLY_ADDED;
+ if ( revision.startsWith( "-" ) && timestamp == "dummy timestamp" )
+ return LOCALLY_REMOVED;
+
+ // check for conflicts
+ if ( timestamp.find( '+' ) >= 0 )
+ return CONFLICT;
+
+ // calculate the UTC time from the file's last modified date
+ struct stat st;
+ lstat( QFile::encodeName(fn), &st );
+ struct tm * tm_p = gmtime( &st.st_mtime );
+ QString ftime = QString( asctime( tm_p ) );
+ ftime.truncate( ftime.length( ) - 1 );
+ if ( ftime != timestamp )
+ return LOCALLY_MODIFIED;
+
+ return UP_TO_DATE;
+}
+
+QString CVSHandler::cvsStatus( const QString& filename ) const
+{
+ return map[filename];
+}
+
+void CVSHandler::execCVSCommand( QWidget* parent, CVS::Command cmd, const QString& filename, bool templates, KSharedConfig* config )
+{
+ if ( !_isPORepository ) {
+ // This message box should never be visible but who knows... ;-)
+ KMessageBox::sorry( parent, i18n( "This is not a valid CVS repository. "
+ "The CVS commands cannot be executed." ) );
+ return;
+ }
+
+ QFileInfo info( filename );
+ if ( !info.isDir( ) ) {
+ execCVSCommand( parent, cmd, QStringList( filename ), templates, config );
+ return;
+ }
+
+ // ### FIXME: instead of making a QString, use KProcess directly, so that it cares about quoting.
+ // ### FIXME: use KProcess::setWorkingDirectory instead of using "cd" (therefore allowing to use KProcess without a shell.)
+ // it's a dir
+ QString command( "cd " + filename + " && cvs " );
+ switch ( cmd ) {
+ case CVS::Update:
+ command += "update -dP";
+ break;
+ case CVS::Commit:
+ // The cvs client does not care about the encoding, so we cannot set anything here
+ command += "commit -F @LOG@FILE@";
+ checkToAdd( QStringList( filename ) );
+ break;
+ case CVS::Status:
+ command += "status";
+ break;
+ case CVS::Diff:
+ command += "diff";
+ break;
+ }
+
+ showDialog( parent, cmd, QStringList( filename ), command, config );
+}
+
+void CVSHandler::execCVSCommand( QWidget* parent, CVS::Command cmd, const QStringList& files, bool templates, KSharedConfig* config )
+{
+ if ( !_isPORepository ) {
+ // This message box should never be visible but who knows... ;-)
+ KMessageBox::sorry( parent, i18n( "This is not a valid CVS repository. "
+ "The CVS commands cannot be executed." ) );
+ return;
+ }
+
+ // ### FIXME: instead of making a QString, use KProcess directly, so that it cares about quoting.
+ // ### FIXME: use KProcess::setWorkingDirectory instead of using "cd" (therefore allowing to use KProcess without a shell.)
+ QString command("cd " + (templates ? _potBaseDir : _poBaseDir) + " && cvs ");
+ switch ( cmd ) {
+ case CVS::Update:
+ command += "update -dP";
+ break;
+ case CVS::Commit:
+ command += "commit -F @LOG@FILE@";
+ checkToAdd( files );
+ break;
+ case CVS::Status:
+ command += "status";
+ break;
+ case CVS::Diff:
+ command += "diff";
+ break;
+ }
+
+ QRegExp rx;
+ if (templates)
+ rx.setPattern(_potBaseDir + "/?");
+ else
+ rx.setPattern(_poBaseDir + "/?");
+
+ QStringList::ConstIterator it;
+ for ( it = files.begin( ); it != files.end( ); ++it ) {
+ QString temp = *it;
+ temp.remove(rx);
+ command += " \'" + temp + "\'";
+ }
+
+ showDialog( parent, cmd, files, command, config );
+}
+
+void CVSHandler::setAutoUpdateTemplates( bool update )
+{
+ _autoUpdateTemplates = update;
+}
+
+void CVSHandler::showDialog( QWidget* parent, CVS::Command cmd, const QStringList& files, const QString& commandLine, KSharedConfig* config )
+{
+ CVSDialog * dia = new CVSDialog( cmd, parent, config );
+ dia->setFiles( files );
+ dia->setCommandLine( commandLine );
+ if ( cmd == CVS::Commit ) {
+ dia->setAddCommand( _addCommand );
+ }
+
+ if ( dia->exec( ) == KDialog::Accepted ) {
+ if ( cmd == CVS::Status )
+ processStatusOutput( dia->statusOutput( ) );
+ if ( cmd == CVS::Diff )
+ processDiff( dia->statusOutput( ) );
+ }
+
+ delete dia;
+
+ // file status display update necessary in Catalog Manager
+ if ( cmd == CVS::Commit )
+ emit signalFilesCommitted( files );
+}
+
+void CVSHandler::checkToAdd( const QStringList& files )
+{
+ if ( files.isEmpty( ) )
+ return;
+
+ QStringList toBeAdded;
+
+ QStringList::ConstIterator it;
+ for ( it = files.begin( ); it != files.end( ); ++it ) {
+ // check for every entry if it needs to be added
+ if ( fstatus( *it ) == NOT_IN_CVS ) {
+ QFileInfo info( *it );
+ QString temp; // will hold the dir path
+ if ( info.isDir( ) ) {
+ toBeAdded << *it;
+ temp = *it;
+ } else {
+ toBeAdded << *it;
+ temp = QFileInfo( *it ).dirPath( true );
+ }
+ // check recursivlely if parent dirs have to be added as well
+ while ( fstatus( temp ) == NOT_IN_CVS && toBeAdded.findIndex( temp ) == -1 ) {
+ toBeAdded << temp;
+ temp = QFileInfo( temp ).dirPath( true );
+ }
+ }
+ }
+
+ // remove an old command
+ _addCommand.setLength( 0 );
+
+ // make sure the diectories are added before the files
+ toBeAdded.sort( );
+
+ // create a command line for adding the files and dirs
+ for ( it = toBeAdded.begin( ); it != toBeAdded.end( ); ++it ) {
+ QFileInfo info( *it );
+ _addCommand += "cd " + info.dirPath( true ) + " && cvs add " + info.fileName( ) + "; ";
+ }
+}
+
+void CVSHandler::processStatusOutput( const QString& status )
+{
+ if ( !_isPORepository )
+ return;
+
+ // at first we need to extract the name of the base directory on the server
+ QFile f( _poBaseDir + "/CVS/Root" );
+ if ( !f.open( IO_ReadOnly ) )
+ return;
+
+ QTextStream stream( &f );
+ // extract the string after the last colon in the first line
+ QString basedir = stream.readLine( ).section( ':', -1 );
+
+ f.close( );
+
+ // divide the complete status output in little chunks for every file
+ QStringList entries = QStringList::split( QRegExp( "={67,67}" ), status );
+ QStringList::Iterator it;
+ for ( it = entries.begin( ); it != entries.end( ); ++it ) {
+ QString entr = *it;
+ // translate the filename from repository to local
+ QRegExp rx( basedir + ".*,v" );
+ int pos = entr.find( rx );
+ QString file = _poBaseDir + entr.mid( pos + basedir.length( ),
+ rx.matchedLength( ) - basedir.length( ) - 2 );
+
+ entr = "<qt>" + entr + "</qt>";
+
+ // TODO: do some markup
+
+ map.replace( file, entr );
+ }
+}
+
+void CVSHandler::processDiff( QString output )
+{
+ output.remove( QRegExp( "\\[ .* \\]$" ));
+ output.remove( QRegExp( "^" + i18n("[ Starting command ]" ).replace("[","\\[").replace("]","\\]")));
+
+ KTempFile tmpFile;
+ *(tmpFile.textStream()) << output;
+ tmpFile.close();
+
+ QString error;
+ if ( KApplication::startServiceByName( "Kompare", tmpFile.name(), &error ) )
+ KMessageBox::error( 0, error );
+}
+
+bool CVSHandler::isConsideredModified( const FileStatus status ) const
+{
+ /*
+ * A file is modified if it is either:
+ * - locally modified for CVS
+ * - directory under CVS control but not the file
+ */
+ return status == LOCALLY_MODIFIED || status == NOT_IN_CVS;
+}
+
+
+
+#include "cvshandler.moc"
diff --git a/kbabel/catalogmanager/libcvs/cvshandler.h b/kbabel/catalogmanager/libcvs/cvshandler.h
new file mode 100644
index 00000000..44777aa3
--- /dev/null
+++ b/kbabel/catalogmanager/libcvs/cvshandler.h
@@ -0,0 +1,114 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002-2003 by Marco Wegner <mail@marcowegner.de>
+ Copyright (C) 2005, 2006 by Nicolas GOUTTE <goutte@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#ifndef CVSHANDLER_H
+#define CVSHANDLER_H
+
+// Qt include files
+#include <qmap.h>
+#include <qobject.h>
+// Project specific include files
+#include "cvsdialog.h"
+#include "cvsresources.h"
+// Forwarding Qt classes
+class QString;
+class QStringList;
+class QWidget;
+
+class KSharedConfig;
+
+/**
+ * This class is the backend for CVS support in Catalog Manager.
+ *
+ * @short Backend for CVS support in Catalog Manager
+ * @author Marco Wegner <mail@marcowegner.de>
+ */
+class CVSHandler : public QObject
+{
+ Q_OBJECT
+
+ public:
+ enum FileStatus {
+ NO_REPOSITORY,
+ NOT_IN_CVS,
+ LOCALLY_ADDED,
+ LOCALLY_REMOVED,
+ LOCALLY_MODIFIED,
+ CONFLICT,
+ UP_TO_DATE
+ };
+
+ CVSHandler( const QString& poBaseDir = QString::null, const QString& potBaseDir = QString::null );
+
+ void setPOBaseDir( const QString& dir );
+ void setPOTBaseDir( const QString& dir );
+
+ FileStatus fstatus( const QString& filename ) const;
+ QString fileStatus( const FileStatus status ) const;
+ QString cvsStatus( const QString& filename ) const;
+
+ void execCVSCommand( QWidget* parent, CVS::Command cmd, const QString& filename, bool templates, KSharedConfig* config );
+ void execCVSCommand( QWidget* parent, CVS::Command cmd, const QStringList& files, bool templates, KSharedConfig* config );
+
+ void setAutoUpdateTemplates( bool update );
+
+ /**
+ * True if the file was modified or has another status considered as a modification
+ */
+ bool isConsideredModified( const FileStatus status ) const;
+
+ signals:
+ void signalIsPORepository( bool );
+ void signalIsPOTRepository( bool );
+ void signalFilesCommitted( const QStringList& );
+
+ private:
+ void showDialog( QWidget* parent, CVS::Command cmd, const QStringList& files, const QString& commandLine, KSharedConfig* config );
+ void checkToAdd( const QStringList& files );
+ void processStatusOutput( const QString& status );
+ void processDiff( QString output );
+
+ private:
+ QString _poBaseDir;
+ QString _potBaseDir;
+ bool _isPORepository;
+ bool _isPOTRepository;
+ bool _autoUpdateTemplates;
+ QString _addCommand;
+
+ /** Mapping the output of 'cvs status' against the filename. */
+ QMap<QString,QString> map;
+};
+
+#endif // CVSHANDLER_H
diff --git a/kbabel/catalogmanager/libcvs/cvsresources.h b/kbabel/catalogmanager/libcvs/cvsresources.h
new file mode 100644
index 00000000..627802f7
--- /dev/null
+++ b/kbabel/catalogmanager/libcvs/cvsresources.h
@@ -0,0 +1,41 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002-2003 by Marco Wegner <mail@marcowegner.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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#ifndef CVSRESOURCES_H
+#define CVSRESOURCES_H
+
+namespace CVS {
+ enum Command { Update, Commit, Status, Diff };
+}
+
+#endif // CVSRESOURCES_H
diff --git a/kbabel/catalogmanager/libsvn/Makefile.am b/kbabel/catalogmanager/libsvn/Makefile.am
new file mode 100644
index 00000000..7c340974
--- /dev/null
+++ b/kbabel/catalogmanager/libsvn/Makefile.am
@@ -0,0 +1,11 @@
+noinst_LTLIBRARIES = libcatalogmanagersvn.la
+
+# set the include path for X, qt and KDE
+INCLUDES = -I.. -I../../common $(all_includes)
+
+libcatalogmanagersvn_la_SOURCES = svnhandler.cpp svndialog.cpp
+
+noinst_HEADERS = svnhandler.h svndialog.h svnresources.h
+
+# let automoc handle all of the meta source files (moc)
+METASOURCES = AUTO
diff --git a/kbabel/catalogmanager/libsvn/svndialog.cpp b/kbabel/catalogmanager/libsvn/svndialog.cpp
new file mode 100644
index 00000000..69653591
--- /dev/null
+++ b/kbabel/catalogmanager/libsvn/svndialog.cpp
@@ -0,0 +1,400 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002-2003 by Marco Wegner <mail@marcowegner.de>
+ Copyright (C) 2005, 2006 by Nicolas GOUTTE <goutte@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+// Qt include files
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qfileinfo.h>
+#include <qframe.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qlistbox.h>
+#include <qpushbutton.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qtextedit.h>
+// KDE include files
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kprocess.h>
+#include <ktempfile.h>
+#include <kmessagebox.h>
+#include <kstringhandler.h>
+// Project specific include files
+#include "svndialog.h"
+
+
+SVNDialog::SVNDialog( SVN::Command cmd, QWidget * parent, KSharedConfig* config )
+ : KDialog( parent, "SVN DIALOG", true ), m_tempFile( 0 ), m_config( config )
+{
+ _cmd = cmd;
+ p=0L;
+ setCaption( i18n( "SVN Dialog" ) );
+
+ QString temp;
+
+ QVBoxLayout * layout = new QVBoxLayout( this, 6, 6, "MAIN LAYOUT" );
+
+ // Set the label's text depending on the SVN command.
+ switch ( cmd ) {
+ case SVN::Update:
+ temp = i18n( "Update the following files:" );
+ break;
+ case SVN::Commit:
+ temp = i18n( "Commit the following files:" );
+ break;
+ case SVN::StatusRemote:
+ temp = i18n( "Get remote status for the following files:" );
+ break;
+ case SVN::StatusLocal:
+ temp = i18n( "Get local status for the following files:" );
+ break;
+ case SVN::Diff:
+ temp = i18n( "Get diff for the following files:" );
+ break;
+ case SVN::Info:
+ temp = i18n( "Get information for the following files:" );
+ break;
+ }
+ layout->addWidget( new QLabel( temp, this ) );
+
+ // Widget for showing the list of files.
+ filebox = new QListBox( this );
+ layout->addWidget( filebox );
+
+ // Add special widgets for 'svn commit'.
+ if ( cmd == SVN::Commit ) {
+ QLabel * label;
+
+ // Combobox for displaying old log messages.
+ label = new QLabel( i18n( "&Old messages:" ), this );
+ oldMessages = new QComboBox( this );
+ oldMessages->setDuplicatesEnabled( false );
+ label->setBuddy( oldMessages );
+ layout->addWidget( label );
+ layout->addWidget( oldMessages );
+
+ // Textfield for entering a log message.
+ label = new QLabel( i18n( "&Log message:" ), this );
+ logedit = new QTextEdit( this );
+ label->setBuddy( logedit );
+ layout->addWidget( label );
+ layout->addWidget( logedit );
+
+ connect( oldMessages, SIGNAL( activated( int ) ),
+ this, SLOT( slotComboActivated( int ) ) );
+ }
+
+ QHBoxLayout * buttons = new QHBoxLayout( 0, 0, 6, "BUTTON LAYOUT" );
+ // Add special buttons for 'svn commit'.
+ if ( cmd == SVN::Commit ) {
+ autoAddBox = new QCheckBox( i18n( "Auto&matically add files if necessary" ), this );
+ buttons->addWidget( autoAddBox );
+ }
+ buttons->addItem( new QSpacerItem( 1, 0, QSizePolicy::Expanding, QSizePolicy::Minimum ) );
+
+ // Set the main button's text depending on the SVN comand.
+ switch ( cmd ) {
+ case SVN::Update:
+ temp = i18n( "&Update" );
+ break;
+ case SVN::Commit:
+ temp = i18n( "&Commit" );
+ break;
+ case SVN::StatusRemote:
+ case SVN::StatusLocal:
+ temp = i18n( "&Get Status" );
+ break;
+ case SVN::Diff:
+ temp = i18n( "&Get Diff" );
+ break;
+ case SVN::Info:
+ temp = i18n( "&Get Information" );
+ break;
+ }
+ mainBtn = new QPushButton( temp, this );
+ mainBtn->setDefault( true );
+ buttons->addWidget( mainBtn );
+
+ cancelBtn = new QPushButton( i18n( "C&ancel" ), this );
+ buttons->addWidget( cancelBtn );
+ layout->addLayout( buttons );
+
+ QFrame * line = new QFrame( this );
+ line->setFrameStyle( QFrame::HLine | QFrame::Sunken );
+ layout->addWidget( line );
+
+ layout->addWidget( new QLabel( i18n( "Command output:" ), this ) );
+
+ output = new QTextEdit( this );
+ output->setReadOnly( true );
+ layout->addWidget( output );
+
+ resize( QSize( 600, 450 ).expandedTo( minimumSizeHint( ) ) );
+
+ if ( cmd == SVN::Commit )
+ logedit->setFocus( );
+
+ readSettings( );
+
+ connect( mainBtn, SIGNAL( clicked( ) ), this, SLOT( slotExecuteCommand( ) ) );
+ connect( cancelBtn, SIGNAL( clicked( ) ), this, SLOT( reject( ) ) );
+}
+
+void SVNDialog::slotComboActivated( int index )
+{
+ if ( index < 0 || index >= m_logMessages.count() )
+ return;
+ logedit->setText( m_logMessages[index] );
+}
+
+SVNDialog::~SVNDialog()
+{
+ delete m_tempFile;
+ delete p;
+}
+
+void SVNDialog::accept( )
+{
+ saveSettings( );
+ KDialog::accept( );
+}
+
+void SVNDialog::setFiles( const QStringList& files )
+{
+ filebox->insertStringList( files );
+}
+
+void SVNDialog::setCommandLine( const QString& command )
+{
+ _commandLine = command;
+}
+
+void SVNDialog::setAddCommand( const QString& command )
+{
+ _addCommand = command;
+}
+
+void SVNDialog::slotExecuteCommand( )
+{
+ // Nothing to do here.
+ if ( _commandLine.isEmpty( ) ) return;
+
+ kdDebug() << "Preparing KProcess" << endl;
+
+ // Create a new shell process
+ p = new KProcess;
+ p->setUseShell( true, "/bin/sh" );
+
+ if ( _cmd == SVN::Commit ) {
+ // Include command for 'svn add'.
+ if ( autoAddBox->isChecked( ) && !_addCommand.isEmpty( ) )
+ _commandLine.prepend( _addCommand );
+
+ const QString msg( logedit->text() );
+
+ if ( msg.isEmpty() )
+ {
+ // A good commit should never have an empty comment, so ask the user if he really wants it.
+ const int res = KMessageBox::warningContinueCancel( this,
+ i18n( "The commit log message is empty. Do you want to continue?" ) );
+ if ( res != KMessageBox::Continue )
+ return;
+ }
+
+ // Write the commit log message from the input field to a temporary file
+ m_tempFile = new KTempFile;
+ m_tempFile->setAutoDelete( true );
+ QTextStream* stream = m_tempFile->textStream();
+ if ( !stream )
+ {
+ kdError() << "Could not create QTextStream for file " << m_tempFile->name();
+ delete m_tempFile;
+ m_tempFile = 0;
+ KMessageBox::error( this, i18n( "Cannot open temporary file for writing. Aborting.") );
+ return;
+ }
+ stream->setEncoding( QTextStream::UnicodeUTF8 );
+ *stream << msg;
+ m_tempFile->close();
+
+ if ( m_tempFile->status() )
+ {
+ kdError() << "Could not write to file " << m_tempFile->name();
+ delete m_tempFile;
+ m_tempFile = 0;
+ KMessageBox::error( this, i18n( "Cannot write to temporary file. Aborting.") );
+ return;
+ }
+
+ // Change the command line to have the real name of the temporary file
+ _commandLine.replace( "@LOG@FILE@", KProcess::quote( m_tempFile->name() ) );
+
+ // Update the list of log messages
+ if ( !msg.isEmpty() ) {
+ const QString shortLog = KStringHandler::csqueeze( msg, 80 );
+
+
+ // Remove the message from the list if it already exists
+ m_logMessages.remove( msg );
+ // Prepend the current message to the list
+ m_logMessages.prepend( msg );
+
+ // At this time of the process, we do not need the combobox anymore, so we do not squeeze the changed strings.
+ }
+ }
+
+ // Set the KProcess' command line.
+ *p << _commandLine;
+
+ connect( p, SIGNAL( receivedStdout( KProcess*, char*, int ) ),
+ this, SLOT ( slotProcessStdout( KProcess*, char*, int ) ) );
+ connect( p, SIGNAL( receivedStderr( KProcess*, char*, int ) ),
+ this, SLOT ( slotProcessStderr( KProcess*, char*, int ) ) );
+ connect( p, SIGNAL( processExited( KProcess* ) ),
+ this, SLOT( slotProcessExited( KProcess* ) ) );
+
+ output->append( i18n( "[ Starting command ]" ) );
+
+ if ( p->start( KProcess::NotifyOnExit, KProcess::Communication( KProcess::AllOutput ) ) ) {
+ // Disable the main button (and the log edit if in commit mode) to
+ // indicate activity.
+ mainBtn->setEnabled( false );
+ if ( _cmd == SVN::Commit )
+ logedit->setEnabled( false );
+ } else
+ {
+ kdError() << "Process could not be started." << endl;
+ KMessageBox::error( this, i18n( "The process could not be started." ) );
+ }
+}
+
+void SVNDialog::slotProcessStdout( KProcess*, char * buffer, int len )
+{
+ output->append( QString::fromLocal8Bit( buffer, len ) );
+ // Set the cursor's position at the end of the output.
+ output->setCursorPosition( output->lines( ), 0 );
+
+ // If the command is 'svn status' or 'svn diff' collect the output of stdout.
+ if ( ( _cmd == SVN::StatusLocal ) || ( _cmd == SVN::StatusRemote ) || ( _cmd == SVN::Diff ) )
+ _statusOutput += QString::fromLocal8Bit( buffer, len );
+}
+
+void SVNDialog::slotProcessStderr( KProcess*, char * buffer, int len )
+{
+ // If an error occurs while executing the command display stderr in
+ // another color.
+ QColor oldColor( output->color( ) );
+ output->setColor( Qt::red );
+ output->append( QString::fromLocal8Bit( buffer, len ) );
+ output->setColor( oldColor );
+ output->setCursorPosition( output->lines( ), 0 );
+}
+
+void SVNDialog::slotProcessExited( KProcess * p )
+{
+ if ( p->exitStatus( ) )
+ output->append( i18n( "[ Exited with status %1 ]" ).arg( p->exitStatus( ) ) );
+ else
+ output->append( i18n( "[ Finished ]" ) );
+
+ // The command is finished. Now we can reconnect the main button.
+ disconnect( mainBtn, 0, 0, 0 );
+ if ( _cmd == SVN::Diff )
+ mainBtn->setText( i18n( "&Show Diff" ) );
+ else
+ mainBtn->setText( i18n( "&Close" ) );
+ connect( mainBtn, SIGNAL( clicked( ) ), this, SLOT( accept( ) ) );
+
+ // Reenable the button and the log edit now that the process is finished.
+ mainBtn->setEnabled( true );
+ if ( _cmd == SVN::Commit )
+ logedit->setEnabled( true );
+}
+
+QString SVNDialog::statusOutput( )
+{
+ return _statusOutput;
+}
+
+void SVNDialog::readSettings( )
+{
+ KSharedConfig * config = m_config;
+ config->setGroup( "SVNSupport" );
+
+ if ( _cmd == SVN::Commit ) {
+ autoAddBox->setChecked( config->readBoolEntry( "AutoAddFiles", true ) );
+
+ // Fill the combobox with old messages.
+ m_logMessages.clear();
+ m_squeezedLogMessages.clear();
+ for ( int cnt = 0; cnt < 10; cnt++ )
+ if ( config->hasKey( QString( "CommitLogMessage%1" ).arg( cnt ) ) )
+ {
+ const QString logMessage = config->readEntry( QString( "CommitLogMessage%1" ).arg( cnt ) );
+ if ( !logMessage.isEmpty() )
+ {
+ // If the message is too long, cut it to 80 characters (or the combo box becomes too wide)
+ // ### FIXME: if the string matches the squeezed 80 chars, it might overwrite another entry
+ const QString shortLog = KStringHandler::csqueeze( logMessage );
+ m_logMessages.append( logMessage );
+ m_squeezedLogMessages.append( shortLog );
+ oldMessages->insertItem( shortLog );
+ }
+ }
+
+ }
+}
+
+void SVNDialog::saveSettings( )
+{
+ KSharedConfig * config = m_config;
+ config->setGroup( "SVNSupport" );
+ if ( _cmd == SVN::Commit ) {
+ config->writeEntry( "AutoAddFiles", autoAddBox->isChecked( ) );
+
+ // Write the log messages to the config file.
+ int cnt = 0;
+ QStringList::const_iterator it;
+ for ( it = m_logMessages.constBegin( ); it != m_logMessages.constEnd( ) && cnt < 10 ; ++it, ++cnt )
+ config->writeEntry( QString( "CommitLogMessage%1" ).arg( cnt ), *it );
+ }
+ m_config->sync();
+}
+
+#include "svndialog.moc"
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/kbabel/catalogmanager/libsvn/svndialog.h b/kbabel/catalogmanager/libsvn/svndialog.h
new file mode 100644
index 00000000..0c824fa8
--- /dev/null
+++ b/kbabel/catalogmanager/libsvn/svndialog.h
@@ -0,0 +1,151 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002-2003 by Marco Wegner <mail@marcowegner.de>
+ Copyright (C) 2005, 2006 by Nicolas GOUTTE <goutte@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#ifndef SVNDIALOG_H
+#define SVNDIALOG_H
+
+// KDE include files
+#include <kdialog.h>
+// Project specific include files
+#include "svnresources.h"
+// Forwarding Qt classes
+class QCheckBox;
+class QComboBox;
+class QListBox;
+class QPushButton;
+class QString;
+class QStringList;
+class QTextEdit;
+// Forwarding KDE classes
+class KProcess;
+class KTempFile;
+class KSharedConfig;
+
+/**
+ * This class represents the dialog which is used for executing SVN commands
+ * in KBabel's Catalog Manager. The dialog shows the list of files to be
+ * processed as well as the output from the command.
+ *
+ * In Commit mode there is also an option for automatically executing
+ * 'svn add' if necessary.
+ *
+ * @short Dialog for SVN support in Catalog Manager
+ */
+class SVNDialog : public KDialog
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Constructor for creating the dialog.
+ * @param cmd The type of command to be executed.
+ */
+ SVNDialog( SVN::Command cmd, QWidget * parent, KSharedConfig* config );
+ ~SVNDialog();
+ /**
+ * Set the list of files which will be used for the SVN command.
+ * @param files The list of files.
+ */
+ void setFiles( const QStringList& files );
+ /**
+ * Set the command line for the execution of the SVN command.
+ * @param command The command line.
+ */
+ void setCommandLine( const QString& command );
+ /**
+ * Set the command line for adding files to the SVN repository.
+ * This method is only used together with a 'svn commit' for automatically
+ * adding files which are not yet in the repository.
+ * @param command The command line.
+ */
+ void setAddCommand( const QString& command );
+ /**
+ * Return the output of a 'svn status' command.
+ * @returns The complete output.
+ */
+ QString statusOutput( );
+
+ protected:
+ /**
+ * This method is overwritten so that the settings can be saved after
+ * pressing the 'Close' button.
+ */
+ virtual void accept( );
+ /** Read the dialog's settings. */
+ void readSettings( );
+ /** Save the dialog's settings. */
+ void saveSettings( );
+
+ protected slots:
+ /** Slot for executing the SVN Command. */
+ void slotExecuteCommand( );
+ /** Slot for processing the stdout of the SVN Command. */
+ void slotProcessStdout( KProcess*, char * buffer, int len );
+ /** Slot for processing the stderr of the SVN Command. */
+ void slotProcessStderr( KProcess*, char * buffer, int len );
+ /** Slot for post-processing after the SVN command is fninished. */
+ void slotProcessExited( KProcess * p );
+ /// Slot for combox having been activated
+ void slotComboActivated( int );
+
+ private:
+ SVN::Command _cmd;
+
+ QPushButton * mainBtn;
+ QPushButton * cancelBtn;
+ QListBox * filebox;
+ QComboBox * oldMessages;
+ QTextEdit * logedit;
+ QTextEdit * output;
+ QCheckBox * autoAddBox;
+
+ KProcess * p;
+
+ QString _commandLine;
+ QString _addCommand;
+ QString _statusOutput;
+
+ /// Log messages (long version)
+ QStringList m_logMessages;
+ /// Log messages (short version)
+ QStringList m_squeezedLogMessages;
+
+ /// Temporary file (for commits)
+ KTempFile* m_tempFile;
+
+ /// Configuration data (of the KBabel project)
+ KSharedConfig* m_config;
+};
+
+#endif // SVNDIALOG_H
diff --git a/kbabel/catalogmanager/libsvn/svnhandler.cpp b/kbabel/catalogmanager/libsvn/svnhandler.cpp
new file mode 100644
index 00000000..8117fe62
--- /dev/null
+++ b/kbabel/catalogmanager/libsvn/svnhandler.cpp
@@ -0,0 +1,544 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002-2003 by Marco Wegner <mail@marcowegner.de>
+ Copyright (C) 2005, 2006 by Nicolas GOUTTE <goutte@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+// System include files
+#include <unistd.h>
+#include <sys/stat.h>
+#include <time.h>
+// Qt include files
+#include <qdir.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qregexp.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qdom.h>
+// KDE include files
+#include <kapplication.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kprocess.h>
+// project specific include files
+#include "svnhandler.h"
+
+SVNHandler::SVNHandler( const QString& poBaseDir, const QString& potBaseDir )
+{
+ setPOBaseDir( poBaseDir );
+ setPOTBaseDir( potBaseDir );
+ _autoUpdateTemplates = false;
+}
+
+void SVNHandler::setPOBaseDir( const QString& dir )
+{
+ // check if '.svn/entries' exists in the PO base directory
+ if ( QFileInfo( dir + "/.svn/entries" ).exists( ) ) {
+ _isPORepository = true;
+ _poBaseDir = dir;
+ } else
+ _isPORepository = false;
+ emit signalIsPORepository( _isPORepository );
+}
+
+void SVNHandler::setPOTBaseDir( const QString& dir )
+{
+ // check if '.svn/entries' exists in the POT base directory
+ if ( QFileInfo( dir + "/.svn/entries" ).exists( ) ) {
+ _isPOTRepository = true;
+ _potBaseDir = dir;
+ } else
+ _isPOTRepository = false;
+ emit signalIsPOTRepository( _isPOTRepository );
+}
+
+QString SVNHandler::fileStatus( const FileStatus status ) const
+{
+ switch ( status ) {
+ case NO_REPOSITORY:
+ return i18n( "No SVN repository" );
+ break;
+ case NOT_IN_SVN:
+ return i18n( "Not in SVN" );
+ break;
+ case LOCALLY_ADDED:
+ return i18n( "Locally added" );
+ break;
+ case LOCALLY_REMOVED:
+ return i18n( "Locally removed" );
+ break;
+ case LOCALLY_MODIFIED:
+ return i18n( "Locally modified" );
+ break;
+ case UP_TO_DATE:
+ return i18n( "Up-to-date" );
+ break;
+ case CONFLICT:
+ return i18n( "Conflict" );
+ break;
+ case ERROR_IN_WC:
+ return i18n( "Error in Working Copy" );
+ default:
+ return i18n( "Unknown" );
+ break;
+ }
+}
+
+SVNHandler::FileStatus SVNHandler::fstatus( const QString& filename ) const
+{
+ // no valid repository
+ if ( !_isPORepository )
+ return NO_REPOSITORY;
+
+ QString fn( filename );
+ fn = fn.remove( QRegExp( "/$" ) );
+
+ QFileInfo info( fn );
+
+ // check if '.svn/entries' exists.
+ QFile entries( info.dir( true ).path( ) + "/.svn/entries" );
+
+ if ( !entries.exists() )
+ return NOT_IN_SVN;
+
+ KProcess proc;
+ SVNOutputCollector out( &proc );
+
+ proc << "svn" << "status" << "-v" << "--xml" << info.absFilePath();
+
+ if( !proc.start( KProcess::Block, KProcess::Stdout ) )
+ return ERROR_IN_WC;
+
+ QDomDocument doc;
+ QString errorMsg;
+ int errorLine, errorCol;
+ QDomNodeList nodelist;
+ QDomNode node;
+ QDomElement entry, wcStatus;
+
+ // Parse the output.
+ if ( !doc.setContent( out.getOutput(), &errorMsg, &errorLine, &errorCol ) ) {
+ kdDebug(8109) << "Cannot parse \"svn status -v --xml\" output for"
+ << filename << endl << "Line: " << errorLine << " Column: "
+ << errorCol << " Error: " << errorMsg << endl;
+ goto no_status_xml;
+ }
+
+ // There should be only one "entry" element. If it doesn't exist, path
+ // isn't repo path at all.
+ nodelist = doc.elementsByTagName("entry");
+ if (nodelist.count() < 1)
+ return NOT_IN_SVN;
+
+ entry = nodelist.item(0).toElement();
+
+ // Shouldn't fail, but just in case there is some weird error.
+ if ( entry.attributeNode("path").value() != info.absFilePath() )
+ return ERROR_IN_WC;
+
+ for ( node = entry.firstChild(); !node.isNull(); node = node.nextSibling() ) {
+ if ( !node.isElement() )
+ continue;
+ if (node.toElement().tagName() == "wc-status")
+ break;
+ }
+
+ if ( node.isNull() )
+ return ERROR_IN_WC;
+
+ wcStatus = node.toElement();
+
+ if ( wcStatus.attributeNode("item").value() == "normal" )
+ return UP_TO_DATE;
+ if ( wcStatus.attributeNode("item").value() == "modified" )
+ return LOCALLY_MODIFIED;
+ if ( wcStatus.attributeNode("item").value() == "conflicted" )
+ return CONFLICT;
+ if ( wcStatus.attributeNode("item").value() == "unversioned" )
+ return NOT_IN_SVN;
+ // TODO Ignored entry should have separate return value probably.
+ if ( wcStatus.attributeNode("item").value() == "ignored" )
+ return NOT_IN_SVN;
+ if ( wcStatus.attributeNode("item").value() == "added" )
+ return LOCALLY_ADDED;
+ if ( wcStatus.attributeNode("item").value() == "deleted" )
+ return LOCALLY_REMOVED;
+ // TODO What to do with "missing", "incomplete", "replaced", "merged",
+ // "obstructed", "external"? Can these appear at all in our case?
+
+ return ERROR_IN_WC;
+
+no_status_xml:
+ if ( !entries.open( IO_ReadOnly ) )
+ return ERROR_IN_WC; // we already know that it is a repository
+
+ // Parse the entries file
+ if ( !doc.setContent( &entries, &errorMsg, &errorLine, &errorCol ) ) {
+ kdDebug() << "Cannot parse .svn/entries file for " << filename << endl
+ << "Line: " << errorLine << " Column: " << errorCol << " Error: " << errorMsg << endl;
+ return ERROR_IN_WC;
+ }
+ entries.close();
+
+ QDomElement element;
+ // File name that we are searching
+ const QString findName = info.fileName();
+ // The entries are <entry> elements, so we have to check them
+ QDomNode child = doc.documentElement().firstChild();
+ for ( ; !child.isNull() ; child = child.nextSibling() )
+ {
+ if ( !child.isElement() )
+ continue;
+ element = child.toElement();
+ if ( element.tagName() != "entry" ) {
+ // We have another kind of element, so skip it
+ // Should not happend with svn 1.1.x
+ continue;
+ }
+ const QString name = element.attribute("name");
+ if ( name == findName )
+ break;
+ }
+
+ if ( child.isNull() ) {
+ // We have not found an entry for the file
+ return NOT_IN_SVN;
+ }
+
+ // ### TODO: should we check the attribute kind to be file and not dir?
+
+ // ### TODO: what do copy and move add here?
+ const QString onSchedule = element.attribute( "schedule" );
+ if ( onSchedule == "delete" )
+ return LOCALLY_REMOVED;
+ else if ( onSchedule == "added" )
+ return LOCALLY_ADDED;
+
+ if ( element.hasAttribute( "conflict-new" ) || element.hasAttribute( "conflict-old" ) || element.hasAttribute( "conflict-wrk" ) ) {
+ return CONFLICT;
+ }
+
+ // Note: we do not check the property time stamp
+ const QString textTimeStamp( element.attribute( "text-time" ) );
+
+ // calculate the UTC time from the file's last modified date
+ struct stat st;
+ lstat( QFile::encodeName(fn), &st );
+ struct tm * tm_p = gmtime( &st.st_mtime );
+ const int year = tm_p->tm_year + 1900;
+ const int month = tm_p->tm_mon + 1;
+ QString fileTime;
+ fileTime.sprintf( "%04i-%02i-%02iT%02i:%02i:%02i.000000Z",
+ year, month, tm_p->tm_mday, tm_p->tm_hour, tm_p->tm_min, tm_p->tm_sec );
+ //kdDebug() << "File: " << filename << " SVN time: " << textTimeStamp << " File time: " << fileTime << endl;
+ if ( fileTime > textTimeStamp ) // ISO 8601 dates/times can be compared as strings if they have the exact same format.
+ return LOCALLY_MODIFIED;
+
+ return UP_TO_DATE;
+
+}
+
+QString SVNHandler::svnStatus( const QString& filename ) const
+{
+ return map[filename];
+}
+
+void SVNHandler::execSVNCommand( QWidget* parent, SVN::Command cmd, const QString& filename, bool templates, KSharedConfig* config)
+{
+ // Unlike cvs, svn works also from outside the repository(as long as the path is in a repository of course!)
+ // ### FIXME: wrong, svn commit cannot work if the current directory is not a SVN one
+ execSVNCommand( parent, cmd, QStringList( filename ), templates, config );
+}
+
+void SVNHandler::execSVNCommand( QWidget* parent, SVN::Command cmd, const QStringList& files, bool templates, KSharedConfig* config )
+{
+ if ( !_isPORepository ) {
+ // This message box should never be visible but who knows... ;-)
+ KMessageBox::sorry( parent, i18n( "This is not a valid SVN repository. "
+ "The SVN commands cannot be executed." ) );
+ return;
+ }
+
+ // ### TODO: instead of making a QString, use KProcess directly, so that it cares about quoting.
+ // ### TODO: use KProcess::setWorkingDirectory instead of using "cd" (therefore allowing to use KProcess without a shell.)
+ QString command("cd " + (templates ? _potBaseDir : _poBaseDir) + " && svn ");
+ switch ( cmd ) {
+ case SVN::Update:
+ command += "update --non-interactive";
+ break;
+ case SVN::Commit:
+ // The svn client allows to choose the encoding, so we select UTF-8
+ command += "commit -F @LOG@FILE@ --encoding UTF-8 --non-interactive";
+ checkToAdd( files );
+ break;
+ case SVN::StatusRemote:
+ command += "status -u --non-interactive";
+ break;
+ case SVN::StatusLocal:
+ command += "status --non-interactive";
+ break;
+ case SVN::Diff:
+ command += "diff --non-interactive";
+ break;
+ case SVN::Info:
+ command += "info"; // Does not allow --non-interactive (at least svn 1.1.4).
+ }
+
+ QRegExp rx;
+ if (templates)
+ rx.setPattern(_potBaseDir + "/?");
+ else
+ rx.setPattern(_poBaseDir + "/?");
+
+ QStringList::ConstIterator it;
+ for ( it = files.begin( ); it != files.end( ); ++it ) {
+ QString temp = *it;
+ temp.remove(rx);
+ command += " \'" + temp + "\'";
+ }
+
+ showDialog( parent, cmd, files, command, config );
+}
+
+void SVNHandler::setAutoUpdateTemplates( bool update )
+{
+ _autoUpdateTemplates = update;
+}
+
+void SVNHandler::showDialog( QWidget* parent, SVN::Command cmd, const QStringList& files, const QString& commandLine, KSharedConfig* config )
+{
+ SVNDialog * dia = new SVNDialog( cmd, parent, config );
+ dia->setFiles( files );
+ dia->setCommandLine( commandLine );
+ if ( cmd == SVN::Commit ) {
+ dia->setAddCommand( _addCommand );
+ }
+
+ if ( dia->exec( ) == KDialog::Accepted ) {
+ if ( cmd == SVN::StatusLocal || cmd == SVN::StatusRemote )
+ processStatusOutput( dia->statusOutput( ) );
+ if ( cmd == SVN::Diff )
+ processDiff( dia->statusOutput( ) );
+ }
+
+ delete dia;
+
+ // file status display update necessary in Catalog Manager
+ if ( cmd == SVN::Commit )
+ emit signalFilesCommitted( files );
+}
+
+bool SVNHandler::isInSvn( const QString& path )
+{
+ if ( path.isEmpty() )
+ return false;
+
+ /*
+ * We need to check if a file is in a SVN repository.
+ *
+ * But as we want to do it quickly (because this function will be called for a few files in a row)
+ * we should avoid to parse the .svn/entries files
+ *
+ * Therefore we only check for the SVN auxilary files that are typical for a file controlled by SVN:
+ * - for a directory: checks if the directory has a .svn/entries file
+ * - for a file: check if there is a corresponding file in .svn/text-base/
+ */
+
+ const QFileInfo info( path );
+ if ( info.isDir() ) {
+ // It is a directory, so find a .svn/entries file
+ QDir dir( path );
+ return dir.exists( ".svn/entries", true );
+ }
+ else {
+ // It is a file, so find the corresponding file in .svn/text-base
+ QDir dir( info.dirPath() );
+ if ( ! dir.cd( ".svn/text-base" ) ) {
+ // There is not even a .svn/text-base directory, so the file is not under control
+ return false;
+ }
+ const QString textBaseFilename( info.fileName() + ".svn-base" );
+ return dir.exists( textBaseFilename, true );
+ }
+}
+
+void SVNHandler::checkToAdd( const QStringList& files )
+{
+ if ( files.isEmpty( ) )
+ return;
+
+ QStringList toBeAdded;
+
+ QStringList::ConstIterator it;
+ for ( it = files.begin( ); it != files.end( ); ++it ) {
+ // check for every entry if it needs to be added
+ if ( ! isInSvn( *it ) ) {
+ QFileInfo info( *it );
+ QString temp; // will hold the dir path
+ if ( info.isDir( ) ) {
+ toBeAdded << *it;
+ temp = *it;
+ } else {
+ toBeAdded << *it;
+ temp = QFileInfo( *it ).dirPath( true );
+ }
+
+ // ### TODO: does SVN really needs this or does it do it automatically?
+ // check recursivlely if parent dirs have to be added as well
+ while ( ! isInSvn( temp ) && toBeAdded.findIndex( temp ) == -1 ) {
+ toBeAdded << temp;
+ temp = QFileInfo( temp ).dirPath( true );
+ }
+
+ }
+ }
+
+ // remove an old command
+ _addCommand = QString();
+
+ // ### TODO: does SVN really need this?
+ // make sure the directories are added before the files
+ toBeAdded.sort( );
+
+ // ### TODO: try to make this better
+ // create a command line for adding the files and dirs
+ for ( it = toBeAdded.begin( ); it != toBeAdded.end( ); ++it ) {
+ QFileInfo info( *it );
+ _addCommand += "cd " + info.dirPath( true ) + " && svn add " + info.fileName( ) + "; ";
+ }
+}
+
+// ### TODO: convert to SVN
+void SVNHandler::processStatusOutput( const QString& status )
+{
+ if ( !_isPORepository )
+ return;
+
+#if 0
+ // at first we need to extract the name of the base directory on the server
+ QFile f( _poBaseDir + "/SVN/Root" ); // ### FIXME
+ if ( !f.open( IO_ReadOnly ) )
+ return;
+
+ QTextStream stream( &f );
+ // extract the string after the last colon in the first line
+ QString basedir = stream.readLine( ).section( ':', -1 );
+
+ f.close( );
+
+ // divide the complete status output in little chunks for every file
+ QStringList entries = QStringList::split( QRegExp( "={67,67}" ), status );
+ QStringList::Iterator it;
+ for ( it = entries.begin( ); it != entries.end( ); ++it ) {
+ QString entr = *it;
+ // translate the filename from repository to local
+ QRegExp rx( basedir + ".*,v" );
+ int pos = entr.find( rx );
+ QString file = _poBaseDir + entr.mid( pos + basedir.length( ),
+ rx.matchedLength( ) - basedir.length( ) - 2 );
+
+ entr = "<qt>" + entr + "</qt>";
+
+ // TODO: do some markup
+
+ map.replace( file, entr );
+ }
+#endif
+}
+
+void SVNHandler::processDiff( QString output )
+{
+ output.remove( QRegExp( "\\[ .* \\]$" ));
+ output.remove( QRegExp( "^" + i18n("[ Starting command ]" ).replace("[","\\[").replace("]","\\]")));
+
+ KTempFile tmpFile;
+ *(tmpFile.textStream()) << output;
+ tmpFile.close();
+
+ QString error;
+ if ( KApplication::startServiceByName( "Kompare", tmpFile.name(), &error ) )
+ KMessageBox::error( 0, error );
+}
+
+bool SVNHandler::isConsideredModified( const FileStatus status ) const
+{
+ /*
+ * A file is modified if it is either:
+ * - locally modified for SVN
+ * - directory under SVN control but not the file
+ */
+
+ // ### TODO: what about moved and copied?
+ return status == LOCALLY_MODIFIED || status == NOT_IN_SVN;
+}
+
+SVNOutputCollector::SVNOutputCollector( KProcess* p )
+ : m_process(0)
+{
+ setProcess( p );
+}
+
+void SVNOutputCollector::setProcess( KProcess* p )
+{
+ if( m_process )
+ m_process->disconnect( this );
+
+ m_process = p;
+ if( p ) {
+ connect( p, SIGNAL(receivedStdout(KProcess*, char*, int)),
+ this, SLOT(slotGatherStdout(KProcess*, char*, int)) );
+ connect( p, SIGNAL(receivedStderr(KProcess*, char*, int)),
+ this, SLOT(slotGatherStderr(KProcess*, char*, int)) );
+ }
+
+ m_gatheredOutput.truncate( 0 );
+ m_stderrOutput.truncate( 0 );
+ m_stdoutOutput.truncate( 0 );
+}
+
+void SVNOutputCollector::slotGatherStderr( KProcess*, char* data, int len )
+{
+ m_gatheredOutput.append( QString::fromLocal8Bit( data, len ) );
+ m_stderrOutput.append( QString::fromLocal8Bit( data, len ) );
+}
+
+void SVNOutputCollector::slotGatherStdout( KProcess*, char* data, int len )
+{
+ m_gatheredOutput.append( QString::fromLocal8Bit( data, len ) );
+ m_stdoutOutput.append( QString::fromLocal8Bit( data, len ) );
+}
+
+#include "svnhandler.moc"
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/kbabel/catalogmanager/libsvn/svnhandler.h b/kbabel/catalogmanager/libsvn/svnhandler.h
new file mode 100644
index 00000000..67c86d73
--- /dev/null
+++ b/kbabel/catalogmanager/libsvn/svnhandler.h
@@ -0,0 +1,138 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002-2003 by Marco Wegner <mail@marcowegner.de>
+ Copyright (C) 2005, 2006 by Nicolas GOUTTE <goutte@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#ifndef SVNHANDLER_H
+#define SVNHANDLER_H
+
+// Qt include files
+#include <qmap.h>
+#include <qobject.h>
+// Project specific include files
+#include "svndialog.h"
+#include "svnresources.h"
+// Forwarding Qt classes
+class QString;
+class QStringList;
+
+class KSharedConfig;
+
+/**
+ * This class is the backend for SVN support in Catalog Manager.
+ *
+ * @short Backend for SVN support in Catalog Manager
+ */
+class SVNHandler : public QObject
+{
+ Q_OBJECT
+
+ public:
+ enum FileStatus {
+ NO_REPOSITORY,
+ NOT_IN_SVN,
+ LOCALLY_ADDED,
+ LOCALLY_REMOVED,
+ LOCALLY_MODIFIED,
+ CONFLICT,
+ UP_TO_DATE,
+ ERROR_IN_WC ///< The working copy has data that cannot be handled
+ };
+
+ SVNHandler( const QString& poBaseDir = QString::null, const QString& potBaseDir = QString::null );
+
+ void setPOBaseDir( const QString& dir );
+ void setPOTBaseDir( const QString& dir );
+
+ FileStatus fstatus( const QString& filename ) const;
+ QString fileStatus( const FileStatus status ) const;
+ QString svnStatus( const QString& filename ) const;
+
+ void execSVNCommand( QWidget* parent, SVN::Command cmd, const QString& filename, bool templates, KSharedConfig* config );
+ void execSVNCommand( QWidget* parent, SVN::Command cmd, const QStringList& files, bool templates, KSharedConfig* config );
+
+ void setAutoUpdateTemplates( bool update );
+
+ /**
+ * True if the file was modified or has another status considered as a modification
+ */
+ bool isConsideredModified( const FileStatus status ) const;
+
+ signals:
+ void signalIsPORepository( bool );
+ void signalIsPOTRepository( bool );
+ void signalFilesCommitted( const QStringList& );
+
+ private:
+ void showDialog( QWidget* parent, SVN::Command cmd, const QStringList& files, const QString& commandLine, KSharedConfig* config );
+ /// Check quickly if the file is part of a SVN repository
+ bool isInSvn( const QString& path );
+ void checkToAdd( const QStringList& files );
+ void processStatusOutput( const QString& status );
+ void processDiff( QString output );
+
+ private:
+ QString _poBaseDir;
+ QString _potBaseDir;
+ bool _isPORepository;
+ bool _isPOTRepository;
+ bool _autoUpdateTemplates;
+ QString _addCommand;
+
+ /** Mapping the output of 'svn status' against the filename. */
+ QMap<QString,QString> map;
+};
+
+class SVNOutputCollector: public QObject
+{
+ Q_OBJECT
+
+ public:
+ SVNOutputCollector( KProcess* );
+ void setProcess( KProcess* );
+
+ const QString& getOutput() const { return m_gatheredOutput; }
+ const QString& getStderr() const { return m_stderrOutput; }
+ const QString& getStdout() const { return m_stdoutOutput; }
+
+ private slots:
+ void slotGatherStderr( KProcess*, char*, int );
+ void slotGatherStdout( KProcess*, char*, int );
+
+ private:
+ QString m_gatheredOutput;
+ QString m_stderrOutput;
+ QString m_stdoutOutput;
+ KProcess* m_process;
+};
+
+#endif // SVNHANDLER_H
diff --git a/kbabel/catalogmanager/libsvn/svnresources.h b/kbabel/catalogmanager/libsvn/svnresources.h
new file mode 100644
index 00000000..d9032a4f
--- /dev/null
+++ b/kbabel/catalogmanager/libsvn/svnresources.h
@@ -0,0 +1,50 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002-2003 by Marco Wegner <mail@marcowegner.de>
+ Copyright (C) 2005 by Nicolas GOUTTE <goutte@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#ifndef SVNRESOURCES_H
+#define SVNRESOURCES_H
+
+namespace SVN {
+ enum Command
+ {
+ Update, ///< svn update
+ Commit, ///< svn commit
+ StatusLocal, ///< svn status
+ StatusRemote, ///< svn status -u
+ Diff, ///< svn diff
+ Info ///< svn info
+ };
+}
+
+#endif // SVNRESOURCES_H
diff --git a/kbabel/catalogmanager/lo16-app-catalogmanager.png b/kbabel/catalogmanager/lo16-app-catalogmanager.png
new file mode 100644
index 00000000..27a7f453
--- /dev/null
+++ b/kbabel/catalogmanager/lo16-app-catalogmanager.png
Binary files differ
diff --git a/kbabel/catalogmanager/lo32-app-catalogmanager.png b/kbabel/catalogmanager/lo32-app-catalogmanager.png
new file mode 100644
index 00000000..eef514b4
--- /dev/null
+++ b/kbabel/catalogmanager/lo32-app-catalogmanager.png
Binary files differ
diff --git a/kbabel/catalogmanager/main.cpp b/kbabel/catalogmanager/main.cpp
new file mode 100644
index 00000000..868df92a
--- /dev/null
+++ b/kbabel/catalogmanager/main.cpp
@@ -0,0 +1,232 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2001 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2001-2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include "kbprojectmanager.h"
+#include "catalogmanager.h"
+#include "catalogmanageriface.h"
+#include "catalog.h"
+#include "catalogmanagerapp.h"
+#include "poinfo.h"
+
+#include "version.h"
+#include "resources.h"
+
+#include <dcopclient.h>
+#include <kaboutdata.h>
+#include <kcmdlineargs.h>
+#include <kcursor.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+#include <kapplication.h>
+#include <kwin.h>
+#include <kmainwindow.h>
+
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qregexp.h>
+#include <qtimer.h>
+
+CatalogManager *CatalogManagerApp::_view = 0;
+
+CatalogManagerApp::CatalogManagerApp()
+ : KApplication()
+{
+ kbInterface = new CatalogManagerInterface;
+ _view = 0;
+ _preferredWindow = 0;
+}
+
+CatalogManagerApp::~CatalogManagerApp()
+{
+ delete kbInterface;
+ KBabel::PoInfo::cacheWrite();
+}
+
+void CatalogManagerApp::setPreferredWindow(WId id)
+{
+ _preferredWindow = id;
+ if( _view )
+ {
+ _view->raise();
+ KWin::activateWindow(_view->winId());
+ }
+}
+
+void CatalogManagerApp::updatedFile(QCString url)
+{
+ if( _view )
+ _view->updateFile(url);
+}
+
+QCString CatalogManagerApp::findNextFile()
+{
+ QString reply = "";
+ if( !CatalogManager::_foundFilesList.isEmpty() )
+ {
+ reply = CatalogManager::_foundFilesList.first();
+ CatalogManager::_foundFilesList.pop_front();
+ if( _view ) _view->decreaseNumberOfFound();
+ } else
+ {
+ if( !CatalogManager::_toBeSearched.isEmpty() )
+ reply = QString(""); // nothing found yet
+ else
+ return QCString(); // not found definitely
+ }
+
+ return reply.utf8();
+}
+
+int CatalogManagerApp::newInstance()
+{
+ if( isRestored() )
+ {
+ int n = 1;
+ while (KMainWindow::canBeRestored(n)){
+ CatalogManager* cm = new CatalogManager();
+ cm->restore(n);
+ n++;
+
+ // this view will be used as DCOP dispatcher
+ if( !_view )
+ _view = cm;
+ }
+ }
+ else
+ {
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+ QString configfile = args->getOption("project");
+
+ if( !configfile.isEmpty() )
+ {
+ QFileInfo fi( configfile );
+ configfile = fi.absFilePath();
+ }
+ else
+ {
+ configfile = KBabel::ProjectManager::defaultProjectName();
+ }
+
+ _view=new CatalogManager(configfile);
+
+ _view->setPreferredWindow( _preferredWindow );
+ _view->show();
+ _view->raise();
+ KWin::activateWindow(_view->winId());
+
+ args->clear();
+ }
+
+ return 0;
+}
+
+CatalogManagerInterface::CatalogManagerInterface()
+ : DCOPObject("CatalogManagerIFace")
+{
+}
+
+void CatalogManagerInterface::setPreferredWindow( WId id )
+{
+ CatalogManagerApp::setPreferredWindow(id);
+}
+
+QCString CatalogManagerInterface::findNextFile()
+{
+ return CatalogManagerApp::findNextFile();
+}
+
+void CatalogManagerInterface::updatedFile( QCString url )
+{
+ CatalogManagerApp::updatedFile(url);
+}
+
+static KCmdLineOptions options[] =
+{
+ {"project <configfile>",I18N_NOOP("File to load configuration from"),0},
+ KCmdLineLastOption
+};
+
+
+int main(int argc, char **argv)
+{
+ KLocale::setMainCatalogue("kbabel");
+ KAboutData about("catalogmanager",I18N_NOOP("KBabel - Catalog Manager"),VERSION,
+ I18N_NOOP("An advanced catalog manager for KBabel"),KAboutData::License_GPL,
+ I18N_NOOP("(c) 1999,2000,2001,2002,2003,2004,2005,2006 The KBabel developers"),0,"http://kbabel.kde.org");
+
+ about.addAuthor("Matthias Kiefer",I18N_NOOP("Original author"),"kiefer@kde.org");
+ about.addAuthor("Stanislav Visnovsky",I18N_NOOP("Current maintainer, porting to KDE3/Qt3.")
+ ,"visnovsky@kde.org");
+ about.addAuthor("Nicolas Goutte", I18N_NOOP("Current maintainer"), "goutte@kde.org");
+
+ about.addCredit("Claudiu Costin",I18N_NOOP("Wrote documentation and sent "
+ "many bug reports and suggestions for improvements.")
+ ,"claudiuc@kde.org");
+ about.addCredit("Thomas Diehl",I18N_NOOP("Gave many suggestions for the GUI "
+ "and the behavior of KBabel. He also contributed the beautiful splash screen.")
+ ,"thd@kde.org");
+ about.addCredit("Wolfram Diestel"
+ ,I18N_NOOP("Wrote diff algorithm, fixed KSpell and gave a lot "
+ "of useful hints."),"wolfram@steloj.de");
+ about.addCredit("Stephan Kulow",I18N_NOOP("Helped keep KBabel up to date "
+ "with the KDE API and gave a lot of other help."),"coolo@kde.org");
+ about.addCredit("Dwayne Bailey",I18N_NOOP("Various validation plugins.")
+ ,"dwayne@translate.org.za");
+ about.addCredit("SuSE GmbH"
+ ,I18N_NOOP("Sponsored development of KBabel for a while.")
+ ,"suse@suse.de","http://www.suse.de");
+ about.addCredit("Bram Schoenmakers",I18N_NOOP("Support for making diffs and some minor "
+ "improvements."),"bramschoenmakers@kde.nl");
+
+ about.addCredit("Trolltech", I18N_NOOP("KBabel contains code from Qt"), 0, "http://www.trolltech.com");
+
+ about.addCredit("GNU gettext", I18N_NOOP("KBabel contains code from GNU gettext"), 0, "http://www.gnu.org/software/gettext/");
+
+ // Initialize command line args
+ KCmdLineArgs::init(argc, argv, &about);
+
+ // Tell which options are supported
+ KCmdLineArgs::addCmdLineOptions( options );
+
+ // Add options from other components
+ KApplication::addCmdLineOptions();
+
+ CatalogManagerApp app;
+
+ app.newInstance();
+
+ return app.exec();
+}
diff --git a/kbabel/catalogmanager/markpatterndialog.cpp b/kbabel/catalogmanager/markpatterndialog.cpp
new file mode 100644
index 00000000..efe893a2
--- /dev/null
+++ b/kbabel/catalogmanager/markpatterndialog.cpp
@@ -0,0 +1,172 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2003 by Marco Wegner <mail@marcowegner.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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qradiobutton.h>
+
+#include <kcombobox.h>
+#include <kcompletion.h>
+#include <kconfig.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kparts/componentfactory.h>
+#include <kregexpeditorinterface.h>
+
+#include "markpatterndialog.h"
+#include "markpatternwidget.h"
+
+MarkPatternDialog::MarkPatternDialog(QWidget * parent, const char * name)
+ : KDialogBase(parent, name, true, 0, Ok|Cancel, Ok)
+{
+ actionButton(Ok)->setEnabled(false);
+
+ mainWidget = new MarkPatternWidget(this);
+
+ connect (mainWidget->combo, SIGNAL(textChanged(const QString&)),
+ this, SLOT(slotComboTextChanged(const QString&)));
+
+ comboCompletion = mainWidget->combo->completionObject( );
+
+ regexpEditDialog = 0;
+ if (!KTrader::self( )->query("KRegExpEditor/KRegExpEditor").isEmpty( )) {
+ connect(mainWidget->regexpButton, SIGNAL(clicked( )), this, SLOT(slotRegexpButtonClicked( )));
+ } else {
+ disconnect(mainWidget->useRegExp, 0, mainWidget->regexpButton, 0);
+ delete mainWidget->regexpButton;
+ mainWidget->regexpButton = 0;
+ }
+
+ restoreSettings( );
+
+ actionButton(Ok)->setEnabled(!mainWidget->combo->currentText( ).isEmpty( ));
+ mainWidget->combo->setFocus( );
+ setMainWidget( mainWidget);
+}
+
+void MarkPatternDialog::accept( )
+{
+ // Update the list of patterns.
+ patternList.remove(mainWidget->combo->currentText( ));
+ patternList.prepend(mainWidget->combo->currentText( ));
+ while (patternList.count( ) > 10)
+ patternList.remove(patternList.last( ));
+
+ saveSettings( );
+ KDialogBase::accept( );
+}
+
+QString MarkPatternDialog::pattern( )
+{
+ return mainWidget->combo->currentText( );
+}
+
+bool MarkPatternDialog::isCaseSensitive( )
+{
+ return mainWidget->caseSensitive->isChecked( );
+}
+
+bool MarkPatternDialog::includeTemplates( )
+{
+ return mainWidget->inclTemplates->isChecked( );
+}
+
+bool MarkPatternDialog::useRegExp( )
+{
+ return mainWidget->useRegExp->isChecked( );
+}
+
+void MarkPatternDialog::setMode(bool markMode)
+{
+ if (markMode) {
+ mainWidget->mainLabel->setText(i18n("Ma&rk files which match the following pattern:"));
+ setButtonOKText(i18n("&Mark Files"));
+ } else {
+ mainWidget->mainLabel->setText(i18n("Unma&rk files which match the following pattern:"));
+ setButtonOKText(i18n("Un&mark Files"));
+ }
+}
+
+void MarkPatternDialog::slotComboTextChanged(const QString& text)
+{
+ actionButton(Ok)->setEnabled(!text.isEmpty( ));
+}
+
+void MarkPatternDialog::slotRegexpButtonClicked( )
+{
+ if (!regexpEditDialog)
+ regexpEditDialog = KParts::ComponentFactory::createInstanceFromQuery<QDialog>(
+ "KRegExpEditor/KRegExpEditor", QString::null, this);
+
+ KRegExpEditorInterface * iface = dynamic_cast<KRegExpEditorInterface *>(regexpEditDialog);
+
+ if (iface) {
+ iface->setRegExp(mainWidget->combo->currentText( ));
+ if (regexpEditDialog->exec( ) == QDialog::Accepted)
+ mainWidget->combo->setCurrentText(iface->regExp( ));
+ }
+}
+
+void MarkPatternDialog::restoreSettings( )
+{
+ KConfig * config = KGlobal::config( );
+ config->setGroup("MarkPatternDialog");
+
+ patternList = config->readListEntry("Patterns");
+ mainWidget->combo->insertStringList(patternList);
+ comboCompletion->insertItems(patternList);
+ mainWidget->caseSensitive->setChecked(config->readBoolEntry("CaseSensitive", false));
+ mainWidget->inclTemplates->setChecked(config->readBoolEntry("IncludeTemplates", false));
+
+ bool rx = config->readBoolEntry("UseRegExp", false);
+ if (rx)
+ mainWidget->useRegExp->setChecked(true);
+ else
+ mainWidget->useWildcards->setChecked(true);
+ if (mainWidget->regexpButton)
+ mainWidget->regexpButton->setEnabled(mainWidget->useRegExp->isChecked( ));
+}
+
+void MarkPatternDialog::saveSettings( )
+{
+ KConfig * config = KGlobal::config( );
+ config->setGroup("MarkPatternDialog");
+
+ config->writeEntry("Patterns", patternList);
+ config->writeEntry("CaseSensitive", mainWidget->caseSensitive->isChecked( ));
+ config->writeEntry("IncludeTemplates", mainWidget->inclTemplates->isChecked( ));
+ config->writeEntry("UseRegExp", mainWidget->useRegExp->isChecked( ));
+}
+
+#include "markpatterndialog.moc"
diff --git a/kbabel/catalogmanager/markpatterndialog.h b/kbabel/catalogmanager/markpatterndialog.h
new file mode 100644
index 00000000..c8ec1218
--- /dev/null
+++ b/kbabel/catalogmanager/markpatterndialog.h
@@ -0,0 +1,75 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2003 by Marco Wegner <mail@marcowegner.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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#ifndef MARKPATTERNDIALOG_H
+#define MARKPATTERNDIALOG_H
+
+#include <kdialogbase.h>
+
+class KCompletion;
+
+class MarkPatternWidget;
+
+class MarkPatternDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ MarkPatternDialog(QWidget * parent, const char * name = 0);
+
+ QString pattern( );
+ bool isCaseSensitive( );
+ bool useRegExp( );
+ bool includeTemplates( );
+
+ void setMode(bool markMode);
+
+ protected:
+ virtual void accept( );
+ void restoreSettings( );
+ void saveSettings( );
+
+ protected slots:
+ void slotComboTextChanged(const QString& text);
+ void slotRegexpButtonClicked( );
+
+ private:
+ MarkPatternWidget * mainWidget;
+ QDialog * regexpEditDialog;
+
+ QStringList patternList;
+
+ KCompletion * comboCompletion;
+};
+
+#endif // MARKPATTERNDIALOG_H
diff --git a/kbabel/catalogmanager/markpatternwidget.ui b/kbabel/catalogmanager/markpatternwidget.ui
new file mode 100644
index 00000000..b4b8745e
--- /dev/null
+++ b/kbabel/catalogmanager/markpatternwidget.ui
@@ -0,0 +1,127 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>MarkPatternWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>MarkPatternWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>374</width>
+ <height>276</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>mainLabel</cstring>
+ </property>
+ <property name="text">
+ <string>To be set dynamically:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>combo</cstring>
+ </property>
+ </widget>
+ <widget class="KComboBox">
+ <property name="name">
+ <cstring>combo</cstring>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>buttonGroup1</cstring>
+ </property>
+ <property name="title">
+ <string>Options</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>caseSensitive</cstring>
+ </property>
+ <property name="text">
+ <string>C&amp;ase sensitive</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>inclTemplates</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Include templates</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="3" column="0">
+ <property name="name">
+ <cstring>useWildcards</cstring>
+ </property>
+ <property name="text">
+ <string>Use &amp;wildcards</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="4" column="1">
+ <property name="name">
+ <cstring>regexpButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Edit</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="4" column="0">
+ <property name="name">
+ <cstring>useRegExp</cstring>
+ </property>
+ <property name="text">
+ <string>Use regu&amp;lar expression</string>
+ </property>
+ </widget>
+ <widget class="Line" row="2" column="0" rowspan="1" colspan="2">
+ <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>
+ </grid>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<connections>
+ <connection>
+ <sender>useRegExp</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>regexpButton</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<includes>
+ <include location="global" impldecl="in implementation">kcombobox.h</include>
+</includes>
+<forwards>
+ <forward>class KComboBox;</forward>
+</forwards>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klineedit.h</includehint>
+</includehints>
+</UI>
diff --git a/kbabel/catalogmanager/multiroughtransdlg.cpp b/kbabel/catalogmanager/multiroughtransdlg.cpp
new file mode 100644
index 00000000..874b9c3e
--- /dev/null
+++ b/kbabel/catalogmanager/multiroughtransdlg.cpp
@@ -0,0 +1,148 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2001 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2002 by Stanislav Visnovsky <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include "catalog.h"
+#include "catmanlistitem.h"
+#include "multiroughtransdlg.h"
+
+#include <qlabel.h>
+#include <qlayout.h>
+
+#include <kdebug.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kprogress.h>
+#include <kurl.h>
+
+using namespace KBabel;
+
+MultiRoughTransDlg::MultiRoughTransDlg(KBabelDictBox *dict, QPtrList<CatManListItem> files
+ , QWidget *parent,const char *name)
+ : RoughTransDlg(dict, new Catalog(), parent, name )
+ ,_fileList(files)
+{
+ QWidget* bars = static_cast<QWidget*>(progressbar->parent());
+ QLabel* label = new QLabel( i18n("Files:"), bars );
+ filesProgressbar = new KProgress(bars,"files progressbar");
+ filesProgressbar->setTextEnabled(true);
+ filesProgressbar->setFormat("%v/%m (%p%)");
+ filesProgressbar->setTotalSteps(files.count());
+ QHBoxLayout* mylayout= new QHBoxLayout(bars->layout());
+ mylayout->add(label);
+ mylayout->add(filesProgressbar);
+
+ msgButtonClicked(0);
+}
+
+void MultiRoughTransDlg::msgButtonClicked(int id)
+{
+ RoughTransDlg::msgButtonClicked(id);
+
+ enableButton(User1,true);
+}
+
+void MultiRoughTransDlg::translate()
+{
+ for ( CatManListItem* it = _fileList.first(); it ; it = _fileList.next() )
+ {
+ if( it->hasPo() )
+ {
+ KURL url( it->poFile() );
+ if( catalog->openURL( url ) != OK )
+ {
+ KMessageBox::error(this, i18n("Error while trying to read file:\n %1\n"
+ "Maybe it is not a valid PO file.").arg(url.prettyURL()));
+ filesProgressbar->advance(1);
+ continue;
+ }
+ } else
+ if( it->hasPot() )
+ {
+ KURL url( it->poFile() );
+ KURL poturl( it->potFile() );
+ if( catalog->openURL( poturl, url ) != OK )
+ {
+ KMessageBox::error(this, i18n("Error while trying to read file:\n %1\n"
+ "Maybe it is not a valid PO file.").arg(poturl.prettyURL()));
+ filesProgressbar->advance(1);
+ continue;
+ }
+ }
+
+ RoughTransDlg::translate();
+
+ if( stop || cancel ) break;
+
+ if( catalog->isModified() ) catalog->saveFile();
+
+ it->forceUpdate();
+ filesProgressbar->advance(1);
+ }
+
+ filesProgressbar->setValue(_fileList.count());
+
+ showAllStatistics();
+}
+
+void MultiRoughTransDlg::showAllStatistics()
+{
+ int tt, ptc, etc;
+
+ statistics( tt, ptc, etc);
+
+ // sanity check
+ if( tt == 0 ) tt = 1;
+
+ int nothing=tt-ptc-etc;
+ KLocale *locale = KGlobal::locale();
+ QString statMsg = i18n("Result of the translation:\n"
+ "Edited entries: %1\n"
+ "Exact translations: %2 (%3%)\n"
+ "Approximate translations: %4 (%5%)\n"
+ "Nothing found: %6 (%7%)")
+ .arg( locale->formatNumber(tt,0) )
+ .arg( locale->formatNumber(etc,0) )
+ .arg( locale->formatNumber( ((double)(10000*etc/tt))/100) )
+ .arg( locale->formatNumber(ptc,0) )
+ .arg( locale->formatNumber(((double)(10000*ptc/tt))/100) )
+ .arg( locale->formatNumber(nothing,0) )
+ .arg( locale->formatNumber(((double)(10000*nothing/tt)/100) ) );
+
+ KMessageBox::information(this, statMsg
+ , i18n("Rough Translation Statistics"));
+
+ accept();
+}
+
+#include "multiroughtransdlg.moc"
diff --git a/kbabel/catalogmanager/multiroughtransdlg.h b/kbabel/catalogmanager/multiroughtransdlg.h
new file mode 100644
index 00000000..8bda58e2
--- /dev/null
+++ b/kbabel/catalogmanager/multiroughtransdlg.h
@@ -0,0 +1,63 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef MULTIROUGHTRANSDLG_H
+#define MULTIROUGHTRANSDLG_H
+
+#include <roughtransdlg.h>
+
+class CatManListItem;
+
+class MultiRoughTransDlg : public RoughTransDlg
+{
+ Q_OBJECT
+
+public:
+ MultiRoughTransDlg(KBabelDictBox* dictBox, QPtrList<CatManListItem> list, QWidget *parent
+ , const char *name=0);
+
+protected slots:
+ virtual void translate();
+ // we show statistics at different point
+ virtual void showStatistics() {}
+ virtual void showAllStatistics();
+
+ // we need to enable Start button at different conditions
+ virtual void msgButtonClicked(int);
+
+private:
+
+ QPtrList<CatManListItem> _fileList;
+ KProgress *filesProgressbar;
+};
+
+#endif // ROUGHTRANSDLG_H
diff --git a/kbabel/catalogmanager/validateprogress.cpp b/kbabel/catalogmanager/validateprogress.cpp
new file mode 100644
index 00000000..9075f24e
--- /dev/null
+++ b/kbabel/catalogmanager/validateprogress.cpp
@@ -0,0 +1,313 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002-2003 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include "validateprogress.h"
+#include "validateprogresswidget.h"
+#include "catmanlistitem.h"
+#include "catmanresource.h"
+
+#include <kdebug.h>
+#include <kdatatool.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kpopupmenu.h>
+#include <kprogress.h>
+#include <ksqueezedtextlabel.h>
+
+#include <qlistbox.h>
+#include <qtimer.h>
+
+#define ID_ERROR_OPEN 1
+#define ID_ERROR_IGNORE 2
+
+// version identification for validation ignores
+#define IGNOREFILE_VERSION 0x00
+
+ValidateProgressDialog::ValidateProgressDialog(const QString& ignoreURL, QWidget *parent,const char *name)
+ : KDialogBase(parent,name,true,i18n("Caption of dialog","Validation")
+ , Close, Close)
+ , _ignoreURL(ignoreURL), _tool(0), _stopped(false)
+ , _ignoreFuzzy(false), _setAsFuzzy(false)
+
+{
+ _mainWidget = new ValidateProgressWidget(this);
+ setMainWidget(_mainWidget);
+ setInitialSize( QSize(400, 300) );
+
+ _errors.clear();
+ _ignores.clear();
+
+ readIgnores();
+
+ _errorMenu = new KPopupMenu(this);
+ _errorMenu->insertItem(i18n("&Open"),ID_ERROR_OPEN);
+ _errorMenu->insertItem(i18n("&Ignore"),ID_ERROR_IGNORE);
+
+ connect( this, SIGNAL(closeClicked()), this, SLOT(stop()));
+ connect( _mainWidget->_errorList, SIGNAL( doubleClicked(QListBoxItem *)),
+ this, SLOT( errorItemDoubleClicked(QListBoxItem *)));
+
+ connect( _mainWidget->_errorList, SIGNAL( contextMenuRequested(QListBoxItem *, const QPoint &)),
+ this, SLOT( showContextMenu(QListBoxItem *, const QPoint &)));
+}
+
+ValidateProgressDialog::~ValidateProgressDialog()
+{
+ writeIgnores();
+}
+
+void ValidateProgressDialog::validate( const KDataToolInfo &tool, const QPtrList<CatManListItem> files )
+{
+ if( files.isEmpty() ) return;
+
+ _errors.clear();
+
+ KDataTool* t = tool.createTool();
+
+ if( !t )
+ {
+ KMessageBox::error( this, i18n("Cannot instantiate a validation tool.\n"
+ "Please check your installation."), i18n("Validation Tool Error") );
+ return;
+ }
+
+ _tool = t;
+ _toolID = tool.service()->library();
+ _files = files;
+
+ _mainWidget->_errorList->clear();
+ _mainWidget->_currentTool->setText(*(tool.userCommands().at(0)));
+ _mainWidget->_overallProgress->setTotalSteps(files.count());
+ _mainWidget->_overallProgress->setValue(0);
+
+ _stopped = false;
+
+ QTimer::singleShot( 0, this, SLOT(validate_internal()) );
+
+ exec();
+
+ _stopped = true;
+}
+
+void ValidateProgressDialog::validate_internal()
+{
+ uint checked=0;
+ uint errors=0;
+ uint ignorederrors=0;
+
+ for( CatManListItem* it=_files.first() ; it && !_stopped ; it = _files.next() )
+ {
+ _mainWidget->_currentFile->setText( it->poFile() );
+
+ checked++;
+
+ _mainWidget->_currentFileProgress->setTotalSteps(100);
+ _mainWidget->_currentFileProgress->setValue(0);
+
+ it->checkErrors(_tool,_mainWidget, _ignoreFuzzy, _setAsFuzzy);
+
+ bool noHeader = true;
+
+ if( it->hasErrors() )
+ {
+ QValueList<IgnoreItem> err = it->errors();
+
+ for( QValueList<IgnoreItem>::Iterator errit = err.begin(); errit!=err.end() ; ++errit )
+ {
+ IgnoreItem item = (*errit);
+
+ QValueList<IgnoreItem>::Iterator ig;
+ for( ig = _ignores.begin() ; ig != _ignores.end() ; ++ig )
+ {
+ if( (*ig).validationTool == _toolID &&
+ (*ig).msgid == item.msgid &&
+ (*ig).msgstr == item.msgstr &&
+ (*ig).fileURL == item.fileURL ) break;
+ }
+
+ if( ig != _ignores.end() )
+ {
+ ++ignorederrors;
+ continue;
+ } ++errors;
+
+ if( noHeader )
+ {
+ _mainWidget->_errorList->insertItem( ICON_ERROR, it->package() );
+ _errors.insert( it->package(), err.first() );
+ noHeader = false;
+ }
+
+ QString errortext=QString::number(item.index+1)+": " + item.msgid.first().left(50);
+ errortext.replace("\n"," ");
+ if( item.msgid.first().length() > 50 ) errortext+="...";
+ _mainWidget->_errorList->insertItem( errortext);
+
+ _errors.insert( errortext, item );
+ }
+ }
+
+ _mainWidget->_currentFileProgress->setValue(100);
+
+ _mainWidget->_overallProgress->advance(1);
+ }
+
+ if( !_stopped )
+ {
+ KMessageBox::information(this, i18n("Validation done.\n"
+ "\n"
+ "Checked files: %1\n"
+ "Number of errors: %2\n"
+ "Number of ignored errors: %3").arg(checked).arg(errors).arg(ignorederrors),i18n("Validation Done"));
+ }
+
+ delete _tool;
+ _tool = 0;
+ _files.clear();
+}
+
+void ValidateProgressDialog::stop()
+{
+ _stopped = true;
+}
+
+void ValidateProgressDialog::errorItemDoubleClicked(QListBoxItem * item)
+{
+ QString it = item->text();
+
+ bool ok =false;
+ int offset = it.find(":");
+
+ int num;
+ if( offset < -1 ) num = 0;
+ else
+ {
+ num = it.left(offset).toInt(&ok);
+ if( !ok ) num = 0;
+ }
+
+ QListBoxItem* package=item;
+
+ while( package && !package->text().startsWith("/") ) package=package->prev();
+
+ if( !package )
+ {
+ kdWarning() << "Unable to find the package for the error" << endl;
+ return;
+ }
+
+ emit errorDoubleClicked(package->text(), num-1 );
+}
+
+void ValidateProgressDialog::showContextMenu(QListBoxItem * item, const QPoint & pos)
+{
+ // disable ignore for whole package
+ _errorMenu->setItemEnabled(ID_ERROR_IGNORE, item->pixmap()==0 );
+ int result = _errorMenu->exec(pos);
+ switch( result )
+ {
+ case ID_ERROR_OPEN:
+ errorItemDoubleClicked( item );
+ break;
+ case ID_ERROR_IGNORE:
+ IgnoreItem it = _errors.find(item->text()).data();
+
+ // if there is no pixmap, it's the whole file
+ if( !item->pixmap() )
+ {
+ it.validationTool = _toolID;
+ _ignores.append( it );
+ }
+ break;
+ }
+}
+
+void ValidateProgressDialog::readIgnores()
+{
+ IgnoreItem item;
+
+ QFile ignoreFile( _ignoreURL );
+ if( ignoreFile.open( IO_ReadOnly ) ) {
+ QDataStream s( &ignoreFile );
+ QString url;
+ int version;
+
+ s >> version;
+ if( version == IGNOREFILE_VERSION ) // Only read if correct versi
+ {
+ _ignores.clear();
+
+ while( !s.atEnd() ) {
+ s >> item;
+ _ignores.append(item);
+ }
+ }
+ ignoreFile.close();
+ }
+}
+
+void ValidateProgressDialog::writeIgnores()
+{
+ QFile ignoreFile( _ignoreURL );
+ if( ignoreFile.open( IO_WriteOnly ) ) {
+ QDataStream s( &ignoreFile );
+ QString url;
+ int version = IGNOREFILE_VERSION;
+
+ s << version;
+
+ for( QValueList<IgnoreItem>::Iterator it = _ignores.begin(); it!=_ignores.end(); ++it)
+ {
+ s << (*it);
+ }
+ ignoreFile.close();
+ }
+}
+
+QDataStream & operator<<( QDataStream & stream, const IgnoreItem & i )
+{
+ return stream << i.fileURL
+ << i.msgid
+ << i.msgstr
+ << i.index
+ << i.validationTool;
+}
+
+QDataStream & operator>>( QDataStream & stream, IgnoreItem & i ) {
+ return stream >> i.fileURL
+ >> i.msgid
+ >> i.msgstr
+ >> i.index
+ >> i.validationTool;
+}
+
+#include "validateprogress.moc"
diff --git a/kbabel/catalogmanager/validateprogress.h b/kbabel/catalogmanager/validateprogress.h
new file mode 100644
index 00000000..05133889
--- /dev/null
+++ b/kbabel/catalogmanager/validateprogress.h
@@ -0,0 +1,109 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002-203 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef VALIDATEDLG_H
+#define VALIDATEDLG_H
+
+#include <qmap.h>
+
+#include <kdialogbase.h>
+#include <kurl.h>
+
+class CatManListItem;
+class ValidateProgressWidget;
+class KDataToolInfo;
+class KDataTool;
+class KPopupMenu;
+
+struct IgnoreItem
+{
+ KURL fileURL;
+ QStringList msgid;
+ QStringList msgstr;
+ uint index;
+ QString validationTool;
+};
+
+QDataStream & operator<<( QDataStream & stream, const IgnoreItem &ident );
+QDataStream & operator>>( QDataStream & stream, IgnoreItem & ident);
+
+class ValidateProgressDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ ValidateProgressDialog(const QString& ignoreURL, QWidget* parent, const char *name=0);
+ virtual ~ValidateProgressDialog();
+
+ void setIgnoreFuzzy(bool enable) { _ignoreFuzzy = enable; }
+ void setMarkAsFuzzy(bool enable) { _setAsFuzzy = enable; }
+
+public slots:
+ void validate(const KDataToolInfo &tool, const QPtrList<CatManListItem> files);
+
+signals:
+ void errorDoubleClicked(const QString file, const int messageNumber);
+
+private slots:
+ /** implementation of the validation itself */
+ void validate_internal();
+
+ /** call this to stop current validation*/
+ void stop();
+
+ /** If user doubleclicked an item, this slot will be invoked.
+ * It emits errorDoubleClicked signal for corresponding error*/
+ void errorItemDoubleClicked(QListBoxItem * item);
+
+ /** show our context menu */
+ void showContextMenu(QListBoxItem * item, const QPoint & pos);
+
+private:
+ void readIgnores();
+ void writeIgnores();
+
+ ValidateProgressWidget *_mainWidget;
+ QString _ignoreURL;
+ KDataTool* _tool;
+ QString _toolID;
+ QPtrList<CatManListItem> _files;
+ bool _stopped;
+ KPopupMenu* _errorMenu;
+
+ bool _ignoreFuzzy;
+ bool _setAsFuzzy;
+
+ QValueList<IgnoreItem> _ignores;
+ QMap<QString,IgnoreItem> _errors;
+};
+
+#endif // VALIDATEDLG_H
diff --git a/kbabel/catalogmanager/validateprogresswidget.ui b/kbabel/catalogmanager/validateprogresswidget.ui
new file mode 100644
index 00000000..a181806b
--- /dev/null
+++ b/kbabel/catalogmanager/validateprogresswidget.ui
@@ -0,0 +1,129 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>ValidateProgressWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>ValidateProgressWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>448</width>
+ <height>295</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>_currentAction</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>92</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Current:</string>
+ </property>
+ </widget>
+ <widget class="KProgress" row="3" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>_overallProgress</cstring>
+ </property>
+ </widget>
+ <widget class="KSqueezedTextLabel" row="0" column="2">
+ <property name="name">
+ <cstring>_currentTool</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="3" column="0">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Overall:</string>
+ </property>
+ </widget>
+ <widget class="KProgress" row="2" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>_currentFileProgress</cstring>
+ </property>
+ </widget>
+ <widget class="KSqueezedTextLabel" row="1" column="2">
+ <property name="name">
+ <cstring>_currentFile</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>_currentLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Current file:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel3_2</cstring>
+ </property>
+ <property name="text">
+ <string>Validation:</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QListBox">
+ <item>
+ <property name="text">
+ <string>New Item</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>_errorList</cstring>
+ </property>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>ValidateProgressWidget</sender>
+ <signal>setValidationProgressBar(int)</signal>
+ <receiver>_currentFileProgress</receiver>
+ <slot>setValue(int)</slot>
+ </connection>
+</connections>
+<includes>
+ <include location="local" impldecl="in implementation">validateprogresswidget.ui.h</include>
+</includes>
+<signals>
+ <signal>setValidationProgressBar(int)</signal>
+</signals>
+<slots>
+ <slot>setupFileProgressBar( QString text, int maxvalue )</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kprogress.h</includehint>
+ <includehint>ksqueezedtextlabel.h</includehint>
+ <includehint>kprogress.h</includehint>
+ <includehint>ksqueezedtextlabel.h</includehint>
+</includehints>
+</UI>
diff --git a/kbabel/catalogmanager/validateprogresswidget.ui.h b/kbabel/catalogmanager/validateprogresswidget.ui.h
new file mode 100644
index 00000000..88f36d60
--- /dev/null
+++ b/kbabel/catalogmanager/validateprogresswidget.ui.h
@@ -0,0 +1,48 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+void ValidateProgressWidget::setupFileProgressBar( QString text, int maxvalue )
+{
+ _currentFileProgress->setTotalSteps(maxvalue);
+
+ QString t = text[0].upper()+text.mid(1)+":";
+
+ _currentAction->setText(t);
+ _currentAction->repaint();
+}
diff --git a/kbabel/catalogmanager/validationoptions.ui b/kbabel/catalogmanager/validationoptions.ui
new file mode 100644
index 00000000..61079ff3
--- /dev/null
+++ b/kbabel/catalogmanager/validationoptions.ui
@@ -0,0 +1,60 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>ValidationOptions</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>ValidationOptions</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>174</width>
+ <height>70</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>markAsFuzzy</cstring>
+ </property>
+ <property name="text">
+ <string>Mark invalid as &amp;fuzzy</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;&lt;p&gt;&lt;b&gt;Mark invalid as fuzzy&lt;/b&gt;&lt;p&gt;
+&lt;p&gt;If you select this option, all items,
+which identifies the tool as invalid, will be
+marked as fuzzy and the resulting file
+will be saved.&lt;/p&gt;&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>ignoreFuzzy</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Do not validate fuzzy</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;&lt;p&gt;&lt;b&gt;Do not validate fuzzy&lt;/b&gt;&lt;p&gt;
+&lt;p&gt;If you select this option, all items
+marked as fuzzy will not be validated at all.&lt;/p&gt;&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </vbox>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kbabel/common/Makefile.am b/kbabel/common/Makefile.am
new file mode 100644
index 00000000..462cc425
--- /dev/null
+++ b/kbabel/common/Makefile.am
@@ -0,0 +1,67 @@
+## Makefile.am for libkbabelcommon
+
+# this has all of the subdirectories that make will recurse into. if
+# there are none, comment this out
+SUBDIRS = libgettext
+
+pkgincludedir = $(includedir)/kbabel
+
+# this is the program that gets installed. it's name is used for all
+# of the other Makefile.am variables
+lib_LTLIBRARIES = libkbabelcommon.la
+
+# set the include path for X, qt and KDE
+INCLUDES = $(all_includes)
+
+# which sources should be compiled
+libkbabelcommon_la_SOURCES = catalog.cpp catalogitem.cpp editcmd.cpp\
+ msgfmt.cpp catalogsettings.cpp tagextractor.cpp diff.cpp\
+ argextractor.cpp kbmailer.cpp poinfo.cpp\
+ regexpextractor.cpp importplugin.cpp \
+ exportplugin.cpp \
+ kbproject.cpp \
+ kbprojectmanager.cpp \
+ kbprojectsettings.kcfgc \
+ projectsettings.cpp \
+ stringdistance.cpp
+
+libkbabelcommon_la_LIBADD = $(LIB_KIO) libgettext/libgettext.la
+libkbabelcommon_la_LDFLAGS = $(all_libraries) -version-info 5:0:2 -no-undefined
+
+# these are the headers for your project
+noinst_HEADERS = resources.h version.h catalogitem_private.h catalog_private.h kbmailer.h stringdistance.h
+pkginclude_HEADERS = catalog.h catalogitem.h editcmd.h msgfmt.h catalogsettings.h findoptions.h catalogview.h tagextractor.h poinfo.h\
+ regexpextractor.h itempart.h catalogfileplugin.h kbabeldatatool.h kbproject.h kbprojectmanager.h \
+ projectsettings.h
+
+
+# let automoc handle all of the meta source files (moc)
+METASOURCES = AUTO
+
+# KConfigXT project settings
+kde_kcfg_DATA=kbprojectsettings.kcfg
+
+# service type for the filters
+kde_servicetypes_DATA = kbabelfilter.desktop
+EXTRA_DIST = $(kde_servicetypes_DATA)
+
+KDE_OPTIONS = nofinal
+
+version.h: $(srcdir)/../VERSION
+ echo "/* Generated file - DO NOT EDIT */" > version.h
+ echo "#undef VERSION" >> version.h
+ echo "#define VERSION \"`cat $(srcdir)/../VERSION`\"" >> version.h
+
+catalog.lo: version.h
+
+# updating of project settings for default project
+update_DATA = kbabel-projectrename.upd
+updatedir = $(kde_datadir)/kconf_update
+
+api:
+ mkdir -p API && kdoc -d API -u $$PWD/API -p -lkdecore -lqt-mt -ldcop $(pkginclude_HEADERS)
+
+distclean-local:
+ rm -r -f API
+ rm -f version.h
+
diff --git a/kbabel/common/argextractor.cpp b/kbabel/common/argextractor.cpp
new file mode 100644
index 00000000..4146a5a7
--- /dev/null
+++ b/kbabel/common/argextractor.cpp
@@ -0,0 +1,70 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2001 by Matthias Kiefer <matthias.kiefer@gmx.de>
+ 2002 by Stanislav Visnovsky <visnovsky@nenya.ms.mff.cuni.cz>
+
+ based on code of Andrea Rizzi <rizzi@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include "catalogsettings.h"
+#include "argextractor.h"
+
+#include <kdebug.h>
+#include <kstaticdeleter.h>
+#include <qregexp.h>
+
+using namespace KBabel;
+
+ArgExtractor::ArgExtractor(QString string) : RegExpExtractor( string )
+{
+}
+
+QStringList *ArgExtractor::_argList=0;
+KStaticDeleter< QStringList > sdAL;
+
+QStringList *ArgExtractor::regExpList()
+{
+ if(!_argList)
+ {
+ sdAL.setObject( _argList, new QStringList );
+ //Build the default arg list
+ _argList->append("%[ndioxXucsfeEgGp]");
+ _argList->append("%([0-9]+(\\$))?[-+'#0]?[0-9]*(.[0-9]+)?[hlL]?[dioxXucsfeEgGp]");
+ _argList->append("%[0-9]+");
+ }
+
+ return _argList;
+}
+
+void ArgExtractor::setArgExpressions( QStringList* list )
+{
+ sdAL.setObject( _argList, new QStringList );
+ for( QStringList::Iterator it = list->begin() ; it != list->end() ; ++it )
+ _argList->append(*it);
+}
diff --git a/kbabel/common/argextractor.h b/kbabel/common/argextractor.h
new file mode 100644
index 00000000..31b28c8a
--- /dev/null
+++ b/kbabel/common/argextractor.h
@@ -0,0 +1,83 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002 by Stanislav Visnovsky
+
+ based on code of Matthias Kiefer <matthias.kiefer@gmx.de> and
+ Andrea Rizzi <rizzi@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef _ARG_EXTRACTOR_H_
+#define _ARG_EXTRACTOR_H_
+
+#include <qptrlist.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qvaluelist.h>
+#include <qregexp.h>
+
+#include "regexpextractor.h"
+
+namespace KBabel
+{
+
+/**
+ * class to extract arguments from a string
+ * @author Stanislav Visnovsky <visnovsky@kde.org>
+ * @author Andrea Rizzi <rizzi@kde.org>
+ */
+class ArgExtractor : public RegExpExtractor
+{
+
+public:
+ /**
+ * Create an argument extractor for "string"
+ */
+ ArgExtractor(QString string=QString::null);
+
+ /**
+ * Set a new list of tag regular expressions. It also
+ * deletes the old tags.
+ * @param list a list of regular expressions
+ */
+ static void setArgExpressions(QStringList* list);
+
+protected:
+ /**
+ * @return the static list of args
+ */
+ virtual QStringList *regExpList();
+
+private:
+ static QStringList *_argList;
+};
+
+}
+
+
+#endif
diff --git a/kbabel/common/catalog.cpp b/kbabel/common/catalog.cpp
new file mode 100644
index 00000000..ffd939b7
--- /dev/null
+++ b/kbabel/common/catalog.cpp
@@ -0,0 +1,3509 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer <matthias.kiefer@gmx.de>
+ 2001-2005 by Stanislav Visnovsky <visnovsky@kde.org>
+ Copyright (C) 2006 by Nicolas GOUTTE <goutte@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include <qtextstream.h>
+#include <qfile.h>
+#include <qdir.h>
+#include <qfileinfo.h>
+#include <qregexp.h>
+#include <qstring.h>
+#include <qtextcodec.h>
+#include <qdatetime.h>
+
+#include <kconfig.h>
+#include <kdatatool.h>
+#include <kglobal.h>
+#include <klibloader.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kmimetype.h>
+#include <kapplication.h>
+#include <kio/netaccess.h>
+#include <krfcdate.h>
+#include <ktrader.h>
+#include <kurl.h>
+
+#include "kbprojectmanager.h"
+#include "catalog.h"
+#include "catalog_private.h"
+#include "catalogitem.h"
+#include "diff.h"
+#include "findoptions.h"
+#include "catalogview.h"
+#include "editcmd.h"
+#include "kbprojectsettings.h"
+
+#include "resources.h"
+#include "version.h"
+#include "stringdistance.h"
+
+#include <kmessagebox.h>
+using namespace KBabel;
+
+Catalog::Catalog(QObject* parent, const char* name, QString projectFile)
+ : QObject(parent,name)
+{
+ if ( projectFile.isEmpty() )
+ projectFile = KBabel::ProjectManager::defaultProjectName();
+ d = new CatalogPrivate(ProjectManager::open(projectFile));
+ readPreferences();
+}
+
+Catalog::Catalog(const Catalog& c): QObject(c.parent(),c.name()
+)
+{
+ kdFatal() << "Copy constructor of Catalog, please report how to reproduce to the authors" << endl;
+}
+
+Catalog::~Catalog()
+{
+ delete d;
+}
+
+QString Catalog::msgctxt(uint index) const
+{
+ if ( d->_entries.isEmpty() )
+ return QString::null;
+ uint max=d->_entries.count()-1;
+ if(index > max)
+ index=max;
+ return d->_entries[index].msgctxt();
+}
+
+QStringList Catalog::msgid(uint index, const bool noNewlines) const
+{
+ if ( d->_entries.isEmpty() )
+ return QString::null;
+ uint max=d->_entries.count()-1;
+ if(index > max)
+ index=max;
+
+ return d->_entries[index].msgid(noNewlines);
+}
+
+QStringList Catalog::msgstr(uint index, const bool noNewlines) const
+{
+ if ( d->_entries.isEmpty() )
+ return QString::null;
+
+ uint max=d->_entries.count()-1;
+ if(index > max)
+ index=max;
+
+ return d->_entries[index].msgstr(noNewlines);
+}
+
+QString Catalog::comment(uint index) const
+{
+ if ( d->_entries.isEmpty() )
+ return QString::null;
+ uint max=d->_entries.count()-1;
+ if(index > max)
+ index=max;
+ return d->_entries[index].comment();
+}
+
+QString Catalog::context(uint index) const
+{
+ QString c = comment(index);
+
+ QStringList lines = QStringList::split("\n",c);
+
+ QString result;
+ for( QStringList::Iterator it=lines.begin(); it!=lines.end(); ++it)
+ {
+ if( (*it).startsWith( "#:") )
+ {
+ result+=(*it)+"\n";
+ }
+ }
+ return result.stripWhiteSpace();
+}
+
+CatalogItem Catalog::header() const
+{
+ return d->_header;
+}
+
+QString Catalog::lastTranslator() const
+{
+ return headerInfo( d->_header ).lastTranslator;
+}
+
+int Catalog::indexForMsgid(const QString& id) const
+{
+ int i=0;
+ QValueVector<CatalogItem>::ConstIterator it = d->_entries.begin();
+
+ while(it != d->_entries.end() && !((*it).msgid(true).contains(id)))
+ {
+ ++it;
+ i++;
+ }
+
+ if(it == d->_entries.end())
+ i=-1;
+
+ return i;
+}
+
+QStringList Catalog::tagList(uint index)
+{
+ if ( d->_entries.isEmpty() )
+ return QStringList();
+
+ uint max=d->_entries.count()-1;
+ if(index > max)
+ index=max;
+
+ return d->_entries[index].tagList(*(d->_tagExtractor));
+}
+
+
+QStringList Catalog::argList(uint index)
+{
+ if ( d->_entries.isEmpty() )
+ return QStringList();
+
+ uint max=d->_entries.count()-1;
+ if(index > max)
+ index=max;
+
+ return d->_entries[index].argList(*(d->_argExtractor));
+}
+
+
+/*
+bool Catalog::setMsgstr(uint index,QString msgstr)
+{
+ kdWarning() << "Catalog::setMsgstr()" << endl;
+
+ bool untranslatedChanged=false;
+
+ if(_entries[index].isUntranslated() && !msgstr.isEmpty())
+ {
+ _untransIndex.remove(index);
+ untranslatedChanged=true;
+ }
+ else if(msgstr.isEmpty())
+ {
+ QValueList<uint>::Iterator it;
+
+ // insert index in the right place in the list
+ it = _untransIndex.begin();
+ while(it != _untransIndex.end() && index > (*it))
+ {
+ ++it;
+ }
+ _untransIndex.insert(it,index);
+
+ untranslatedChanged=true;
+ }
+
+ _entries[index].setMsgstr(msgstr);
+
+ setModified(true);
+
+ if(untranslatedChanged)
+ emit signalNumberOfUntranslatedChanged(numberOfUntranslated());
+
+ return untranslatedChanged;
+}
+*/
+
+/*
+bool Catalog::setComment(uint index,QString comment)
+{
+ kdWarning() << "Catalog::setComment()" << endl;
+ bool fuzziesChanged=false;
+
+
+ bool wasFuzzy=_entries[index].isFuzzy();
+
+ _entries[index].setComment(comment);
+
+ bool isFuzzy=_entries[index].isFuzzy();
+
+ if(wasFuzzy && !isFuzzy)
+ {
+ _fuzzyIndex.remove(index);
+ fuzziesChanged=true;
+ }
+ else if(isFuzzy)
+ {
+ QValueList<uint>::Iterator it;
+
+ // insert index in the right place in the list
+ it = _fuzzyIndex.begin();
+ while(it != _fuzzyIndex.end() && index > (*it))
+ {
+ ++it;
+ }
+ _fuzzyIndex.insert(it,index);
+
+ fuzziesChanged=true;
+ }
+
+ setModified(true);
+
+ if(fuzziesChanged)
+ emit signalNumberOfFuzziesChanged(numberOfFuzzies());
+
+
+ return fuzziesChanged;
+}
+*/
+
+bool Catalog::setHeader(CatalogItem newHeader)
+{
+ if(newHeader.isValid())
+ {
+ // normalize the values - ensure every key:value pair is only on a single line
+ QString values = newHeader.msgstr().first();
+ values.replace ("\n", "");
+ values.replace ("\\n", "\\n\n");
+
+ kdDebug () << "Normalized header: " << values << endl;
+
+ d->_header=newHeader;
+ d->_header.setMsgstr (values);
+
+ setModified(true);
+
+ emit signalHeaderChanged();
+
+ return true;
+ }
+
+ return false;
+}
+
+KURL Catalog::currentURL() const
+{
+ return d->_url;
+}
+
+void Catalog::setCurrentURL(const KURL& url)
+{
+ d->_url=url;
+}
+
+
+CatalogItem Catalog::updatedHeader(CatalogItem oldHeader, bool usePrefs) const
+{
+ QStringList headerList=oldHeader.msgstrAsList();
+ QStringList commentList=QStringList::split('\n',oldHeader.comment());
+
+ QStringList::Iterator it,ait;
+ QString temp;
+ bool found;
+
+ const IdentitySettings identityOptions = identitySettings();
+ const SaveSettings saveOptions = saveSettings();
+
+ if(!usePrefs || saveOptions.updateLastTranslator)
+ {
+ found=false;
+
+ temp="Last-Translator: "+identityOptions.authorName;
+ if(!identityOptions.authorEmail.isEmpty())
+ {
+ temp+=(" <"+identityOptions.authorEmail+">");
+ }
+ temp+="\\n";
+ for( it = headerList.begin(); it != headerList.end(); ++it )
+ {
+ if((*it).contains(QRegExp("^ *Last-Translator:.*")))
+ {
+ (*it) = temp;
+ found=true;
+ break;
+ }
+ }
+ if(!found)
+ {
+ headerList.append(temp);
+ }
+ }
+ if(!usePrefs || saveOptions.updateRevisionDate)
+ {
+ found=false;
+
+ temp="PO-Revision-Date: "+dateTime()+"\\n";
+
+ for( it = headerList.begin(); it != headerList.end(); ++it )
+ {
+ if((*it).contains(QRegExp("^ *PO-Revision-Date:.*")))
+ {
+ (*it) = temp;
+ found=true;
+ break;
+ }
+ }
+ if(!found)
+ {
+ headerList.append(temp);
+ }
+ }
+ if(!usePrefs || saveOptions.updateProject)
+ {
+ found=false;
+
+ temp="Project-Id-Version: "+saveOptions.projectString+"\\n";
+ temp.replace( "@PACKAGE@", packageName());
+
+ for( it = headerList.begin(); it != headerList.end(); ++it )
+ {
+ if((*it).contains(QRegExp("^ *Project-Id-Version:.*")))
+ {
+ (*it) = temp;
+ found=true;
+ break;
+ }
+ }
+ if(!found)
+ {
+ headerList.append(temp);
+ }
+ }
+ if(!usePrefs || saveOptions.updateLanguageTeam)
+ {
+ found=false;
+
+ temp="Language-Team: "+identityOptions.languageName;
+ if(!identityOptions.mailingList.isEmpty())
+ {
+ temp+=(" <"+identityOptions.mailingList+">");
+ }
+ temp+="\\n";
+ for( it = headerList.begin(); it != headerList.end(); ++it )
+ {
+ if((*it).contains(QRegExp("^ *Language-Team:.*")))
+ {
+ (*it) = temp;
+ found=true;
+ break;
+ }
+ }
+ if(!found)
+ {
+ headerList.append(temp);
+ }
+ }
+ if(!usePrefs || saveOptions.updateCharset)
+ {
+
+ found=false;
+
+ QString encodingStr;
+ if(saveOptions.useOldEncoding && d->fileCodec)
+ {
+ encodingStr = charsetString(d->fileCodec);
+ }
+ else
+ {
+ encodingStr=charsetString(saveOptions.encoding);
+ }
+
+ temp = "Content-Type: text/plain; charset=" + encodingStr + "\\n";
+
+ it = headerList.begin();
+ while( it != headerList.end() )
+ {
+ if( (*it).find( QRegExp( "^ *Content-Type:.*" ) ) != -1 )
+ {
+ if ( found )
+ {
+ // We had already a Content-Type, so we do not need a duplicate
+ it = headerList.remove( it );
+ }
+ else
+ {
+ found=true;
+ QRegExp regexp( "^ *Content-Type:(.*/.*);?\\s*charset=.*$" );
+ QString mimeType;
+ if ( regexp.search( *it ) )
+ {
+ mimeType = regexp.cap( 1 ).stripWhiteSpace();
+ }
+ if ( mimeType.isEmpty() )
+ {
+ mimeType = "text/plain";
+ }
+ temp = "Content-Type: ";
+ temp += mimeType;
+ temp += "; charset=";
+ temp += encodingStr;
+ temp += "\\n";
+ (*it) = temp;
+ }
+ }
+ ++it;
+ }
+ if(!found)
+ {
+ headerList.append(temp);
+ }
+ }
+ if(!usePrefs || saveOptions.updateEncoding)
+ {
+ found=false;
+
+ temp="Content-Transfer-Encoding: 8bit\\n";
+
+ for( it = headerList.begin(); it != headerList.end(); ++it )
+ {
+ if((*it).contains(QRegExp("^ *Content-Transfer-Encoding:.*")))
+ {
+ (*it) = temp;
+ found=true;
+ break;
+ }
+ }
+ if(!found)
+ {
+ headerList.append(temp);
+ }
+ }
+
+ temp="X-Generator: KBabel %1\\n";
+ temp=temp.arg(VERSION);
+ found=false;
+
+ for( it = headerList.begin(); it != headerList.end(); ++it )
+ {
+ if((*it).contains(QRegExp("^ *X-Generator:.*")))
+ {
+ (*it) = temp;
+ found=true;
+ break;
+ }
+ }
+ if(!found)
+ {
+ headerList.append(temp);
+ }
+
+ // ensure MIME-Version header
+ temp="MIME-Version: 1.0\\n";
+ found=false;
+ for( it = headerList.begin(); it != headerList.end(); ++it )
+ {
+ if((*it).contains(QRegExp("^ *MIME-Version:")))
+ {
+ (*it) = temp;
+ found=true;
+ break;
+ }
+ }
+ if( !found )
+ {
+ headerList.append(temp);
+ }
+
+
+ temp="Plural-Forms: %1\\n";
+ temp=temp.arg(identityOptions.gnuPluralFormHeader);
+ found=false;
+
+ // update plural form header
+ if( !identityOptions.gnuPluralFormHeader.isEmpty() )
+ {
+ for( it = headerList.begin(); it != headerList.end(); ++it )
+ {
+ if((*it).contains(QRegExp("^ *Plural-Forms:")))
+ {
+ (*it) = temp;
+ found=true;
+ break;
+ }
+ }
+ if( !found )
+ {
+ headerList.append(temp);
+ }
+ }
+
+ oldHeader.setMsgstr( headerList.join( "\n" ) );
+
+ //comment = description, copyrights
+ if(!usePrefs || (saveOptions.FSFCopyright != ProjectSettingsBase::NoChange))
+ {
+ found=false;
+
+ for( it = commentList.begin(); it != commentList.end(); ++it )
+ {
+ // U+00A9 is the Copyright sign
+ if ( (*it).find( QRegExp("^# *Copyright (\\(C\\)|\\x00a9).*Free Software Foundation, Inc") ) != -1 )
+ {
+ found=true;
+ break;
+ }
+ }
+ if(found)
+ {
+ if ( (*it).find( QRegExp("^# *Copyright (\\(C\\)|\\x00a9) YEAR Free Software Foundation, Inc\\.") ) != -1 )
+ {
+ //template string
+ if( saveOptions.FSFCopyright == ProjectSettingsBase::Remove)
+ (*it).remove(" YEAR Free Software Foundation, Inc");
+ else
+ (*it).replace("YEAR", QDate::currentDate().toString("yyyy"));
+ } else
+ if( saveOptions.FSFCopyright == ProjectSettingsBase::Update )
+ {
+ //update years
+ QString cy = QDate::currentDate().toString("yyyy");
+ if( !(*it).contains( QRegExp(cy)) ) // is the year already included?
+ {
+ int index = (*it).findRev( QRegExp("[\\d]+[\\d\\-, ]*") );
+ if( index == -1 )
+ {
+ KMessageBox::information(0,i18n("Free Software Foundation Copyright does not contain any year. "
+ "It will not be updated."));
+ } else {
+ (*it).insert(index+1, QString(", ")+cy);
+ }
+ }
+ }
+ }
+ }
+
+ if ( ( !usePrefs || saveOptions.updateDescription )
+ && ( !saveOptions.descriptionString.isEmpty() ) )
+ {
+ temp = "# "+saveOptions.descriptionString;
+ temp.replace( "@PACKAGE@", packageName());
+ temp.replace( "@LANGUAGE@", identityOptions.languageName);
+ temp = temp.stripWhiteSpace();
+
+ // The description strings has often buggy variants already in the file, these must be removed
+ QString regexpstr = "^#\\s+" + QRegExp::escape( saveOptions.descriptionString.stripWhiteSpace() ) + "\\s*$";
+ regexpstr.replace( "@PACKAGE@", ".*" );
+ regexpstr.replace( "@LANGUAGE@", ".*" );
+ //kdDebug() << "REGEXPSTR: " << regexpstr << endl;
+ QRegExp regexp ( regexpstr );
+
+ // The buggy variants exist in English too (of a time before KBabel got a translation for the corresponding language)
+ QRegExp regexpUntranslated ( "^#\\s+Translation of .* into .*\\s*$" );
+
+ kdDebug () << "Temp is '" << temp << "'" << endl;
+
+ found=false;
+//not used anyway bool foundTemplate=false;
+
+ it = commentList.begin();
+ while ( it != commentList.end() )
+ {
+ kdDebug () << "testing '" << (*it) << "'" << endl;
+ bool deleteItem = false;
+
+ if ( (*it) == temp )
+ {
+ kdDebug () << "Match " << endl;
+ if ( found )
+ deleteItem = true;
+ else
+ found=true;
+ }
+ else if ( regexp.search( *it ) >= 0 )
+ {
+ // We have a similar (translated) string (from another project or another language (perhaps typos)). Remove it.
+ deleteItem = true;
+ }
+ else if ( regexpUntranslated.search( *it ) >= 0 )
+ {
+ // We have a similar (untranslated) string (from another project or another language (perhaps typos)). Remove it.
+ deleteItem = true;
+ }
+ else if ( (*it) == "# SOME DESCRIPTIVE TITLE." )
+ {
+ // We have the standard title placeholder, remove it
+ deleteItem = true;
+ }
+
+ if ( deleteItem )
+ it = commentList.remove( it );
+ else
+ ++it;
+ }
+ if(!found) commentList.prepend(temp);
+ }
+
+ // kdDebug() << "HEADER COMMENT: " << commentList << endl;
+
+ if ( (!usePrefs || saveOptions.updateTranslatorCopyright)
+ && ( ! identityOptions.authorName.isEmpty() )
+ && ( ! identityOptions.authorEmail.isEmpty() ) ) // An email address can be used as ersatz of a name
+ {
+ QStringList foundAuthors;
+
+ temp = "# ";
+ temp += identityOptions.authorName;
+ if(!identityOptions.authorEmail.isEmpty())
+ {
+ temp+=(" <"+identityOptions.authorEmail+">");
+ }
+ temp+=", "+QDate::currentDate().toString("yyyy")+".";
+
+ // ### TODO: it would be nice if the entry could start with "COPYRIGHT" and have the "(C)" symbol (both not mandatory)
+ QRegExp regexpAuthorYear( "^#.*(<.+@.+>)?,\\s*([\\d]+[\\d\\-, ]*|YEAR)" );
+ QRegExp regexpYearAlone( "^# , \\d{4}.?\\s*$" );
+ it = commentList.begin();
+ while ( it != commentList.end() )
+ {
+ bool deleteItem = false;
+ if ( (*it).find ( "copyright", 0, false ) != -1 )
+ {
+ // We have a line with a copyright. It should not be moved.
+ }
+ else if ( (*it).find ( regexpYearAlone ) != -1 )
+ {
+ // We have found a year number that is preceeded by a comma.
+ // That is typical of KBabel 1.10 (and earlier?) when there is neither an author name nor an email
+ // Remove the entry
+ deleteItem = true;
+ }
+ else if ( (*it) == "# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR." )
+ {
+ // Typical placeholder, remove it.
+ deleteItem = true;
+ }
+ else if ( (*it).find ( regexpAuthorYear ) != -1 ) // email address followed by year
+ {
+ if ( foundAuthors.find( (*it) ) == foundAuthors.end() )
+ {
+ // The author line is new (and not a duplicate), so add it to the author line list
+ foundAuthors.append( (*it) );
+ }
+ // Delete also non-duplicated entry, as now all what is needed will be processed in foundAuthors
+ deleteItem = true;
+ }
+
+ if ( deleteItem )
+ it = commentList.remove( it );
+ else
+ ++it;
+ }
+
+ if( !foundAuthors.isEmpty() )
+ {
+ found = false;
+ bool foundAuthor = false;
+
+ const QString cy = QDate::currentDate().toString("yyyy");
+
+ ait = foundAuthors.end();
+ for( it = foundAuthors.begin() ; it!=foundAuthors.end(); ++it )
+ {
+ if ( (*it).find( QRegExp(
+ QRegExp::escape( identityOptions.authorName )+".*"
+ + QRegExp::escape( identityOptions.authorEmail ) ) ) != -1 )
+ {
+ foundAuthor = true;
+ if( (*it).find( cy ) != -1 )
+ found = true;
+ else
+ ait = it;
+ }
+ }
+ if( !found )
+ {
+ if ( !foundAuthor )
+ foundAuthors.append(temp);
+ else if ( ait != foundAuthors.end() )
+ {
+ //update years
+ const int index = (*ait).findRev( QRegExp("[\\d]+[\\d\\-, ]*") );
+ if ( index == -1 )
+ (*ait)+=", "+cy;
+ else
+ (*ait).insert(index+1, QString(", ")+cy);
+ }
+ else
+ kdDebug() << "INTERNAL ERROR: author found but iterator dangling!" << endl;
+ }
+
+ }
+ else
+ foundAuthors.append(temp);
+ it=commentList.end();
+ do
+ --it;
+ while( ( it != commentList.begin() ) && ( (*it).find( QRegExp( "^#(\\s*$|[:,\\.])" ) ) == -1 ) );
+ ++it;
+ for( ait = foundAuthors.begin() ; ait != foundAuthors.end() ; ++ait )
+ {
+ QString s = (*ait);
+
+ // ensure dot at the end of copyright
+ if( !s.endsWith(".") ) s += ".";
+ commentList.insert(it, s);
+ }
+ }
+
+ oldHeader.setComment( commentList.join( "\n" ) );
+
+ return oldHeader;
+}
+
+void Catalog::setFuzzy(uint index, bool on)
+{
+ if ( d->_entries.isEmpty() )
+ return;
+
+ uint max=d->_entries.count()-1;
+ if(index > max)
+ return;
+
+ if(d->_entries[index].isFuzzy() != on)
+ {
+ applyBeginCommand( index, Comment, 0 );
+
+ QPtrList<EditCommand> editList;
+ if(on)
+ {
+ editList=d->_entries[index].addFuzzy(false);
+ }
+ else
+ {
+ editList=d->_entries[index].removeFuzzy(false);
+ d->_fuzzyIndex.remove(index);
+ }
+
+ for ( EditCommand* cmd=editList.first(); cmd != 0; cmd=editList.next() )
+ {
+ cmd->setIndex(index);
+ applyEditCommand(cmd,0);
+ }
+
+ setModified(true);
+
+ applyEndCommand( index, Comment, 0 );
+
+ emit signalNumberOfFuzziesChanged(numberOfFuzzies());
+ }
+
+}
+
+void Catalog::removeFuzzyStatus(uint index)
+{
+ setFuzzy(index,false);
+}
+
+
+void Catalog::setModified(bool flag)
+{
+ bool old=d->_modified;
+ d->_modified=flag;
+
+ if(old!=d->_modified)
+ emit signalModified(flag);
+}
+
+
+QString Catalog::packageName() const
+{
+ if( !d->_packageName.isNull() ) return d->_packageName;
+
+ QString package=d->_url.fileName();
+
+ int index=package.find(QRegExp("(\\."+identitySettings().languageCode+")?\\.pot?$"));
+
+ if(index>0)
+ package=package.left(index);
+
+ return package;
+}
+
+void Catalog::setPackage(const QString& package )
+{
+ const int pos = package.findRev( '/' );
+ if( pos < 0 )
+ {
+ d->_packageDir = QString();
+ d->_packageName = package;
+ }
+ else
+ {
+ d->_packageDir = package.left( pos + 1 ); // We want the / included
+ d->_packageName = package.mid( pos + 1 ); // We do not want /
+ }
+ kdDebug() << k_funcinfo << " " << package << " => " << d->_packageDir << " + " << d->_packageName << endl;
+}
+
+QString Catalog::packageDir() const
+{
+ QString result;
+ if( !d->_packageDir.isNull() ) result=d->_packageDir;
+ else result=d->_url.directory(false);
+
+ return result;
+}
+
+QString Catalog::encoding() const
+{
+ SaveSettings options = saveSettings();
+
+ QString encodingStr;
+ if(options.useOldEncoding && d->fileCodec)
+ {
+ encodingStr = charsetString(d->fileCodec);
+ }
+ else
+ {
+ encodingStr= charsetString(options.encoding);
+ }
+
+ return encodingStr;
+}
+
+ConversionStatus Catalog::openURL(const KURL& url, const QString& package)
+{
+ QString target;
+ ConversionStatus error = OK;
+
+ if(KIO::NetAccess::download(url, target, NULL))
+ {
+ CatalogImportPlugin* filter=0;
+
+ // gimme plugin for this MIME type
+ KMimeType::Ptr mime = KMimeType::findByURL( url, 0, true );
+ kdDebug() << "Found mimetype: " << mime->name() << endl;
+ KTrader::OfferList offers = KTrader::self()->query("KBabelFilter", "('"+mime->name()+"' in [X-KDE-Import])");
+ KService::Ptr ptr = offers.first();
+
+ // we have no offer for this MIME type
+ if( !ptr )
+ {
+ kdDebug(KBABEL) << "No plugin for this type, will try PO" << endl;
+ offers = KTrader::self()->query("KBabelFilter", "('application/x-gettext' in [X-KDE-Import])");
+ ptr = offers.first();
+ if( !ptr )
+ {
+ kdDebug(KBABEL) << "No plugin for PO files, giving up" << endl;
+ KIO::NetAccess::removeTempFile(target);
+ return NO_PLUGIN;
+ }
+ }
+
+ // try to load the library, if unsuccesfull, we have an installation problem
+ KLibFactory *factory = KLibLoader::self()->factory( ptr->library().local8Bit() );
+ if (!factory)
+ {
+ kdDebug(KBABEL) << "No factory" << endl;
+ KIO::NetAccess::removeTempFile(target);
+ return OS_ERROR;
+ }
+
+ // create the filter
+ filter = static_cast<CatalogImportPlugin*>(factory->create(0, 0));
+
+ // provide progress bar indication
+ connect( filter, SIGNAL( signalResetProgressBar(QString,int) ),
+ this, SIGNAL( signalResetProgressBar(QString,int) ));
+ connect( filter, SIGNAL( signalProgress(int) ),
+ this, SIGNAL( signalProgress(int) ));
+ connect( filter, SIGNAL( signalClearProgressBar() ),
+ this, SIGNAL( signalClearProgressBar() ));
+
+ connect( this, SIGNAL( signalStopActivity() ),
+ filter, SLOT( stop() ));
+
+ // load in the file (target is always local)
+ d->_active = true;
+ kdDebug(KBABEL) << "openURL active" << endl;
+ error = filter->open(target,mime->name(),this);
+ // we should be not freed yet
+ d->_active = false;
+ kdDebug(KBABEL) << "openURL not active" << endl;
+ if( error == STOPPED )
+ {
+ delete filter;
+ return STOPPED;
+ }
+
+ if( error == OK || error == RECOVERED_PARSE_ERROR || error == RECOVERED_HEADER_ERROR )
+ {
+ const uint entries = numberOfEntries();
+
+ if ( !entries )
+ {
+ // KBabel cannot work correctly with not any entry
+ kdWarning() << k_funcinfo << " No entries! Assuming parse error!" << endl;
+ delete filter;
+ return NO_ENTRY_ERROR;
+ }
+
+ //kdDebug( KBABEL ) << k_funcinfo << " Success (full or partial) " << entries << endl;
+ setModified(false);
+ d->_url=url;
+
+ if( package.isEmpty() )
+ {
+ d->_packageName=QString::null;
+ d->_packageDir=QString::null;
+ }
+ else setPackage(package);
+
+ emit signalFileOpened(d->_readOnly);
+ emit signalNumberOfFuzziesChanged(numberOfFuzzies());
+ emit signalNumberOfUntranslatedChanged(numberOfUntranslated());
+ emit signalTotalNumberChanged( entries );
+ }
+
+ delete filter;
+
+ return error;
+ }
+ else
+ {
+ return OS_ERROR;
+ }
+}
+
+ConversionStatus Catalog::openURL(const KURL& openUrl, const KURL& saveURL, const QString& package)
+{
+ QString target;
+ ConversionStatus error = OK;
+
+ if(KIO::NetAccess::download(openUrl, target, NULL))
+ {
+ CatalogImportPlugin* filter=0;
+
+ // gimme plugin for this MIME type
+ KMimeType::Ptr mime = KMimeType::findByURL( openUrl, 0, true );
+ KTrader::OfferList offers = KTrader::self()->query("KBabelFilter", "('"+mime->name()+"' in [X-KDE-Import])");
+ KService::Ptr ptr = offers.first();
+
+ // we have no offer for this MIME type
+ if( !ptr )
+ {
+ kdDebug(KBABEL) << "No plugin for this type" << endl;
+ KIO::NetAccess::removeTempFile(target);
+ return NO_PLUGIN;
+ }
+
+ // try to load the library, if unsuccesfull, we have an installation problem
+ KLibFactory *factory = KLibLoader::self()->factory( ptr->library().local8Bit() );
+ if (!factory)
+ {
+ kdDebug(KBABEL) << "No factory" << endl;
+ KIO::NetAccess::removeTempFile(target);
+ return OS_ERROR;
+ }
+
+ // create the filter
+ filter = static_cast<CatalogImportPlugin*>(factory->create(0, 0));
+
+ // provide progress bar indication
+ connect( filter, SIGNAL( signalResetProgressBar(QString,int) ),
+ this, SIGNAL( signalResetProgressBar(QString,int) ));
+ connect( filter, SIGNAL( signalProgress(int) ),
+ this, SIGNAL( signalProgress(int) ));
+ connect( filter, SIGNAL( signalClearProgressBar() ),
+ this, SIGNAL( signalClearProgressBar() ));
+
+ connect( this, SIGNAL( signalStopActivity() ),
+ filter, SLOT( stop() ));
+
+ // load in the file (target is always local)
+ d->_active = true;
+ kdDebug(KBABEL) << "openURL - template active" << endl;
+ error = filter->open(target,mime->name(),this);
+ // we should be not freed yet
+ kdDebug(KBABEL) << "openURL - template not active" << endl;
+ d->_active = false;
+ if( error == STOPPED )
+ {
+ delete filter;
+ KIO::NetAccess::removeTempFile(target);
+ return STOPPED;
+ }
+
+ // Templates should not have recoverable errors (or they are bad templates)
+ if( error == OK )
+ {
+ const uint entries = numberOfEntries();
+
+ if ( !entries )
+ {
+ // KBabel cannot work correctly with not any entry
+ kdWarning() << k_funcinfo << " No entries! Assuming parse error!" << endl;
+ delete filter;
+ KIO::NetAccess::removeTempFile(target);
+ return NO_ENTRY_ERROR;
+ }
+
+ setModified(false);
+ d->_url = saveURL;
+ if( package.isEmpty() )
+ {
+ d->_packageName=QString::null;
+ d->_packageDir=QString::null;
+ }
+ else setPackage(package);
+
+ emit signalFileOpened(d->_readOnly);
+ emit signalNumberOfFuzziesChanged(numberOfFuzzies());
+ emit signalNumberOfUntranslatedChanged(numberOfUntranslated());
+ emit signalTotalNumberChanged( entries );
+ }
+
+ delete filter;
+
+ // and remove the temp file
+ KIO::NetAccess::removeTempFile(target);
+
+ return error;
+ }
+ else
+ {
+ return OS_ERROR;
+ }
+}
+
+Msgfmt::Status Catalog::checkSyntax(QString& output, bool clearErrors)
+{
+ if( !d->_mimeTypes.contains( "application/x-gettext" ) )
+ return Msgfmt::Unsupported;
+
+ QString filename;
+ bool tempFileUsed=false;
+
+ if(d->_url.isLocalFile() && !isModified())
+ {
+ filename=d->_url.path(0);
+ }
+ else
+ {
+ tempFileUsed=true;
+ filename=saveTempFile();
+ }
+
+ Msgfmt msgfmt;
+ Msgfmt::Status result = msgfmt.checkSyntax( filename , output, pluralFormType() != KDESpecific );
+
+ if( clearErrors) clearErrorList();
+
+ if( result==Msgfmt::SyntaxError )
+ {
+ int currentIndex=-1;
+ int currentLine=0;
+
+ if( !d->_header.msgstr().isEmpty() )
+ currentLine=d->_header.totalLines()+1;
+
+ // ### KDE4: return "lines" not "output"
+ const QStringList lines = QStringList::split("\n",output);
+ for ( QStringList::const_iterator it = lines.constBegin(); it != lines.constEnd(); ++it )
+ {
+ if( (*it).find(QRegExp("^.+:\\d+:")) >= 0 )
+ {
+ const int begin=(*it).find(":",0)+1;
+ const int end=(*it).find(":",begin);
+
+ const QString line=(*it).mid(begin,end-begin);
+
+ while( line.toInt() > currentLine )
+ {
+ currentIndex++;
+ currentLine += ( d->_entries[currentIndex].totalLines() + 1 );
+ }
+
+ if( currentIndex == -1 )
+ {
+ // header error
+ result = Msgfmt::HeaderError;
+ continue;
+ }
+
+ if( !d->_errorIndex.contains(currentIndex) )
+ {
+ d->_errorIndex.append(currentIndex);
+ d->_entries[currentIndex].setSyntaxError(true);
+ }
+ }
+ }
+ }
+
+ if(tempFileUsed)
+ QFile::remove(filename);
+
+ return result;
+}
+
+void Catalog::clearErrorList()
+{
+ QValueList<uint>::Iterator it;
+ for(it = d->_errorIndex.begin(); it != d->_errorIndex.end(); ++it)
+ {
+ d->_entries[(*it)].setSyntaxError(false);
+ d->_entries[(*it)].clearErrors();
+ }
+
+ d->_errorIndex.clear();
+}
+
+void Catalog::removeFromErrorList(uint index)
+{
+ if(d->_errorIndex.contains(index))
+ {
+ d->_errorIndex.remove(index);
+ d->_entries[index].setSyntaxError(false);
+ d->_entries[index].clearErrors();
+ }
+}
+
+QStringList Catalog::itemStatus(uint index, bool recheck, QPtrList<KDataTool> whatToCheck)
+{
+ if ( d->_entries.isEmpty() )
+ return QStringList();
+
+ uint max=d->_entries.count()-1;
+ if(index > max)
+ index=max;
+
+ CatalogItem& item = d->_entries[index];
+
+ if(recheck)
+ {
+ for( KDataTool* t = whatToCheck.first(); t ; t=whatToCheck.next() )
+ {
+ t->run("validate", (void*)(&item), "CatalogItem", "application/x-kbabel-catalogitem" );
+ }
+ }
+
+ return item.errors();
+}
+
+QStringList Catalog::itemStatus(uint index)
+{
+ if ( d->_entries.isEmpty() )
+ return QStringList();
+
+ uint max=d->_entries.count()-1;
+ if(index > max)
+ index=max;
+
+ CatalogItem& item = d->_entries[index];
+
+ return item.errors();
+}
+
+bool Catalog::checkUsingTool(KDataTool* tool, bool clearErrors)
+{
+ if(clearErrors)
+ clearErrorList();
+
+ kdDebug(KBABEL) << "checkUsingTool active" << endl;
+ d->_active=true;
+ d->_stop=false;
+ connect( this, SIGNAL( signalStopActivity() ), this, SLOT( stopInternal() ));
+
+ int index = 0;
+ bool hasErrors=false;
+
+ emit signalResetProgressBar(i18n("validating file"),100);
+
+ for ( QValueVector<CatalogItem>::Iterator it = d->_entries.begin();
+ it != d->_entries.end(); ++it, index++ )
+ {
+ if( !tool->run( "validate", (void*)(&(*it)), "CatalogItem", "application/x-kbabel-catalogitem" ))
+ {
+ if( !d->_errorIndex.contains(index) )
+ {
+ d->_errorIndex.append(index);
+ hasErrors=true;
+ }
+ }
+ if( d->_stop ) break;
+ emit signalProgress((index*100)/d->_entries.count());
+ }
+
+ if( hasErrors && !clearErrors ) qHeapSort(d->_errorIndex);
+
+ kdDebug(KBABEL) << "checkUsingTool not active" << endl;
+ d->_active=false;
+ d->_stop=false;
+ disconnect( this, SIGNAL( signalStopActivity() ), this, SLOT( stopInternal() ));
+
+ emit signalClearProgressBar();
+
+ return !hasErrors;
+}
+
+void Catalog::modifyUsingTool(KDataTool* tool, const QString& command)
+{
+ kdDebug(KBABEL) << "modifyUsingTool active" << endl;
+ d->_active=true;
+ d->_stop=false;
+ connect( this, SIGNAL( signalStopActivity() ), this, SLOT( stopInternal() ));
+
+ int index = 0;
+ bool modified = false;
+
+ emit signalResetProgressBar(i18n("applying tool"),100);
+
+ for ( QValueVector<CatalogItem>::Iterator it = d->_entries.begin();
+ it != d->_entries.end(); ++it, index++ )
+ {
+ CatalogItem dummyItem( *it );
+
+ tool->run( command, (void*)(&dummyItem), "CatalogItem", "application/x-kbabel-catalogitem" );
+
+ if( (*it).msgstr() != dummyItem.msgstr() || (*it).comment() != dummyItem.comment() )
+ {
+ if( !modified )
+ {
+ applyBeginCommand(0,Msgstr,0);
+ modified = true;
+ }
+
+ if( (*it).msgstr() != dummyItem.msgstr() )
+ {
+ uint in = 0; // number of current lural form
+ // go over all plural forms and test, which changed
+ for ( QStringList::Iterator itorig = (*it).msgstr().begin()
+ , itchanged = dummyItem.msgstr().begin()
+ ; itorig != (*it).msgstr().end()
+ ; ++itorig, ++itchanged) {
+ if( (*itorig) != (*itchanged) )
+ {
+ EditCommand* cmd = new DelTextCmd(0,(*itorig),index);
+ cmd->setPart(Msgstr);
+ applyEditCommand(cmd,0);
+ cmd = new InsTextCmd(0,(*itchanged),index);
+ cmd->setPart(Msgstr);
+ applyEditCommand(cmd,0);
+ }
+ in++;
+ }
+ }
+
+ if( (*it).comment() != dummyItem.comment() )
+ {
+ EditCommand* cmd = new DelTextCmd(0,(*it).comment(),0);
+ cmd->setPart(Comment);
+ cmd->setIndex(index);
+ applyEditCommand(cmd,0);
+ cmd = new InsTextCmd(0,dummyItem.comment(),0);
+ cmd->setPart(Comment);
+ cmd->setIndex(index);
+ applyEditCommand(cmd,0);
+ kdDebug(KBABEL) << "DummyItem comment is " << dummyItem.comment() << endl;
+ }
+ }
+
+ if( d->_stop ) break;
+ emit signalProgress((index*100)/d->_entries.count());
+ }
+
+ if( modified ) applyEndCommand(0, Msgstr, 0);
+
+ kdDebug(KBABEL) << "modifyUsingTool not active" << endl;
+ d->_active=false;
+ d->_stop=false;
+ disconnect( this, SIGNAL( signalStopActivity() ), this, SLOT( stopInternal() ));
+
+ emit signalClearProgressBar();
+}
+
+void Catalog::clear()
+{
+ d->_errorIndex.clear();
+ d->_entries.clear();
+ d->_url=KURL();
+ d->_obsoleteEntries.clear();
+
+ if(d->_undoList.count() > 0)
+ emit signalUndoAvailable(false);
+ if(d->_redoList.count() > 0)
+ emit signalRedoAvailable(false);
+
+ d->_undoList.clear();
+ d->_redoList.clear();
+
+ d->msgidDiffList.clear();
+ d->msgstr2MsgidDiffList.clear();
+ d->diffCache.clear();
+}
+
+
+uint Catalog::numberOfEntries() const
+{
+ return d->_entries.count();
+}
+
+uint Catalog::numberOfFuzzies() const
+{
+ return d->_fuzzyIndex.count();
+}
+
+uint Catalog::numberOfUntranslated() const
+{
+ return d->_untransIndex.count();
+}
+
+
+bool Catalog::hasFuzzyInFront(uint index) const
+{
+ if(findPrevInList(d->_fuzzyIndex,index)>=0)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+bool Catalog::hasFuzzyAfterwards(uint index) const
+{
+ if(findNextInList(d->_fuzzyIndex,index)>=0)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+bool Catalog::hasUntranslatedInFront(uint index) const
+{
+ if(findPrevInList(d->_untransIndex,index)>=0)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+bool Catalog::hasUntranslatedAfterwards(uint index) const
+{
+ if(findNextInList(d->_untransIndex,index)>=0)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+bool Catalog::hasErrorInFront(uint index) const
+{
+ if(findPrevInList(d->_errorIndex,index)>=0)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+bool Catalog::hasErrorAfterwards(uint index) const
+{
+ if(findNextInList(d->_errorIndex,index)>=0)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+bool Catalog::isFuzzy(uint index) const
+{
+ if ( d->_entries.isEmpty() )
+ return false;
+
+ if(index > numberOfEntries())
+ return false;
+
+ return d->_entries[index].isFuzzy();
+}
+
+
+bool Catalog::isUntranslated(uint index) const
+{
+ if ( d->_entries.isEmpty() )
+ return false;
+
+ if(index > numberOfEntries())
+ return false;
+
+ return d->_entries[index].isUntranslated();
+}
+
+bool Catalog::hasError(uint index, DocPosition& pos) const
+{
+ if( d->_errorIndex.contains(index) )
+ {
+ pos.item=index;
+ pos.form=0;
+ return true;
+ }
+ return false;
+}
+
+PluralFormType Catalog::pluralForm(uint index) const
+{
+ if ( d->_entries.isEmpty() )
+ return NoPluralForm;
+
+ if(index > numberOfEntries())
+ return NoPluralForm;
+
+ return static_cast<PluralFormType>(d->_entries[index].pluralForm());
+}
+
+PluralFormType Catalog::pluralFormType() const
+{
+ if ( d->_entries.isEmpty() )
+ return NoPluralForm;
+
+ for( uint i = 0 ; i < numberOfEntries(); i++)
+ {
+ if( d->_entries[i].pluralForm() != NoPluralForm )
+ return d->_entries[i].pluralForm();
+ }
+
+ return NoPluralForm;
+}
+
+int Catalog::nextFuzzy(uint startIndex, DocPosition& pos) const
+{
+ pos.item=findNextInList(d->_fuzzyIndex,startIndex);
+ pos.form=0;
+ return pos.item;
+}
+
+int Catalog::prevFuzzy(uint startIndex, DocPosition& pos) const
+{
+ pos.item=findPrevInList(d->_fuzzyIndex,startIndex);
+ pos.form=0;
+ return pos.item;
+}
+
+int Catalog::nextUntranslated(uint startIndex, DocPosition& pos) const
+{
+ pos.item=findNextInList(d->_untransIndex,startIndex);
+ pos.form=0;
+ return pos.item;
+}
+
+int Catalog::prevUntranslated(uint startIndex, DocPosition& pos) const
+{
+ pos.item=findPrevInList(d->_untransIndex,startIndex);
+ pos.form=0;
+ return pos.item;
+}
+
+
+int Catalog::nextError(uint startIndex, DocPosition& pos) const
+{
+ pos.item=findNextInList(d->_errorIndex,startIndex);
+ pos.form=0;
+ return pos.item;
+}
+
+int Catalog::prevError(uint startIndex, DocPosition& pos) const
+{
+ pos.item=findPrevInList(d->_errorIndex,startIndex);
+ pos.form=0;
+ return pos.item;
+}
+
+
+void Catalog::registerView(CatalogView* view)
+{
+ if(d->_views.containsRef(view)==0)
+ {
+ d->_views.append(view);
+ }
+}
+
+
+void Catalog::removeView(CatalogView* view)
+{
+ d->_views.removeRef(view);
+}
+
+
+void Catalog::updateViews(EditCommand* cmd,CatalogView* view2exclude)
+{
+ CatalogView* view;
+ for ( view=d->_views.first(); view != 0; view=d->_views.next())
+ {
+ if(view!=view2exclude)
+ {
+ view->update(cmd);
+ }
+ }
+}
+
+
+
+bool Catalog::hasView() const
+{
+ if(d->_views.count()==0)
+ return false;
+
+ return true;
+}
+
+bool Catalog::isLastView() const
+{
+ if(d->_views.count()<=1)
+ return true;
+
+ return false;
+}
+
+
+void Catalog::useProject(Project::Ptr project)
+{
+ d->_project->config()->sync();
+ d->_project = project;
+ readPreferences();
+ emit signalSettingsChanged(saveSettings());
+ emit signalSettingsChanged(identitySettings());
+ emit signalSettingsChanged(miscSettings());
+ emit signalSettingsChanged(tagSettings());
+}
+
+Project::Ptr Catalog::project() const
+{
+ return d->_project;
+}
+
+void Catalog::readPreferences()
+{
+ getNumberOfPluralForms();
+
+ d->_project->config()->setGroup("Tags");
+ d->_tagSettings.tagExpressions=d->_project->config()->readListEntry("TagExpressions");
+ if( d->_tagSettings.tagExpressions.empty() ) d->_tagSettings.tagExpressions = Defaults::Tag::tagExpressions();
+ d->_tagExtractor->setRegExpList(d->_tagSettings.tagExpressions) ;
+
+ d->_tagSettings.argExpressions=d->_project->config()->readListEntry("ArgExpressions");
+ if( d->_tagSettings.argExpressions.empty() ) d->_tagSettings.argExpressions = Defaults::Tag::argExpressions();
+ d->_argExtractor->setRegExpList(d->_tagSettings.argExpressions) ;
+}
+
+void Catalog::savePreferences()
+{
+ d->_project->config()->setGroup("Tags");
+
+ d->_project->config()->writeEntry( "TagExpressions", d->_tagSettings.tagExpressions );
+ d->_project->config()->writeEntry( "ArgExpressions", d->_tagSettings.argExpressions );
+
+ d->_project->config()->sync();
+}
+
+IdentitySettings Catalog::identitySettings() const
+{
+ return d->_project->identitySettings();
+}
+
+SaveSettings Catalog::saveSettings() const
+{
+ return d->_project->saveSettings();
+
+}
+
+MiscSettings Catalog::miscSettings() const
+{
+ return d->_project->miscSettings();
+
+}
+
+TagSettings Catalog::tagSettings() const
+{
+ return d->_tagSettings;
+
+}
+
+bool Catalog::isGeneratedFromDocbook() const
+{
+ return d->_generatedFromDocbook;
+}
+
+QString Catalog::package() const
+{
+ return packageDir()+packageName();
+}
+
+bool Catalog::isReadOnly() const
+{
+ return d->_readOnly;
+}
+
+void Catalog::setSettings(SaveSettings settings)
+{
+ d->_project->setSettings(settings);
+}
+
+void Catalog::setSettings(IdentitySettings settings)
+{
+ IdentitySettings oldsettings = d->_project->identitySettings();
+
+ QString oldLanguageCode = oldsettings.languageCode;
+ int oldForms = oldsettings.numberOfPluralForms;
+
+
+ d->_project->setSettings(settings);
+
+ if(oldLanguageCode != settings.languageCode)
+ {
+ getNumberOfPluralForms();
+ }
+
+ if(oldForms != settings.numberOfPluralForms)
+ {
+ getNumberOfPluralForms();
+ }
+
+ emit signalSettingsChanged(settings);
+}
+
+void Catalog::setSettings(MiscSettings settings)
+{
+ d->_project->setSettings(settings);
+ emit signalSettingsChanged(settings);
+}
+
+void Catalog::setSettings(TagSettings settings)
+{
+ d->_tagSettings=settings;
+
+ emit signalSettingsChanged(settings);
+}
+
+void Catalog::generateIndexLists()
+{
+ d->_fuzzyIndex.clear();
+ d->_untransIndex.clear();
+ clearErrorList();
+
+ uint counter=0;
+ for ( QValueVector<CatalogItem>::Iterator it = d->_entries.begin(); it != d->_entries.end(); ++it )
+ {
+ if((*it).isUntranslated())
+ {
+ d->_untransIndex.append(counter);
+ }
+ else if((*it).isFuzzy())
+ {
+ d->_fuzzyIndex.append(counter);
+ }
+
+ counter++;
+ }
+
+}
+
+int Catalog::findNextInList(const QValueList<uint>& list,uint index) const
+{
+ QValueList<uint>::ConstIterator it;
+
+ int nextIndex=-1;
+
+ // find index in List
+ it=list.find(index);
+
+ // if the given index is found in the list and not the last entry
+ // in the list, return the next listentry
+ if(it!=list.end() && it!=list.fromLast())
+ {
+ ++it;
+ return (*it);
+ }
+
+ // if the index is not in the list, search the index in the list, that
+ // is the nearest to the given index
+ for( it = list.begin(); it != list.end(); ++it )
+ {
+ if((*it) > index)
+ {
+ nextIndex=(*it);
+ break;
+ }
+ }
+
+
+ return nextIndex;
+}
+
+int Catalog::findPrevInList(const QValueList<uint>& list,uint index) const
+{
+ QValueList<uint>::ConstIterator it;
+
+ int prevIndex=-1;
+
+ it=list.find(index);
+
+ // if the given index is found in the list and not the last entry
+ // in the list, return the next listentry
+ if(it!=list.end() && it!=list.begin())
+ {
+ --it;
+ return (*it);
+ }
+
+
+ // if the index is not in the list, search the index in the list, that
+ // is the nearest to the given index
+ for( it = list.fromLast(); it != list.end(); --it )
+ {
+ if((*it) < index)
+ {
+ prevIndex=(*it);
+ break;
+ }
+
+ if ( it == list.constBegin() )
+ {
+ // Decremeniting the iterator at the begin is undefined, so break the loop
+ break;
+ }
+ }
+
+
+ return prevIndex;
+}
+
+
+QString Catalog::dateTime() const
+{
+ const QDateTime dt = QDateTime::currentDateTime();
+ QString dateTimeString;
+
+ const SaveSettings options = d->_project->saveSettings();
+
+ switch(options.dateFormat)
+ {
+ case Qt::LocalDate:
+ {
+ dateTimeString = KGlobal::locale()->formatDateTime( dt );
+ break;
+ }
+ case Qt::ISODate:
+ {
+ dateTimeString = dt.toString("yyyy-MM-dd hh:mm");
+ QTime t;
+ const int offset = KRFCDate::localUTCOffset();
+ const int correction = offset < 0 ? -60 : 60 ;
+ t = t.addSecs( offset * correction );
+ dateTimeString += ( offset < 0 ? "-" : "+" );
+ dateTimeString += t.toString("hhmm");
+ break;
+ }
+ case Qt::TextDate:
+ {
+ dateTimeString = options.customDateFormat;
+
+ const QDate date = dt.date();
+ const QTime time = dt.time();
+
+ // the year
+ dateTimeString.replace( "%Y", QString::number( date.year() ) );
+ dateTimeString.replace( "%y", QString::number( date.year() ).right(2) );
+
+ // the month
+ if(date.month()<10)
+ {
+ dateTimeString.replace( "%m", "0"+QString::number( date.month() ) );
+ }
+ else
+ {
+ dateTimeString.replace( "%m", QString::number( date.month() ) );
+ }
+
+ dateTimeString.replace( "%f", QString::number( date.month() ) );
+
+ dateTimeString.replace( "%b", date.longMonthName(date.month()) );
+ dateTimeString.replace( "%h", date.longMonthName(date.month()) );
+
+ // the day
+ dateTimeString.replace( "%j", QString::number( date.dayOfYear() ) );
+ dateTimeString.replace( "%e", QString::number( date.day() ) );
+ if(date.day() < 10)
+ {
+ dateTimeString.replace( "%d", "0"+QString::number( date.day() ) );
+ }
+ else
+ {
+ dateTimeString.replace( "%d", QString::number( date.day() ) );
+ }
+
+ dateTimeString.replace( "%a", date.longDayName( date.dayOfWeek() ) );
+
+
+ // hour
+ dateTimeString.replace( "%k", QString::number( time.hour() ) );
+
+ if(time.hour() < 10)
+ {
+ dateTimeString.replace( "%H", "0"+QString::number( time.hour() ) );
+ }
+ else
+ {
+ dateTimeString.replace( "%H", QString::number( time.hour() ) );
+ }
+
+ QString zone; // AM or PM
+ int hour = time.hour();
+ if( hour > 12 )
+ {
+ zone="PM";
+ hour -= 12;
+ }
+ else
+ {
+ zone="AM";
+ }
+
+ dateTimeString.replace( "%I", QString::number( hour ) );
+
+ if(hour < 10)
+ {
+ dateTimeString.replace( "%i", "0"+QString::number( hour ) );
+ }
+ else
+ {
+ dateTimeString.replace( "%i", QString::number( hour ) );
+ }
+
+ dateTimeString.replace( "%p", zone );
+
+ // minutes
+ if(time.minute() < 10)
+ {
+ dateTimeString.replace( "%M", "0"+QString::number( time.minute() ) );
+ }
+ else
+ {
+ dateTimeString.replace( "%M", QString::number( time.minute() ) );
+ }
+
+ // seconds
+ if(time.second() < 10)
+ {
+ dateTimeString.replace( "%S", "0"+QString::number( time.second() ) );
+ }
+ else
+ {
+ dateTimeString.replace( "%S", QString::number( time.second() ) );
+ }
+
+ // timezone
+ dateTimeString.replace( "%Z", d->_project->identitySettings().timeZone );
+ QTime t;
+ const int offset = KRFCDate::localUTCOffset();
+ const int correction = offset < 0 ? -60 : 60;
+ t = t.addSecs( offset * correction );
+ dateTimeString.replace( "%z", ( offset < 0 ? "-" : "+" ) + t.toString("hhmm") );
+ break;
+ }
+ }
+ kdDebug(KBABEL) << "New date: " << dateTimeString << endl;
+ return dateTimeString;
+}
+
+
+ConversionStatus Catalog::saveFile()
+{
+ if(d->_url.isEmpty())
+ {
+ kdFatal(KBABEL) << "fatal error: empty filename" << endl;
+ return NO_FILE;
+ }
+
+ return saveFileAs(d->_url,true);
+}
+
+ConversionStatus Catalog::saveFileAs(const KURL &url, bool overwrite)
+{
+ if( d->_active ) return BUSY;
+
+ ConversionStatus status=OK;
+
+ bool newName=false;
+ KURL targetURL=d->_url;
+
+ if(url != d->_url)
+ {
+ newName = true;
+ targetURL=url;
+ }
+
+
+ if(d->_project->saveSettings().autoUpdate)
+ {
+ d->_header=updatedHeader(d->_header);
+ emit signalHeaderChanged();
+ }
+
+
+ if(targetURL.isLocalFile())
+ {
+ // test if the directory exists. If not, create it.
+ QDir dir( targetURL.directory());
+
+ QStringList dirList;
+ while(!dir.exists() && !dir.dirName().isEmpty())
+ {
+ dirList.prepend(dir.dirName());
+ dir.setPath(dir.path()+"/..");
+ }
+ for ( QStringList::Iterator it = dirList.begin(); it != dirList.end(); ++it )
+ {
+ if(!dir.mkdir(*it))
+ {
+ status=OS_ERROR;
+ break;
+ }
+ dir.cd(*it);
+ }
+
+ if(status==OK)
+ {
+ status=writeFile(targetURL.path(0),overwrite);
+ }
+ }
+ else
+ {
+ QString tempFile=kapp->tempSaveName(targetURL.path(0));
+
+ status = writeFile(tempFile,overwrite);
+
+ if(status == OK)
+ {
+ if( !KIO::NetAccess::upload( tempFile, targetURL, NULL ) )
+ {
+ status = OS_ERROR;
+ }
+ }
+
+ QFile::remove(tempFile);
+ }
+
+ if(status == OK)
+ {
+ setModified(false);
+
+ if(newName)
+ {
+ // if we saved a file, the catalog can not be any longer readOnly;
+ d->_readOnly=false;
+
+ d->_url=targetURL;
+
+ emit signalFileOpened(d->_readOnly);
+ }
+ }
+
+ return status;
+}
+
+QString Catalog::saveTempFile()
+{
+ QString filename = kapp->tempSaveName("/temp/kbabel_temp.po");
+ if( writeFile(filename) != OK )
+ {
+ filename = QString::null;
+ }
+
+ return filename;
+}
+
+
+ConversionStatus Catalog::writeFile(QString localFile , bool overwrite)
+{
+ QFileInfo info(localFile);
+
+ if(info.isDir())
+ return NO_FILE;
+
+ if(info.exists())
+ {
+ if(!overwrite || !info.isWritable())
+ {
+ return NO_PERMISSIONS;
+ }
+ }
+ else // check if the directory is writable
+ {
+ QFileInfo dir(info.dirPath());
+ if(!dir.isWritable())
+ {
+ return NO_PERMISSIONS;
+ }
+ }
+
+ ConversionStatus error = OK;
+ CatalogExportPlugin* filter=0;
+
+ // gimme plugin for this MIME type
+ KMimeType::Ptr mime = KMimeType::findByURL( KURL::fromPathOrURL( localFile ) );
+ KTrader::OfferList offers = KTrader::self()->query("KBabelFilter", "('"+mime->name()+"' in [X-KDE-Export])");
+ KService::Ptr ptr = offers.first();
+
+ // we have no offer for this MIME type
+ if( !ptr )
+ {
+ kdDebug(KBABEL) << "No plugin for this type" << endl;
+ return NO_PLUGIN;
+ }
+
+ // try to load the library, if unsuccesfull, we have an installation problem
+ KLibFactory *factory = KLibLoader::self()->factory( ptr->library().local8Bit() );
+ if (!factory)
+ {
+ kdDebug(KBABEL) << "No factory" << endl;
+ return OS_ERROR;
+ }
+
+ // create the filter
+ filter = static_cast<CatalogExportPlugin*>(factory->create(0, 0));
+
+ // provide progress bar indication
+ connect( filter, SIGNAL( signalResetProgressBar(QString,int) ),
+ this, SIGNAL( signalResetProgressBar(QString,int) ));
+ connect( filter, SIGNAL( signalProgress(int) ),
+ this, SIGNAL( signalProgress(int) ));
+ connect( filter, SIGNAL( signalClearProgressBar() ),
+ this, SIGNAL( signalClearProgressBar() ));
+
+ connect( this, SIGNAL( signalStopActivity() ),
+ filter, SLOT( stop() ));
+
+ // load in the file (target is always local)
+ kdDebug(KBABEL) << "writeFile active" << endl;
+ d->_active = true;
+ error = filter->save(localFile,mime->name(),this);
+ // we should be not freed yet
+ kdDebug(KBABEL) << "writeFile not active" << endl;
+ d->_active = false;
+ if( error == STOPPED ) return STOPPED;
+
+ delete filter;
+
+ return error;
+}
+
+QTextCodec* Catalog::codecForFile(QString gettextHeader)
+{
+ QString charset;
+
+ QString head = gettextHeader;
+
+ QRegExp r("Content-Type:\\s*\\w+/[-\\w]+;?\\s*charset\\s*=\\s*[^\\\"\\n]+");
+ int begin=r.search(head);
+ int len=r.matchedLength();
+ if(begin<0) {
+ kdDebug(KBABEL) << "no charset entry found" << endl;
+ return 0;
+ }
+
+ head = head.mid(begin,len);
+
+ QRegExp regexp("charset *= *([^\\\\\\\"]+)");
+ if( regexp.search( head ) > -1 )
+ {
+ charset = regexp.cap(1);
+ }
+
+ QTextCodec* codec=0;
+
+ if(!charset.isEmpty())
+ {
+ // "CHARSET" is the default charset entry in a template (pot).
+ // characters in a template should be either pure ascii or
+ // at least utf8, so utf8-codec can be used for both.
+ if( charset == "CHARSET")
+ {
+ codec=QTextCodec::codecForName("utf8");
+ kdDebug(KBABEL)
+ << QString("file seems to be a template: using utf8 encoding.")
+ << endl;
+ }
+ else
+ {
+ codec=QTextCodec::codecForName(charset.latin1());
+ }
+
+ if(!codec)
+ {
+ kdWarning() << "charset found, but no codec available, using UTF8 instead" << endl;
+ codec=QTextCodec::codecForName("utf8");
+ }
+ }
+
+ return codec;
+}
+
+PoInfo Catalog::headerInfo(const CatalogItem headerItem)
+{
+ QStringList header=headerItem.msgstrAsList();
+
+ QStringList::Iterator it;
+
+ PoInfo info;
+
+ // extract information from the header
+ for(it=header.begin();it!=header.end();++it)
+ {
+ if((*it).contains(QRegExp("^\\s*Project-Id-Version\\s*:\\s*.+\\s*$")))
+ {
+ info.project=(*it).replace(QRegExp("^\\s*Project-Id-Version\\s*:\\s*"),"");
+
+ if(info.project.right(2)=="\\n")
+ info.project.remove(info.project.length()-2,2);
+
+ info.project=info.project.simplifyWhiteSpace();
+ }
+ else if((*it).contains(QRegExp("^\\s*POT-Creation-Date\\s*:\\s*.+\\s*$")))
+ {
+ info.creation=(*it).replace(QRegExp("^\\s*POT-Creation-Date\\s*:\\s*"),"");
+
+ if(info.creation.right(2)=="\\n")
+ info.creation.remove(info.creation.length()-2,2);
+
+ info.creation=info.creation.simplifyWhiteSpace();
+ }
+ else if((*it).contains(QRegExp("^\\s*PO-Revision-Date\\s*:\\s*.+\\s*$")))
+ {
+ info.revision=(*it).replace(QRegExp("^\\s*PO-Revision-Date\\s*:\\s*"),"");
+
+ if(info.revision.right(2)=="\\n")
+ info.revision.remove(info.revision.length()-2,2);
+
+ info.revision=info.revision.simplifyWhiteSpace();
+ }
+ else if((*it).contains(QRegExp("^\\s*Last-Translator\\s*:\\s*.+\\s*$")))
+ {
+ info.lastTranslator=(*it).replace(QRegExp("^\\s*Last-Translator\\s*:\\s*"),"");
+
+ if(info.lastTranslator.right(2)=="\\n")
+ info.lastTranslator.remove(info.lastTranslator.length()-2,2);
+
+ info.lastTranslator=info.lastTranslator.simplifyWhiteSpace();
+ }
+ else if((*it).contains(QRegExp("^\\s*Language-Team\\s*:\\s*.+\\s*")))
+ {
+ info.languageTeam=(*it).replace(QRegExp("^\\s*Language-Team\\s*:\\s*"),"");
+
+ if(info.languageTeam.right(2)=="\\n")
+ info.languageTeam.remove(info.languageTeam.length()-2,2);
+
+ info.languageTeam=info.languageTeam.simplifyWhiteSpace();
+ }
+ else if((*it).contains(QRegExp("^\\s*MIME-Version\\s*:\\s*.+\\s*")))
+ {
+ info.mimeVersion=(*it).replace(QRegExp("^\\s*MIME-Version\\s*:\\s*"),"");
+
+ if(info.mimeVersion.right(2)=="\\n")
+ info.mimeVersion.remove(info.mimeVersion.length()-2,2);
+
+ info.mimeVersion=info.mimeVersion.simplifyWhiteSpace();
+ }
+ else if((*it).contains(QRegExp("^\\s*Content-Type\\s*:\\s*.+\\s*")))
+ {
+ info.contentType=(*it).replace(QRegExp("^\\s*Content-Type\\s*:\\s*"),"");
+
+ if(info.contentType.right(2)=="\\n")
+ info.contentType.remove(info.contentType.length()-2,2);
+
+ info.contentType=info.contentType.simplifyWhiteSpace();
+ }
+ else if((*it).contains(QRegExp("^\\s*Content-Transfer-Encoding\\s*:\\s*.+\\s*")))
+ {
+ info.encoding=(*it).replace(QRegExp("^\\s*Content-Transfer-Encoding\\s*:\\s*"),"");
+
+ if(info.encoding.right(2)=="\\n")
+ info.encoding.remove(info.encoding.length()-2,2);
+
+ info.encoding=info.encoding.simplifyWhiteSpace();
+ }
+ else
+ {
+ QString line=(*it);
+
+ if(line.right(2)=="\\n")
+ line.remove(line.length()-2,2);
+
+ line=line.simplifyWhiteSpace();
+ if(!info.others.isEmpty())
+ info.others+='\n';
+
+ info.others+=line;
+ }
+
+
+ }
+
+ info.headerComment=headerItem.comment();
+
+ return info;
+}
+
+bool Catalog::isUndoAvailable()
+{
+ return !d->_undoList.isEmpty();
+}
+
+bool Catalog::isRedoAvailable()
+{
+ return !d->_redoList.isEmpty();
+}
+
+int Catalog::undo()
+{
+ if(!isUndoAvailable())
+ return -1;
+
+ int macroLevel = 0;
+
+ EditCommand *command=0;
+ do
+ {
+ command = d->_undoList.take();
+ if ( !command )
+ {
+ kdError() << "undo command is NULL?" << endl;
+ return -1;
+ }
+
+ processCommand( command, 0, true );
+
+ macroLevel += command->terminator();
+
+ if ( d->_undoList.isEmpty() )
+ {
+ emit signalUndoAvailable( false );
+ }
+ if(d->_redoList.isEmpty())
+ {
+ emit signalRedoAvailable(true);
+ }
+ d->_redoList.append(command);
+
+ }
+ while(macroLevel != 0);
+
+ return command->index();
+}
+
+int Catalog::redo()
+{
+ if(!isRedoAvailable())
+ return -1;
+
+ int macroLevel = 0;
+ EditCommand *command=0;
+
+ do
+ {
+ command = d->_redoList.take();
+ if ( !command )
+ {
+ kdError() << "undo command is NULL?" << endl;
+ return -1;
+ }
+
+ processCommand( command, 0,false );
+
+ macroLevel += command->terminator();
+ if ( d->_redoList.isEmpty() )
+ {
+ emit signalRedoAvailable( false );
+ }
+ if ( d->_undoList.isEmpty() )
+ {
+ emit signalUndoAvailable( true );
+ }
+
+ d->_undoList.append( command );
+ }
+ while (macroLevel != 0);
+
+ return command->index();
+}
+
+void Catalog::applyEditCommand(EditCommand* cmd, CatalogView* view)
+{
+
+ processCommand(cmd,view);
+ setModified(true);
+
+ if ( d->_undoList.isEmpty() )
+ {
+ emit signalUndoAvailable(true);
+ }
+ else if ( cmd->merge( d->_undoList.last() ) )
+ {
+ delete cmd;
+ return;
+ }
+
+
+ d->_undoList.append(cmd);
+
+
+ if ( !d->_redoList.isEmpty() )
+ {
+ d->_redoList.clear();
+ emit signalRedoAvailable( false );
+ }
+
+}
+
+void Catalog::applyBeginCommand(uint index, Part part, CatalogView* view)
+{
+ applyEditCommand( new BeginCommand(index,part), view );
+}
+
+void Catalog::applyEndCommand(uint index, Part part, CatalogView* view)
+{
+ applyEditCommand( new EndCommand(index,part), view );
+}
+
+void Catalog::processCommand(EditCommand* cmd,CatalogView* view, bool undo)
+{
+ kdDebug(KBABEL) << "Catalog::processCommand()" << endl;
+ if(cmd->terminator()==0)
+ {
+ bool checkUntranslated=false;
+ bool checkFuzzy=false;
+ bool wasFuzzy=false;
+
+ CatalogItem &item=d->_entries[cmd->index()];
+
+ if(cmd->part() == Msgstr)
+ {
+ if( item.isUntranslated() )
+ {
+ d->_untransIndex.remove(cmd->index());
+
+ emit signalNumberOfUntranslatedChanged(numberOfUntranslated());
+ }
+ else
+ {
+ checkUntranslated=true;
+ }
+ }
+ else if(cmd->part() == Comment)
+ {
+ checkFuzzy=true;
+ wasFuzzy=item.isFuzzy();
+ }
+
+
+
+ item.processCommand(cmd,undo);
+
+ if(undo)
+ {
+ EditCommand* tmpCmd=0;
+ DelTextCmd* delcmd = (DelTextCmd*) cmd;
+ if (delcmd->type() == EditCommand::Delete )
+ {
+ tmpCmd = new InsTextCmd(delcmd->offset,delcmd->str,delcmd->pluralNumber);
+ }
+ else
+ {
+ tmpCmd = new DelTextCmd(delcmd->offset,delcmd->str,delcmd->pluralNumber);
+ }
+
+ tmpCmd->setIndex(cmd->index());
+ tmpCmd->setPart(cmd->part());
+
+ updateViews(tmpCmd,view);
+
+ delete tmpCmd;
+ }
+ else
+ {
+ updateViews(cmd,view);
+ }
+
+ if(checkUntranslated && item.isUntranslated())
+ {
+ QValueList<uint>::Iterator it;
+
+ // insert index in the right place in the list
+ it = d->_untransIndex.begin();
+ while(it != d->_untransIndex.end() && cmd->index() > (int)(*it))
+ {
+ ++it;
+ }
+ d->_untransIndex.insert( it,(uint)(cmd->index()) );
+
+ emit signalNumberOfUntranslatedChanged(numberOfUntranslated());
+ }
+ else if(checkFuzzy)
+ {
+ if(wasFuzzy != item.isFuzzy())
+ {
+ if(wasFuzzy)
+ {
+ d->_fuzzyIndex.remove(cmd->index());
+ emit signalNumberOfFuzziesChanged(numberOfFuzzies());
+ }
+ else
+ {
+ QValueList<uint>::Iterator it;
+
+ // insert index in the right place in the list
+ it = d->_fuzzyIndex.begin();
+ while(it != d->_fuzzyIndex.end() && cmd->index() > (int)(*it))
+ {
+ ++it;
+ }
+ d->_fuzzyIndex.insert( it,(uint)(cmd->index()) );
+
+ emit signalNumberOfFuzziesChanged(numberOfFuzzies());
+ }
+ }
+ }
+
+ }
+}
+
+bool Catalog::findNext(const FindOptions* findOpts, DocPosition& docPos, int& len)
+{
+ bool success = false; // true, when string found
+ bool endReached=false;
+
+ kdDebug(KBABEL) << "findNext active" << endl;
+ d->_active=true;
+ d->_stop=false;
+ connect( this, SIGNAL( signalStopActivity() ), this, SLOT( stopInternal() ));
+
+ MiscSettings miscOptions = miscSettings();
+
+ len=0;
+ int pos=0;
+
+ QString searchStr = findOpts->findStr;
+ QRegExp regexp(searchStr);
+
+ if( findOpts->isRegExp ) {
+ regexp.setCaseSensitive(findOpts->caseSensitive);
+ }
+
+ if( docPos.item == numberOfEntries()-1) {
+ switch(docPos.part) {
+ case Msgid:
+ // FIXME: we should search in plurals as well
+ if(!findOpts->inMsgstr && !findOpts->inComment
+ && docPos.offset >= msgid(docPos.item).first().length() ) {
+ endReached=true;
+ }
+ break;
+ case Msgstr:
+ if(!findOpts->inComment && (int)(docPos.form+1) >= numberOfPluralForms(docPos.item)
+ && docPos.offset >= msgstr(docPos.item).last().length() ) {
+ endReached=true;
+ }
+ break;
+ case Comment:
+ if(docPos.offset >= comment(docPos.item).length() ) {
+ endReached=true;
+ }
+ break;
+ case UndefPart:
+ break;
+ }
+ }
+
+ while(!success) {
+ int accelMarkerPos = -1;
+ int contextInfoLength = 0;
+ int contextInfoPos = -1;
+ QString targetStr;
+
+ kapp->processEvents(10);
+
+ if( d->_stop || endReached)
+ {
+ kdDebug(KBABEL) << "FindNext: endReached or stopped" << endl;
+ disconnect( this, SIGNAL( signalStopActivity() ), this, SLOT( stopInternal() ));
+ kdDebug(KBABEL) << "findNext not active" << endl;
+ d->_active=false;
+ d->_stop=false;
+ return false;
+ }
+
+ switch(docPos.part) {
+ case Msgid:
+ // FIXME: should care about plural forms in msgid
+ targetStr = msgid(docPos.item).first();
+ break;
+ case Msgstr:
+ targetStr = *(msgstr(docPos.item).at(docPos.form));
+ break;
+ case Comment:
+ targetStr = comment(docPos.item);
+ break;
+ case UndefPart:
+ break;
+ }
+
+ if(findOpts->ignoreContextInfo)
+ {
+ contextInfoPos = miscOptions.contextInfo.search(targetStr);
+ contextInfoLength = miscOptions.contextInfo.matchedLength();
+ if(contextInfoPos >= 0)
+ {
+ targetStr.remove(contextInfoPos,contextInfoLength);
+
+ if(docPos.offset > (uint)contextInfoPos)
+ docPos.offset -= contextInfoLength;
+ }
+ }
+
+ if(findOpts->ignoreAccelMarker
+ && targetStr.contains(miscOptions.accelMarker))
+ {
+ accelMarkerPos = targetStr.find(miscOptions.accelMarker);
+ targetStr.remove(accelMarkerPos,1);
+
+ if(docPos.offset > (uint)accelMarkerPos)
+ docPos.offset--;
+ }
+
+ if( findOpts->isRegExp ) {
+ if ((pos=regexp.search(targetStr,docPos.offset)) >= 0 ) {
+ len = regexp.matchedLength();
+ if(findOpts->wholeWords) {
+ QString pre=targetStr.mid(pos-1,1);
+ QString post=targetStr.mid(pos+len,1);
+ if(!pre.contains(QRegExp("[a-zA-Z0-9]")) && !post.contains(QRegExp("[a-zA-Z0-9]")) ){
+ success=true;
+ docPos.offset=pos;
+ }
+ }
+ else {
+ success=true;
+ docPos.offset=pos;
+ }
+ }
+ }
+ else {
+ if( (pos=targetStr.find(searchStr,docPos.offset,findOpts->caseSensitive)) >= 0 ) {
+ len=searchStr.length();
+
+ if(findOpts->wholeWords) {
+ QString pre=targetStr.mid(pos-1,1);
+ QString post=targetStr.mid(pos+len,1);
+ if(!pre.contains(QRegExp("[a-zA-Z0-9]")) && !post.contains(QRegExp("[a-zA-Z0-9]")) ){
+ success=true;
+ docPos.offset=pos;
+ }
+ }
+ else {
+ success=true;
+ docPos.offset=pos;
+ }
+ }
+ }
+
+
+ if(!success) {
+ docPos.offset=0;
+ switch(docPos.part) {
+ case Msgid:
+ {
+ if(findOpts->inMsgstr) {
+ docPos.part = Msgstr;
+ docPos.form = 0;
+ }
+ else if(findOpts->inComment) {
+ docPos.part = Comment;
+ }
+ else
+ {
+ if(docPos.item >= numberOfEntries()-1)
+ {
+ endReached=true;
+ }
+ else
+ {
+ docPos.item++;
+ docPos.form = 0;
+ }
+ }
+ break;
+ }
+ case Msgstr:
+ if( (int)docPos.form < numberOfPluralForms(docPos.item)-1 && pluralForm(docPos.item)==Gettext) {
+ docPos.form++;
+ }
+ else
+ if(findOpts->inComment) {
+ docPos.part = Comment;
+ }
+ else if(findOpts->inMsgid) {
+ if(docPos.item >= numberOfEntries()-1)
+ {
+ endReached=true;
+ }
+ else
+ {
+ docPos.part = Msgid;
+ docPos.item++;
+ }
+ }
+ else {
+ if(docPos.item >= numberOfEntries()-1)
+ {
+ endReached=true;
+ }
+ else
+ {
+ docPos.item++;
+ docPos.form = 0;
+ }
+ }
+ break;
+ case Comment:
+ if(findOpts->inMsgid) {
+ if(docPos.item >= numberOfEntries()-1)
+ {
+ endReached=true;
+ }
+ else
+ {
+ docPos.part = Msgid;
+ docPos.item++;
+ docPos.form = 0;
+ }
+ }
+ else if(findOpts->inMsgstr){
+ if(docPos.item >= numberOfEntries()-1)
+ {
+ endReached=true;
+ }
+ else
+ {
+ docPos.part = Msgstr;
+ docPos.form = 0;
+ docPos.item++;
+ }
+ }
+ else {
+ if(docPos.item >= numberOfEntries()-1)
+ {
+ endReached=true;
+ }
+ else
+ {
+ docPos.item++;
+ docPos.form = 0;
+ }
+ }
+ break;
+ case UndefPart:
+ break;
+ }
+ }
+ else
+ {
+ if(accelMarkerPos >= 0)
+ {
+ if(docPos.offset >= (uint)accelMarkerPos)
+ {
+ docPos.offset++;
+ }
+ else if(docPos.offset+len > (uint)accelMarkerPos)
+ {
+ len++;
+ }
+ }
+
+ if(contextInfoPos >= 0)
+ {
+ if(docPos.offset >= (uint)contextInfoPos)
+ {
+ docPos.offset+=contextInfoLength;
+ }
+ else if(docPos.offset+len > (uint)contextInfoPos)
+ {
+ len+=contextInfoLength;
+ }
+
+ }
+ }
+ }
+
+ disconnect( this, SIGNAL( signalStopActivity() ), this, SLOT( stopInternal() ));
+ kdDebug(KBABEL) << "findNext not active" << endl;
+ d->_active=false;
+ d->_stop=false;
+
+ return true;
+}
+
+bool Catalog::findPrev(const FindOptions* findOpts, DocPosition& docPos, int& len)
+{
+ bool success = false; // true, when found
+ bool beginReached = false;
+
+ kdDebug(KBABEL) << "findPrev active" << endl;
+ d->_active=true;
+ d->_stop=false;
+ connect( this, SIGNAL( signalStopActivity() ), this, SLOT( stopInternal() ));
+
+ MiscSettings miscOptions = miscSettings();
+
+ len=0;
+ int pos=0;
+
+ QString searchStr = findOpts->findStr;
+ QRegExp regexp(searchStr);
+
+ if( findOpts->isRegExp ) {
+ regexp.setCaseSensitive(findOpts->caseSensitive);
+ }
+ while(!success) {
+ int accelMarkerPos = -1;
+ int contextInfoLength = 0;
+ int contextInfoPos = -1;
+ QString targetStr;
+
+ kapp->processEvents(10);
+
+ if( d->_stop || beginReached)
+ {
+ kdDebug(KBABEL) << "FindNext: endReached or stopped" << endl;
+ disconnect( this, SIGNAL( signalStopActivity() ), this, SLOT( stopInternal() ));
+ kdDebug(KBABEL) << "findPrev active" << endl;
+ d->_active=false;
+ d->_stop=false;
+ return false;
+ }
+
+ switch(docPos.part) {
+ case Msgid:
+ // FIXME: should care about plural forms in msgid
+ targetStr = msgid(docPos.item).first();
+ break;
+ case Msgstr:
+ targetStr = *(msgstr(docPos.item).at(docPos.form));
+ break;
+ case Comment:
+ targetStr = comment(docPos.item);
+ break;
+ case UndefPart:
+ break;
+ }
+
+ if(findOpts->ignoreContextInfo)
+ {
+ contextInfoPos = miscOptions.contextInfo.search(targetStr);
+ contextInfoLength = miscOptions.contextInfo.matchedLength();
+ if(contextInfoPos >= 0)
+ {
+ targetStr.remove(contextInfoPos,contextInfoLength);
+
+ if(docPos.offset > (uint)contextInfoPos)
+ docPos.offset -= contextInfoLength;
+ }
+ }
+
+ if(findOpts->ignoreAccelMarker
+ && targetStr.contains(miscOptions.accelMarker))
+ {
+ accelMarkerPos = targetStr.find(miscOptions.accelMarker);
+ targetStr.remove(accelMarkerPos,1);
+
+ if(docPos.offset > (uint)accelMarkerPos)
+ docPos.offset--;
+ }
+
+ if(docPos.offset <= 0) {
+ success=false;
+ }
+ else if( findOpts->isRegExp ) {
+ /*
+ don't work!?
+ if((pos=targetStr.findRev(regexp,docPos.offset)) >= 0 ) {
+ regexp.match(targetStr,pos,&len); // to get the length of the string
+ */
+ bool found=false;
+ int tmpPos=docPos.offset;
+ while(!found && tmpPos>=0)
+ {
+ if( (pos=regexp.search(targetStr,tmpPos)) >= 0 && (uint)pos < docPos.offset)
+ found=true;
+ else
+ tmpPos--;
+ len = regexp.matchedLength();
+ }
+ if(found) {
+ if(findOpts->wholeWords) {
+ QString pre=targetStr.mid(pos-1,1);
+ QString post=targetStr.mid(pos+len,1);
+ if(!pre.contains(QRegExp("[a-zA-Z0-9]")) && !post.contains(QRegExp("[a-zA-Z0-9]")) ){
+ success=true;
+ docPos.offset=pos;
+ }
+ }
+ else {
+ success=true;
+ docPos.offset=pos;
+ }
+ }
+ }
+ else if( (pos=targetStr.findRev(searchStr,docPos.offset-1,findOpts->caseSensitive)) >= 0
+ && (uint)pos < docPos.offset) {
+ len=searchStr.length();
+ if(findOpts->wholeWords) {
+ QString pre=targetStr.mid(pos-1,1);
+ QString post=targetStr.mid(pos+len,1);
+ if(!pre.contains(QRegExp("[a-zA-Z0-9]")) && !post.contains(QRegExp("[a-zA-Z0-9]")) ){
+ success=true;
+ docPos.offset=pos;
+ }
+ }
+ else {
+ success=true;
+ docPos.offset=pos;
+ }
+ }
+
+ if(!success) {
+ switch(docPos.part) {
+ case Comment:
+ {
+ if(findOpts->inMsgstr) {
+ docPos.part = Msgstr;
+ docPos.form = msgstr(docPos.item).count()-1;
+ docPos.offset = msgstr(docPos.item).last().length();
+ }
+ else if(findOpts->inMsgid) {
+ docPos.part = Msgid;
+ // FIXME: should care about plural forms in msgid
+ docPos.offset = msgid(docPos.item).first().length();
+ }
+ else
+ {
+ if(docPos.item <= 0)
+ {
+ beginReached=true;
+ }
+ else
+ {
+ docPos.item--;
+ docPos.offset = comment(docPos.item).length();
+ }
+ }
+ break;
+ }
+ case Msgstr:
+ if(docPos.form != 0 ) {
+ docPos.form--;
+ docPos.offset = (*msgstr(docPos.item).at(docPos.form)).length();
+ }
+ else if(findOpts->inMsgid) {
+ docPos.part = Msgid;
+ // FIXME: should care about plural forms in msgid
+ docPos.offset = msgid(docPos.item).first().length();
+ }
+ else if(findOpts->inComment) {
+ if(docPos.item <= 0)
+ {
+ beginReached=true;
+ }
+ else
+ {
+ docPos.part = Comment;
+ docPos.item--;
+ docPos.offset = comment(docPos.item).length();
+ }
+ }
+ else {
+ if(docPos.item <= 0)
+ {
+ beginReached=true;
+ }
+ else
+ {
+ docPos.item--;
+ docPos.offset = msgstr(docPos.item).last().length();
+ docPos.form = msgstr(docPos.item).count()-1;
+ }
+ }
+ break;
+ case Msgid:
+ if(findOpts->inComment) {
+ if(docPos.item <= 0 )
+ {
+ beginReached=true;
+ }
+ else
+ {
+ docPos.part = Comment;
+ docPos.item--;
+ docPos.offset = comment(docPos.item).length();
+ }
+ }
+ else if(findOpts->inMsgstr){
+ if(docPos.item <= 0)
+ {
+ beginReached=true;
+ }
+ else
+ {
+ docPos.part = Msgstr;
+ docPos.item--;
+ docPos.offset = msgstr(docPos.item).last().length();
+ docPos.form = msgstr(docPos.item).count()-1;
+ }
+ }
+ else {
+ if(docPos.item <= 0)
+ {
+ beginReached=true;
+ }
+ else
+ {
+ docPos.item--;
+ // FIXME: should care about plural forms in msgid
+ docPos.offset = msgid(docPos.item).first().length();
+ }
+ }
+ break;
+ case UndefPart:
+ break;
+ }
+ }
+ else
+ {
+ if(accelMarkerPos >= 0)
+ {
+ if(docPos.offset >= (uint)accelMarkerPos)
+ {
+ docPos.offset++;
+ }
+ else if(docPos.offset+len > (uint)accelMarkerPos)
+ {
+ len++;
+ }
+ }
+
+ if(contextInfoPos >= 0)
+ {
+ if(docPos.offset >= (uint)contextInfoPos)
+ {
+ docPos.offset+=contextInfoLength;
+ }
+ else if(docPos.offset+len > (uint)contextInfoPos)
+ {
+ len+=contextInfoLength;
+ }
+
+ }
+ }
+ }
+
+ disconnect( this, SIGNAL( signalStopActivity() ), this, SLOT( stopInternal() ));
+ kdDebug(KBABEL) << "findPrev active" << endl;
+ d->_active=false;
+ d->_stop=false;
+
+ return true;
+}
+
+
+Catalog::DiffResult Catalog::diff(uint entry, QString *result)
+{
+ if(!result)
+ {
+ kdWarning() << "0 pointer for result" << endl;
+ return DiffNotFound;
+ }
+
+ if( d->msgidDiffList.isEmpty() )
+ {
+ return DiffNeedList;
+ }
+
+ // first look if the diff for this entry is in the cache
+ QString *s = d->diffCache[entry];
+ if(s)
+ {
+ if(s->isEmpty())
+ return DiffNotFound;
+
+
+ *result = *s;
+ return DiffOk;
+ }
+
+ // then look if the same msgid is contained in the diff file
+ // FIXME: should care about plural forms in msgid
+ QString id = msgid(entry).first();
+ id.replace( "\n","");
+ if(d->msgidDiffList.contains(id))
+ {
+ // FIXME:: should care about plural forms in msgid
+ *result = msgid(entry).first();
+
+ return DiffOk;
+ }
+
+ connect( this, SIGNAL( signalStopActivity() ), this, SLOT( stopInternal() ));
+ kdDebug(KBABEL) << "diffv active" << endl;
+ d->_active=true;
+ d->_stop=false;
+
+ QString idForDiff;
+
+
+ // then look if there are entries with the same translation
+ kdWarning() << "Diff feature (2) does not work with plural forms" << endl;
+ QString str = msgstr(entry).first();
+ str.replace("\n","");
+ if(d->msgstr2MsgidDiffList.contains(str))
+ {
+ QStringList list = d->msgstr2MsgidDiffList[str];
+
+ if(list.count() == 1)
+ {
+ idForDiff = list.first();
+ }
+ else
+ {
+ // find the best matching id
+ double bestWeight = 0.6;
+ QString bestId;
+
+ QStringList::ConstIterator it;
+ for(it = list.begin(); it != list.end(); ++it)
+ {
+ double weight = LevenshteinDistance()(id, (*it));
+ if(weight > bestWeight)
+ {
+ bestWeight = weight;
+ bestId = (*it);
+ }
+ }
+
+ if( !bestId.isEmpty() )
+ {
+ idForDiff = bestId;
+ }
+ }
+ }
+ else
+ {
+ emit signalResetProgressBar(i18n("searching matching message")
+ ,100);
+
+ // find the best matching id
+ double bestWeight = 0.6;
+ QString bestId;
+
+ int counter=0;
+ int oldPercent=0;
+ int max = QMAX( d->msgidDiffList.count()-1, 1);
+
+ QStringList::ConstIterator it;
+ for(it = d->msgidDiffList.begin();
+ it != d->msgidDiffList.end(); ++it)
+ {
+ counter++;
+ int percent = 100*counter/max;
+ if(percent > oldPercent)
+ {
+ oldPercent = percent;
+ emit signalProgress(percent);
+ }
+
+ double weight = LevenshteinDistance()( id, (*it) );
+ if(weight > bestWeight)
+ {
+ bestWeight = weight;
+ bestId = (*it);
+ }
+
+ kapp->processEvents(10);
+
+ if( d->_stop )
+ {
+ disconnect( this, SIGNAL( signalStopActivity() ), this, SLOT( stopInternal() ));
+ kdDebug
+
+ (KBABEL) << "diffv not active" << endl;
+ d->_active=false;
+ d->_stop=false;
+ return DiffNotFound;
+ }
+ }
+
+ if( !bestId.isEmpty() )
+ {
+ idForDiff = bestId;
+ }
+
+ emit signalClearProgressBar();
+
+ }
+
+ if( idForDiff.isEmpty() )
+ {
+ s = new QString(*result);
+ if( !d->diffCache.insert(entry,s) )
+ delete s;
+
+ kdDebug (KBABEL) << "diffv not active" << endl;
+ d->_active=false;
+ d->_stop=false;
+ return DiffNotFound;
+ }
+
+ QString r = wordDiff(idForDiff,id);
+
+ //esp for plural forms
+ *result = r.replace("\\n<KBABELADD>" + QString(QChar(0x00B6)) + "</KBABELADD>", "\\n\n");
+
+ s = new QString(*result);
+ if( !d->diffCache.insert(entry,s) )
+ delete s;
+
+ disconnect( this, SIGNAL( signalStopActivity() ), this, SLOT( stopInternal() ));
+ kdDebug(KBABEL) << "diffv not active" << endl;
+ d->_active=false;
+ d->_stop=false;
+
+ return DiffOk;
+}
+
+void Catalog::setDiffList( const QValueList<DiffEntry>& list)
+{
+ connect( this, SIGNAL( signalStopActivity() ), this, SLOT( stopInternal() ));
+ kdDebug(KBABEL) << "setDiffList active" << endl;
+ d->_active=true;
+ d->_stop=false;
+
+ emit signalResetProgressBar(i18n("preparing messages for diff"),100);
+
+ d->msgidDiffList.clear();
+ d->msgstr2MsgidDiffList.clear();
+ d->diffCache.clear();
+
+ uint max = QMAX(list.count()-1,1);
+ int oldPercent=0;
+ uint counter=0;
+ QValueList<DiffEntry>::ConstIterator it;
+ for(it = list.begin(); it != list.end(); ++it)
+ {
+ int percent = (100*counter)/max;
+ counter++;
+ if(percent > oldPercent)
+ {
+ oldPercent = percent;
+ emit signalProgress(percent);
+ kapp->processEvents(10);
+ }
+
+ QString id = (*it).msgid;
+ id.replace("\n","");
+ QString str = (*it).msgstr;
+ str.replace("\n","");
+ d->msgidDiffList.append(id);
+
+ if(!str.isEmpty())
+ {
+ if(d->msgstr2MsgidDiffList.contains(str))
+ {
+ QStringList sl = d->msgstr2MsgidDiffList[str];
+ sl.append(id);
+ }
+ else
+ {
+ QStringList sl;
+ sl.append(id);
+ d->msgstr2MsgidDiffList.insert(str,sl);
+ }
+ }
+ }
+
+ emit signalClearProgressBar();
+
+ disconnect( this, SIGNAL( signalStopActivity() ), this, SLOT( stopInternal() ));
+ kdDebug(KBABEL) << "setDiffList not active" << endl;
+ d->_active=false;
+ d->_stop=false;
+}
+
+QValueList<DiffEntry> Catalog::asDiffList()
+{
+ QValueList<DiffEntry> list;
+
+ for ( QValueVector<CatalogItem>::Iterator it = d->_entries.begin();
+ it != d->_entries.end(); ++it)
+ {
+ DiffEntry e;
+ e.msgid = (*it).msgid().first();
+ kdWarning() << "Diff feature does not support plural forms" << endl;
+ e.msgstr = (*it).msgstr().first();
+
+ list.append(e);
+ }
+
+ return list;
+
+}
+
+int Catalog::defaultNumberOfPluralForms() const
+{
+ return d->numberOfPluralForms;
+}
+
+void Catalog::getNumberOfPluralForms()
+{
+ IdentitySettings options = identitySettings();
+
+ if(options.numberOfPluralForms > 0)
+ {
+ d->numberOfPluralForms = options.numberOfPluralForms;
+ return;
+ }
+
+ QString lang=options.languageCode;
+ if(lang.isEmpty())
+ {
+ d->numberOfPluralForms=-1;
+ return;
+ }
+
+ d->numberOfPluralForms = getNumberOfPluralForms(lang);
+}
+
+int Catalog::getNumberOfPluralForms(const QString& lang)
+{
+ int nr=-1;
+
+ KLocale locale("kdelibs");
+ locale.setLanguage(lang);
+
+ const char* formsString =
+ "_: Dear translator, please do not translate this string in any form, but "
+ "pick the _right_ value out of NoPlural/TwoForms/French... If not sure what "
+ "to do mail thd@kde.org and coolo@kde.org, they will tell you. Better leave "
+ "that out if unsure, the programs will crash!!\n"
+ "Definition of PluralForm - to be set by the translator of kdelibs.po";
+
+ QString formsTranslation = locale.translate(formsString);
+
+ // no translation found
+ if(formsTranslation == formsString || formsTranslation.isEmpty())
+ {
+ kdDebug(KBABEL) << "no translation of PluralForms found" << endl;
+ return -1;
+ }
+ if ( formsTranslation == "NoPlural" )
+ nr = 1;
+ else if ( formsTranslation == "TwoForms" )
+ nr = 2;
+ else if ( formsTranslation == "French" )
+ nr = 2;
+ else if ( formsTranslation == "Gaeilge" || formsTranslation == "OneTwoRest" )
+ nr = 3;
+ else if ( formsTranslation == "Russian" )
+ nr = 3;
+ else if ( formsTranslation == "Polish" )
+ nr = 3;
+ else if ( formsTranslation == "Slovenian" )
+ nr = 4;
+ else if ( formsTranslation == "Lithuanian" )
+ nr = 3;
+ else if ( formsTranslation == "Czech" )
+ nr = 3;
+ else if ( formsTranslation == "Slovak" )
+ nr = 3;
+ else if ( formsTranslation == "Maltese" )
+ nr = 4;
+ else if ( formsTranslation == "Arabic" )
+ nr = 4;
+ else if ( formsTranslation == "Balcan" )
+ nr = 3;
+ else
+ {
+ kdDebug(KBABEL) << "unknown translation of PluralForms: "
+ << formsTranslation << endl;
+ nr=-1;
+ }
+
+ return nr;
+}
+
+int Catalog::numberOfPluralForms( uint index ) const
+{
+ if( index > numberOfEntries() ) return -1;
+
+ if ( d->_entries.isEmpty() )
+ return -1;
+ if( d->_entries[index].pluralForm() == NoPluralForm ) return 1;
+
+ if( d->numberOfPluralForms > 0 ) return d->numberOfPluralForms;
+
+ return 2; //default
+}
+
+bool Catalog::isModified() const
+{
+ return d->_modified;
+}
+
+void Catalog::setEntries(QValueVector<CatalogItem> entries)
+{
+ d->_entries=entries;
+
+ // update the project for entries
+ for ( QValueVector<CatalogItem>::Iterator it = d->_entries.begin();
+ it != d->_entries.end(); ++it)
+ {
+ it->setProject( d->_project );
+ }
+}
+
+void Catalog::setObsoleteEntries(QValueList<CatalogItem> entries)
+{
+ d->_obsoleteEntries=entries;
+}
+
+QValueList<CatalogItem> Catalog::obsoleteEntries() const
+{
+ return d->_obsoleteEntries;
+}
+
+void Catalog::setCatalogExtraData(const QStringList& data)
+{
+ d->_catalogExtra = data;
+}
+
+QStringList Catalog::catalogExtraData() const
+{
+ return d->_catalogExtra;
+}
+
+QString Catalog::importPluginID() const
+{
+ return d->_importID;
+}
+
+QTextCodec* Catalog::fileCodec() const
+{
+ return d->fileCodec;
+}
+
+void Catalog::setGeneratedFromDocbook(const bool generated)
+{
+ d->_generatedFromDocbook = generated;
+}
+
+void Catalog::setFileCodec( QTextCodec* codec )
+{
+ d->fileCodec = codec;
+}
+
+void Catalog::setErrorIndex( const QValueList<uint>& list )
+{
+ d->_errorIndex = list;
+}
+
+void Catalog::setImportPluginID( const QString& id )
+{
+ d->_importID = id;
+}
+
+void Catalog::stop()
+{
+ if( d->_active )
+ emit signalStopActivity();
+}
+
+void Catalog::stopInternal()
+{
+ d->_stop = true;
+}
+
+bool Catalog::isActive()
+{
+ return d->_active;
+}
+
+void Catalog::setMimeTypes( const QString& mimeTypes )
+{
+ d->_mimeTypes = mimeTypes;
+}
+
+QString Catalog::mimeTypes() const
+{
+ return d->_mimeTypes;
+}
+
+void Catalog::wordCount (uint &total, uint &fuzzy, uint &untranslated) const
+{
+ total = 0;
+ fuzzy = 0;
+ untranslated = 0;
+
+ QRegExp separator( "[ \n\t]+" );
+
+ for ( QValueVector<CatalogItem>::Iterator it = d->_entries.begin();
+ it != d->_entries.end(); ++it)
+ {
+ // find out the number of words for this message
+
+ // join all forms together
+ QString message = (*it).msgid ().join (" ");
+
+ // remove tags first
+ d->_tagExtractor->setString( message );
+ message = d->_tagExtractor->plainString(false);
+
+ QStringList words = QStringList::split ( separator, message );
+
+ total += words.count();
+
+ if ( (*it).isFuzzy() )
+ fuzzy += words.count();
+ else if ( (*it).isUntranslated() )
+ untranslated += words.count();
+ }
+}
+
+#include "catalog.moc"
+
+// kate: space-indent on; indent-width 4; replace-tabs on;
diff --git a/kbabel/common/catalog.h b/kbabel/common/catalog.h
new file mode 100644
index 00000000..db47c48b
--- /dev/null
+++ b/kbabel/common/catalog.h
@@ -0,0 +1,698 @@
+/*****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2001-2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef CATALOG_H
+#define CATALOG_H
+
+#include "pluralforms.h"
+#include "itempart.h"
+#include "msgfmt.h"
+#include "poinfo.h"
+#include "catalogfileplugin.h"
+#include "kbproject.h"
+
+#include <qptrlist.h>
+#include <qvaluevector.h>
+#include <kdemacros.h>
+#include <kstandarddirs.h>
+
+class KDataTool;
+class QString;
+class QTextStream;
+class KFileInfo;
+class QTextCodec;
+class QFile;
+class KDataTool;
+class KURL;
+
+namespace KBabel
+{
+
+class CatalogView;
+class EditCommand;
+class FindOptions;
+class CatalogItem;
+class IdentitySettings;
+class MiscSettings;
+class SaveSettings;
+class TagSettings;
+
+class CatalogPrivate;
+
+/**
+* This struct represents a position in a catalog.
+* A position is a tuple (index,pluralform,textoffset).
+*
+* @short Structure, that represents a position in a catalog.
+* @author Matthias Kiefer <matthias.kiefer@gmx.de>
+* @author Stanislav Visnovsky <visnovsky@kde.org>
+*/
+struct DocPosition
+{
+ DocPosition( ) : offset(0), part(UndefPart), item(0), form(0) { }
+ uint offset;
+
+ Part part;
+ uint item;
+ uint form;
+};
+
+/**
+* This struct represents an entry in diff-algorithm sresults.
+*
+* @short Structure, that represents a diff result.
+*/
+struct DiffEntry
+{
+ QString msgid;
+ QString msgstr;
+};
+
+/**
+* This class represents a catalog, saved in a po-file.
+* It has the ability to load from and save to a po-file.
+* Also it defines all necessary functions to set and get the entries
+*
+* @short Class, that represents a translation catalog(po-file)
+* @author Matthias Kiefer <matthias.kiefer@gmx.de>
+*/
+class KDE_EXPORT Catalog : public QObject
+{
+ Q_OBJECT
+
+public:
+ enum DiffResult{DiffOk, DiffNotFound, DiffNeedList};
+
+ /**
+ * reads header information from the file and searches for charset
+ * information.
+ * @param gettextHeader text containing gettext headers
+ *
+ * @return Codec for found charset or 0, if no information has been found
+ */
+ static QTextCodec* codecForFile(QString gettextHeader);
+
+ static PoInfo headerInfo(const CatalogItem headerItem);
+
+ /**
+ * A constructor for an empty message catalog.
+ * @param parent parent @ref QObject for this catalog
+ * @param name unique name for this object
+ * @param configFile configuration file to read config from
+ */
+ Catalog(QObject* parent=0, const char* name=0, QString projectFile = QString() );
+
+ /**
+ * Deprecated. A copy constructor. Do not use since each Catalog registers
+ * its views and there should be no more than one Catalog for a given file.
+ */
+ Catalog(const Catalog&);
+ virtual ~Catalog();
+
+ /**
+ * Get the message context for a given message.
+ *
+ * @param index index of the requested message
+ * @return context for the given message
+ */
+ QString msgctxt(uint index) const;
+
+ /**
+ * Get list of texts for a given message in original language. Each entry in the list
+ * represents a single singular/plural form.
+ *
+ * @param index index of the requested message
+ * @param noNewLines set true if the new lines should be eliminated in result
+ * (useful for searching etc)
+ * @return list of singular/plural forms of the original text
+ */
+ QStringList msgid(uint index, const bool noNewlines=false) const;
+
+ /**
+ * Get list of translated texts for a given message. Each entry in the list
+ * represents a single singular/plural form.
+ *
+ * @param index index of the requested message
+ * @param noNewLines set true if the new lines should be eliminated in result
+ * (useful for searching etc)
+ * @return list of translated singular/plural forms
+ */
+ QStringList msgstr(uint index, const bool noNewlines=false) const;
+
+ /**
+ * Get the comment for a given message.
+ *
+ * @param index index of the requested message
+ * @return comment for the given message
+ */
+ QString comment(uint index) const;
+
+ /**
+ * Get the context information for a given message. This works
+ * for GNU gettext PO files comments only. Finds and returns comment lines,
+ * which start with #:
+ *
+ * @param index index of the requested message
+ * @return context information found in the message comment
+ * @deprecated
+ */
+ QString context(uint index) const KDE_DEPRECATED;
+
+ /**
+ * Get the header for the current file.
+ *
+ * @return @ref CatalogItem representing the header
+ */
+ CatalogItem header() const;
+
+ /**
+ * Get the name and e-mail address of the last translator of the current file.
+ *
+ * @return string representation of the name and e-mail address
+ */
+ QString lastTranslator() const;
+
+ /**
+ * @return The list of obsolete entries. These cannot be changed at
+ * all and are stored for import/export purposes.
+ */
+ QValueList<CatalogItem> obsoleteEntries() const;
+
+ /**
+ * @return The index of the item, that has the msgid id.
+ * If no item is found, -1 is returned.
+ */
+ int indexForMsgid(const QString& id) const;
+
+ /** @return a list of tags in entry #index */
+ QStringList tagList(uint index);
+
+ /** @return a list of arguments in entry #index */
+ QStringList argList(uint index);
+
+ /**
+ * @return the list of errors found for a given item index
+ * @param index index of the item to check
+ */
+ QStringList itemStatus(uint index);
+
+ /**
+ * @return the list of errors found for a given item index
+ * @param index index of the item to check
+ * @param recheck flag, if the item status should be checked now
+ * @param whatToCheck what checks to do (a list of tools to be used
+ */
+ QStringList itemStatus(uint index, bool recheck, QPtrList<KDataTool> whatToCheck);
+
+ /**
+ * replaces msgstr in catalog item at index index with msgstr
+ * returns true, if untranslated status changed
+ */
+ //bool setMsgstr(uint index,QString msgstr);
+ /**
+ * replaces comment in catalog item at index index with comment
+ * returns true, if fuzzy status changed
+ */
+ //bool setComment(uint index,QString comment);
+ /**
+ * replaces header with given String
+ * @return false if the header is not valid
+ */
+ bool setHeader(CatalogItem header);
+
+ /** removes string ", fuzzy" from comment */
+ void removeFuzzyStatus(uint index);
+
+ /** sets or unsets fuzzy status of entry index */
+ void setFuzzy(uint index, bool on);
+
+ /**
+ * used for session managment when modified file is
+ * saved in a temp file
+ */
+ void setCurrentURL(const KURL& url);
+ /**
+ * @return URL currently represented by the catalog
+ */
+ KURL currentURL() const;
+
+ /**
+ * @return package name for the current catalog
+ */
+ QString packageName() const;
+ /**
+ * @return directory for the package of the current catalog
+ */
+ QString packageDir() const;
+ /**
+ * @return package name and directory for the current catalog
+ */
+ QString package() const;
+
+ /**
+ * Setup the package for the catalog. It tries to parse the
+ * package and split it to name and directory
+ * @param package the name and directory to be set as package
+ */
+ void setPackage(const QString& package);
+
+ /**
+ * @return encoding for the current catalog
+ */
+ QString encoding() const;
+
+ /**
+ * opens file url by using KDE's network downlad and calls
+ * openFile with a local filename
+ */
+ ConversionStatus openURL(const KURL& url, const QString& package=QString::null);
+
+ /**
+ * opens file openURL by using KDE's network downlad and calls
+ * openFile with a local filename
+ * sets current URL to saveURL
+ */
+ ConversionStatus openURL(const KURL& openURL, const KURL& saveURL, const QString& package=QString::null);
+
+ /** save the file under the old filename */
+ ConversionStatus saveFile();
+ /** saves the file under a new filename */
+ ConversionStatus saveFileAs(const KURL& url,bool overwrite=false);
+
+ /**
+ * saves the current catalog in a temporary file and
+ * returns the name and path of the file.
+ */
+ QString saveTempFile();
+
+ /**
+ * @return extra data for the catalog as set by the import filter
+ */
+ QStringList catalogExtraData() const;
+ /**
+ * @return ID string of the used import filter
+ */
+ QString importPluginID() const;
+ /**
+ * @return list of MIME types (separated by comma) this catalog
+ * can be viewed as. It is set by the used import filter.
+ */
+ QString mimeTypes() const;
+ /**
+ * @return the file codec used for the current catalog
+ */
+ QTextCodec* fileCodec() const;
+
+ /**
+ * Check syntax of the GNU gettext PO file using 'msgfmt'.
+ *
+ * @param output the result as returned by msgfmt
+ * @param clearError should the errors be cleared before running msgfmt
+ * @return the file codec used for the current catalog
+ */
+ Msgfmt::Status checkSyntax(QString& output, bool clearErrors=true);
+
+ /**
+ * checks using an external tool. The tool must provide the "validate" command
+ * with the datatype expected to be CatalogItem *. The MIME type
+ * is application/x-kbabel-catalogitem.
+ */
+ bool checkUsingTool(KDataTool* tool, bool clearErrors=true);
+
+ /**
+ * modifies catalog by applying an external tool on all items. The tool must provide the "validate" command
+ * with the datatype expected to be CatalogItem *. The MIME type
+ * is application/x-kbabel-catalogitem.
+ */
+ void modifyUsingTool(KDataTool* tool, const QString& command);
+
+ /**
+ * Returns true, if there is an ongoing activity, such as load/save
+ */
+ bool isActive();
+
+ /**
+ * Stop the current activity, for example load/save or validation
+ */
+ void stop();
+
+ /** closes the file and deletes all entries */
+ void clear();
+
+ /** @return whether the catalog has been modified since the last save */
+ bool isModified() const;
+ /** sets modified flag */
+ void setModified(bool flag);
+
+ /** @return whether the catalog is read-only */
+ bool isReadOnly() const;
+
+ /** set if file is generated from a docbook source file (with xml2pot) */
+ bool isGeneratedFromDocbook() const;
+
+ /** @return current number of entries */
+ uint numberOfEntries() const;
+ /** @return current number of fuzzies */
+ uint numberOfFuzzies() const;
+ /** @return current number of untranslated entries */
+ uint numberOfUntranslated() const;
+
+ /** returns the number of words total, in fuzzy and in untranslated messages */
+ void wordCount (uint &total, uint &fuzzy, uint &untranslated) const;
+
+ bool hasFuzzyInFront(uint index) const;
+ bool hasFuzzyAfterwards(uint index) const;
+ bool hasUntranslatedInFront(uint index) const;
+ bool hasUntranslatedAfterwards(uint index) const;
+ bool hasErrorInFront(uint index) const;
+ bool hasErrorAfterwards(uint index) const;
+ bool isFuzzy(uint index) const;
+ bool isUntranslated(uint index) const;
+ /** @return whether the entry has an error
+ * @param index index of the queried entry
+ * @param pos position of the error (currently only form is filled)
+ */
+ bool hasError(uint index, DocPosition& pos) const;
+ /** @return type of plural forms for the given entry
+ * @param index index of the queried entry
+ */
+ PluralFormType pluralForm(uint index) const;
+
+ /** @return type of plural forms this file uses.
+ */
+ PluralFormType pluralFormType() const;
+
+ /** @return number of the plural forms for a given entry
+ * @param index index of the queried entry
+ */
+ int numberOfPluralForms(uint index) const;
+
+ /**
+ * returns the expected number of plural forms
+ */
+ int defaultNumberOfPluralForms() const;
+
+ /**
+ * returns index of next fuzzy entry behind startIndex
+ * -1 if there is no entry behind. Further, it fills the
+ * pos parameter with correct index and sets the form to 0.
+ */
+ int nextFuzzy(uint startIndex, DocPosition &pos) const;
+ /**
+ * returns index of previous fuzzy entry before startIndex
+ * -1 if there is no entry before. Further, it fills the
+ * pos parameter with correct index and sets the form to 0.
+ */
+ int prevFuzzy(uint startIndex, DocPosition &pos) const;
+ /**
+ * returns index of next untranslated entry behind startIndex
+ * -1 if there is no entry behind. Further, it fills the
+ * pos parameter with correct index and the form.
+ */
+ int nextUntranslated(uint startIndex, DocPosition &pos) const;
+ /**
+ * returns index of previous untranslated entry before startIndex
+ * -1 if there is no entry before. Further, it fills the
+ * pos parameter with correct index and the form.
+ */
+ int prevUntranslated(uint startIndex, DocPosition &pos) const;
+ /**
+ * returns index of next error entry behind startIndex
+ * -1 if there is no entry behind
+ */
+ int nextError(uint startIndex, DocPosition &pos) const;
+ /**
+ * returns index of previous error entry before startIndex
+ * -1 if there is no entry before
+ */
+ int prevError(uint startIndex, DocPosition &pos) const;
+
+ /**
+ * returns the header with Information updated, but does _not_ change
+ * the header in the catalog
+ */
+ CatalogItem updatedHeader(CatalogItem oldHeader, bool usePrefs=true) const;
+
+ /** read settings from the apps config file/project */
+ void readPreferences();
+ /** save settings to the apps config file/project */
+ void savePreferences();
+
+ void useProject(Project::Ptr project);
+ Project::Ptr project() const;
+
+ SaveSettings saveSettings() const;
+ IdentitySettings identitySettings() const;
+ MiscSettings miscSettings() const;
+ TagSettings tagSettings() const;
+
+ /**
+ * reads the header from QTextstream and puts it in header
+ * I made it static to be able to use this function for
+ * the search in po-files. This way, I can easily find the first
+ * catalog entry in the textstream
+ */
+// static ConversionStatus readHeader(QTextStream& stream,CatalogItem& header);
+
+
+ void registerView(CatalogView* view);
+ void removeView(CatalogView* view);
+ bool hasView() const;
+ bool isLastView() const;
+
+ bool isUndoAvailable();
+ bool isRedoAvailable();
+ /**
+ * undo the last edit command
+ * @return the index of the item, which was modified or -1, if no undo available
+ */
+ int undo();
+ /**
+ * redo the last undo command
+ * @return the index of the item, which was modified or -1, if no redo available
+ */
+ int redo();
+
+ /**
+ * finds next occurence of searchstring using opts, starting at pos.
+ * @param pos starting position and if successful contains position
+ * of found string.
+ * @param len contains len of found string
+ * @ return true, if a string was found. false, if end was reached
+ */
+ bool findNext(const FindOptions* opts, DocPosition& pos, int& len);
+ /**
+ * finds previous occurence of searchstring using opts, starting at pos.
+ * @param pos starting position and if successful contains position
+ * of found string.
+ * @param len contains len of found string
+ * @ return true, if a string was found. false, if begin was reached
+ */
+ bool findPrev(const FindOptions* opts, DocPosition& pos, int& len);
+
+ /**
+ * Remove the index from the error list
+ * @param index index to be removed
+ */
+ void removeFromErrorList(uint index);
+
+ /**
+ * tries to find a corresponding entry for entry entry
+ * from the list of old messages and calculates the diff for it
+ */
+ DiffResult diff(uint entry, QString* result);
+
+ /**
+ * sets a list of entries to generate a diff from
+ */
+ void setDiffList( const QValueList<DiffEntry>& );
+
+ /**
+ * @return the contents of this catalog as list for diffs
+ */
+ QValueList<DiffEntry> asDiffList();
+
+ /**
+ * @return how many plural forms are used in language lang.
+ * If nothing is found -1 is returned.
+ */
+ static int getNumberOfPluralForms(const QString& lang);
+
+public slots:
+ /**
+ * Update the save setting using this one.
+ * @param settings the new settings.
+ */
+ void setSettings(KBabel::SaveSettings settings);
+ /**
+ * Update the identity setting using this one.
+ * @param settings the new settings.
+ */
+ void setSettings(KBabel::IdentitySettings settings);
+ /**
+ * Update the miscelanous setting using this one.
+ * @param settings the new settings.
+ */
+ void setSettings(KBabel::MiscSettings settings);
+ /**
+ * Update the tag setting using this one.
+ * @param settings the new settings.
+ */
+ void setSettings(KBabel::TagSettings settings);
+
+ /**
+ * Apply the given edit command.
+ *
+ * @param cmd the command to be applied
+ * @param souce the view which applies the command
+ */
+ void applyEditCommand(EditCommand* cmd,CatalogView* source);
+ /**
+ * Convenience method. Apply a begin edit command for a given message and catalog
+ * source.
+ *
+ * @param index index of to be changed message
+ * @param part part (msgid,msgstr,comment) of to be changed message
+ * @param source the view which applies the command
+ */
+ void applyBeginCommand(uint index, Part part, CatalogView* source);
+ /**
+ * Convenience method. Apply an end edit command for a given message and catalog
+ * source.
+ *
+ * @param index index of to be changed message
+ * @param part part (msgid,msgstr,comment) of to be changed message
+ * @param source the view which applies the command
+ */
+ void applyEndCommand(uint index, Part part, CatalogView* source);
+
+private slots:
+ /** slot used for internal long-term activity */
+ void stopInternal();
+
+private:
+ /** calls @ref CatalogView::update(EditCommand*) */
+ void updateViews(EditCommand* cmd,CatalogView* view2exclude=0);
+
+ /**
+ * takes over changes, but does not change undo/redo list
+ */
+ void processCommand(EditCommand* cmd, CatalogView* view2exclude=0, bool undo=false);
+
+ /** do the actual file write using plugin */
+ ConversionStatus writeFile(QString localfile, bool overwrite=false);
+
+ /**
+ * generates lists that contain indexes of all fuzzy and untranslated entries
+ */
+ void generateIndexLists();
+
+ /**
+ * returns value in list that is lower than parameter index
+ * or -1 if there is none
+ */
+ int findPrevInList(const QValueList<uint>& list,uint index) const;
+ /**
+ * returns value in list that is bigger than parameter index
+ * or -1 if there is none
+ */
+ int findNextInList(const QValueList<uint>& list,uint index) const;
+
+ /** returns the current date and time in the format of the users choice */
+ QString dateTime() const;
+
+ /** clear the list of all errors */
+ void clearErrorList();
+
+ /**
+ * Tries to find out how many plural forms are used in this language and
+ * sets numberOfPluralForms accordingly. If nothing is found,
+ * numberOfPLuralForms is set to -1.
+ */
+ void getNumberOfPluralForms();
+
+ // this class can fill our contents
+ friend class CatalogImportPlugin;
+
+ /** set the flag that the catalog is generated from docbook */
+ void setGeneratedFromDocbook(const bool generated);
+ /** set the entries of the catalog */
+ void setEntries( QValueVector<CatalogItem> entries);
+ /** set the obsolete entries of the catalog */
+ void setObsoleteEntries( QValueList<CatalogItem> entries);
+ /** set extra data for the catalog as defined by import plugin */
+ void setCatalogExtraData(const QStringList& data);
+ /** set file codec for the catalog */
+ void setFileCodec(QTextCodec* codec);
+ /** set the list of import errors */
+ void setErrorIndex(const QValueList<uint>&errors);
+ /** set ID of the used import plugin */
+ void setImportPluginID(const QString& id);
+ /** set the MIME types for the current catalog as defined by import plugin */
+ void setMimeTypes(const QString& mimeTypes);
+
+private:
+ CatalogPrivate* d;
+
+signals:
+ void signalError(QString);
+ void signalResetProgressBar(QString,int);
+ void signalProgress(int);
+ void signalClearProgressBar();
+
+ void signalModified(bool);
+ /** emitted when the header was changed, maybe when saving */
+ void signalHeaderChanged();
+ /** emitted when a file was opened or saved under another name */
+ void signalFileOpened(bool readOnly);
+
+ void signalNumberOfFuzziesChanged(uint number);
+ void signalNumberOfUntranslatedChanged(uint number);
+ void signalTotalNumberChanged(uint number);
+
+ void signalSettingsChanged(KBabel::SaveSettings);
+ void signalSettingsChanged(KBabel::IdentitySettings);
+ void signalSettingsChanged(KBabel::MiscSettings);
+ void signalSettingsChanged(KBabel::TagSettings);
+
+ void signalUndoAvailable(bool);
+ void signalRedoAvailable(bool);
+
+ /** internal signal sent to external part to stop current ongoing activity*/
+ void signalStopActivity();
+};
+
+}
+
+#endif //CATALOG_H
diff --git a/kbabel/common/catalog_private.h b/kbabel/common/catalog_private.h
new file mode 100644
index 00000000..645353f3
--- /dev/null
+++ b/kbabel/common/catalog_private.h
@@ -0,0 +1,147 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2001-2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef CATALOGPRIVATE_H
+#define CATALOGPRIVATE_H
+
+#include <qintcache.h>
+#include <qobject.h>
+#include <qptrlist.h>
+#include <qstringlist.h>
+#include <qmap.h>
+#include <qvaluevector.h>
+#include <kurl.h>
+
+#include "msgfmt.h"
+#include "catalogsettings.h"
+#include "catalogitem.h"
+#include "regexpextractor.h"
+
+class QString;
+class QTextStream;
+class KFileInfo;
+class QTextCodec;
+class QFile;
+class FindOptions;
+class KConfig;
+
+namespace KBabel
+{
+
+class CatalogPrivate
+{
+
+public:
+
+ /** url of the po-file, that belongs to this catalog */
+ KURL _url;
+ QString _packageName;
+ QString _packageDir;
+
+ /** holds the entries in the catalog */
+ QValueVector<CatalogItem> _entries;
+ /** The header of the po-file. */
+ CatalogItem _header;
+
+ /** list of obsolete entries */
+ QValueList<CatalogItem> _obsoleteEntries;
+
+ /** identification string for used import filter*/
+ QString _importID;
+ QString _mimeTypes;
+
+ bool _modified;
+ bool _readOnly;
+ bool _generatedFromDocbook;
+ bool _active;
+ bool _stop;
+
+ QValueList<uint> _fuzzyIndex;
+ QValueList<uint> _untransIndex;
+ QValueList<uint> _errorIndex;
+
+ QPtrList<CatalogView> _views;
+
+ TagSettings _tagSettings;
+
+ QPtrList<EditCommand> _undoList;
+ QPtrList<EditCommand> _redoList;
+
+ QTextCodec *fileCodec;
+
+ QStringList msgidDiffList;
+ QMap< QString, QStringList > msgstr2MsgidDiffList;
+ QIntCache<QString> diffCache;
+
+ int numberOfPluralForms;
+
+ Project::Ptr _project;
+ RegExpExtractor *_tagExtractor, *_argExtractor;
+
+ QStringList _catalogExtra;
+
+ CatalogPrivate(Project::Ptr project) :
+ _packageName( QString::null ), _packageDir( QString::null ),
+ _header (project),
+ _importID( QString::null ), _mimeTypes( "text/plain" ),
+ _modified(false), _readOnly(false), _generatedFromDocbook(false),
+ _active(false), _stop(false),
+ fileCodec(0), diffCache(30,76), numberOfPluralForms(-1),
+ _project(project)
+ {
+ _entries.clear();
+ _obsoleteEntries.clear();
+ diffCache.setAutoDelete(true);
+ diffCache.clear();
+
+ _views.setAutoDelete(false);
+
+ _undoList.setAutoDelete(true);
+ _redoList.setAutoDelete(true);
+ _tagExtractor = new RegExpExtractor(QStringList());
+ _argExtractor = new RegExpExtractor(QStringList());
+
+ _catalogExtra.clear();
+ }
+
+ ~CatalogPrivate()
+ {
+ delete _tagExtractor;
+ delete _argExtractor;
+ }
+};
+
+}
+
+#endif //CATALOGPRIVATE_H
diff --git a/kbabel/common/catalogfileplugin.h b/kbabel/common/catalogfileplugin.h
new file mode 100644
index 00000000..f47e0d89
--- /dev/null
+++ b/kbabel/common/catalogfileplugin.h
@@ -0,0 +1,205 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002-2003 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+**************************************************************************** */
+#ifndef IMPORTPLUGIN_H
+#define IMPORTPLUGIN_H
+
+#include <qobject.h>
+
+#include <kdemacros.h>
+
+class QString;
+
+namespace KBabel
+{
+
+class Catalog;
+class CatalogItem;
+class CatalogImportPluginPrivate;
+class CatalogExportPluginPrivate;
+
+// ### KDE4: force OK=0
+/**
+ * Result of the conversion
+ */
+enum ConversionStatus {
+ OK,
+ NOT_IMPLEMENTED,
+ NO_FILE,
+ NO_PERMISSIONS,
+ PARSE_ERROR,
+ RECOVERED_PARSE_ERROR,
+ OS_ERROR,
+ NO_PLUGIN,
+ UNSUPPORTED_TYPE,
+ HEADER_ERROR, ///< Old name for a recovered error in header @deprecated
+ RECOVERED_HEADER_ERROR = HEADER_ERROR, ///< Header error that could be recovered @since 1.11.2 (KDE 3.5.2)
+ STOPPED,
+ BUSY,
+ NO_ENTRY_ERROR ///< The loaded catalog has not any entry! @since 1.11.2 (KDE 3.5.2)
+};
+
+/**
+* This class is the base for import plugins for catalogs.
+* It provides "transactional behavior", so the changes are stored in
+* catalog only if the import process finishes successfully.
+*
+* To use it, just subclass and redefine load() and id() methods.
+* When importing, you can use the protected methods for setting
+* the catalog. New catalog items can be added using appendCatalogItem.
+*
+* @short Base class for Catalog import plugins
+* @author Stanislav Visnovsky <visnovsky@kde.org>
+*/
+class KDE_EXPORT CatalogImportPlugin: public QObject
+{
+ Q_OBJECT
+
+public:
+ CatalogImportPlugin(QObject* parent, const char* name);
+ virtual ~CatalogImportPlugin();
+
+ /**
+ * Load the file and fill the corresponding catalog. The file
+ * is considered to be of @ref mimetype MIME type.
+ *
+ * @param file local file name to be opened
+ * @param mimetype the MIME type is should be handled as
+ * @param catalog the catalog to be filled
+ * @return result of the operation
+ */
+ ConversionStatus open(const QString& file, const QString& mimetype, Catalog* catalog);
+
+ /**
+ * Reimplement this method to load the local file passed as an argument.
+ * Throughout the run, you can use the protected methods for setting
+ * the contents of the resulting catalog.
+ * This method must call \see setMimeTypes to setup correct MIME types
+ * for the loaded file. Also, it should use \see isStopped to
+ * abort loading and the signals for providing user feedback.
+ * @param file file to be loaded
+ * @param mimetype the expected MIME type (the type used for plugin selection
+ */
+ virtual ConversionStatus load(const QString& file, const QString& mimetype) = 0;
+ /**
+ * Reimplement this method to return unique identification of your plugin
+ */
+ virtual const QString id() = 0;
+
+ /** @return the list of all available MIME types for which there
+ * is a import plugin.
+ */
+ static QStringList availableImportMimeTypes();
+
+public slots:
+ /** stop the current operation */
+ void stop();
+
+protected:
+ /** Append a new catalog item, either as normal or as an obsolete one
+ * @param item the new item
+ * @param obsolete flag that the item is obsolete
+ */
+ void appendCatalogItem( const CatalogItem& item, const bool obsolete = false );
+
+ /** set flag that the file is generated from DocBook */
+ void setGeneratedFromDocbook(const bool fromDocbook);
+ /** set the list of parse error indexes */
+ void setErrorIndex(const QValueList<uint>& errors);
+ /** set the file codec */
+ void setFileCodec(QTextCodec* codec);
+
+ /** set extra data for the catalog, which can't be stored in
+ * @ref CatalogItem. The format can be arbitrary */
+ void setCatalogExtraData( const QStringList& data );
+ /** set the header catalog item */
+ void setHeader( const CatalogItem& header );
+ /** set the MIME types which can be used for this catalog */
+ void setMimeTypes( const QString& catalog );
+
+ /** start a new transaction. You should never call this method. */
+ void startTransaction();
+ /** commit the data in the current transaction. You should never call this method. */
+ void commitTransaction();
+
+ /** Flag, whether the operation should be stopped immediately.*/
+ bool isStopped() const;
+
+signals:
+ /** Signal start of the operation */
+ void signalResetProgressBar(QString,int);
+ /** Signal progress of the operation */
+ void signalProgress(int);
+ /** Signal end of the operation */
+ void signalClearProgressBar();
+
+private:
+ CatalogImportPluginPrivate* d;
+};
+
+
+/**
+* This class is the base for export plugins for catalogs.
+*
+* To use it, just subclass and redefine the save() method.
+*
+* @short Base class for Catalog export plugins
+* @author Stanislav Visnovsky <visnovsky@kde.org>
+*/
+class KDE_EXPORT CatalogExportPlugin: public QObject
+{
+ Q_OBJECT
+
+public:
+ CatalogExportPlugin(QObject* parent, const char* name);
+ virtual ~CatalogExportPlugin();
+ virtual ConversionStatus save(const QString& file, const QString& mimetype, const Catalog* catalog) = 0;
+
+ static QStringList availableExportMimeTypes();
+
+public slots:
+ void stop();
+
+protected:
+ bool isStopped() const;
+
+signals:
+ void signalResetProgressBar(QString,int);
+ void signalProgress(int);
+ void signalClearProgressBar();
+
+private:
+ CatalogExportPluginPrivate* d;
+};
+
+}
+
+#endif
diff --git a/kbabel/common/catalogitem.cpp b/kbabel/common/catalogitem.cpp
new file mode 100644
index 00000000..ced02e8c
--- /dev/null
+++ b/kbabel/common/catalogitem.cpp
@@ -0,0 +1,521 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer <matthias.kiefer@gmx.de>
+ 2002 by Stanislav Visnovsky <visnovsky@nenya.ms.mff.cuni.cz>
+ Copyright (C) 2006 by Nicolas GOUTTE <goutte@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include "catalogitem.h"
+#include "catalogitem_private.h"
+#include "editcmd.h"
+#include "resources.h"
+#include "libgettext/pofiles.h"
+#include "libgettext/tokens.h"
+
+#include "regexpextractor.h"
+
+#include <qtextstream.h>
+#include <qtextcodec.h>
+#include <qdom.h>
+
+using namespace KBabel;
+
+CatalogItem::CatalogItem(Project::Ptr project)
+{
+ d=0;
+ clear();
+ d->_project = project;
+}
+
+CatalogItem::CatalogItem(const CatalogItem& item)
+{
+ d=0;
+ clear();
+ *d=*(item.d);
+}
+
+CatalogItem::~CatalogItem()
+{
+ delete d;
+}
+
+QString CatalogItem::comment() const
+{
+ return d->_comment;
+}
+
+QString CatalogItem::msgctxt(const bool noNewlines) const
+{
+ if( noNewlines )
+ {
+ QString tmp = d->_msgctxt;
+ tmp.replace("\n", " "); // ### TODO: " " or "" ?
+ return tmp;
+ }
+ else
+ return d->_msgctxt;
+}
+
+QStringList CatalogItem::msgid(const bool noNewlines) const
+{
+ QStringList result=d->_msgid;
+ if( noNewlines )
+ {
+ result.gres( "\n", "" );
+ }
+ return result;
+}
+
+QStringList CatalogItem::msgstr(const bool noNewlines) const
+{
+ QStringList result=d->_msgstr;
+ if( noNewlines )
+ {
+ result.gres( "\n", "" );
+ }
+ return result;
+}
+
+QStringList CatalogItem::msgstrAsList(int nr) const
+{
+ QString str;
+ if(d->_gettextPluralForm && nr > 0)
+ {
+ QStringList::ConstIterator it = d->_msgstr.at(nr);
+ if(it != d->_msgstr.end())
+ {
+ str = *it;
+ }
+ else
+ {
+ kdDebug(KBABEL) << "request for non existing plural form "
+ << nr << endl;
+ }
+ }
+ else
+ {
+ str = d->_msgstr.first();
+ }
+
+ QStringList list=QStringList::split("\n",str);
+
+ if(str.left(1)=="\n")
+ list.prepend("");
+
+ if(list.isEmpty())
+ list.append("");
+
+ return list;
+}
+
+bool CatalogItem::isValid() const
+{
+ return d->_valid;
+}
+
+void CatalogItem::setMsgctxt(QString msg)
+{
+ d->_msgctxt=msg;
+}
+
+void CatalogItem::setMsgid(QString msg)
+{
+ d->_msgid=msg;
+}
+
+void CatalogItem::setMsgid(QStringList msg)
+{
+ d->_msgid=msg;
+}
+
+void CatalogItem::setMsgstr(QString msg)
+{
+ d->_msgstr=msg;
+}
+
+void CatalogItem::setMsgstr(QStringList msg)
+{
+ d->_msgstr=msg;
+}
+
+void CatalogItem::setComment(QString com)
+{
+ d->_comment=com;
+}
+
+void CatalogItem::setGettextPluralForm( bool _gettextPlural )
+{
+ d->_gettextPluralForm = _gettextPlural;
+}
+
+QStringList CatalogItem::errors() const
+{
+ return d->_errors;
+}
+
+QStringList CatalogItem::tagList( RegExpExtractor& te)
+{
+ if(!d->_haveTagList)
+ {
+ // FIXME: should care about plural forms in msgid
+ te.setString(msgid(true).first());
+ d->_tagList = QStringList(te.matches());
+ d->_haveTagList = true;
+ }
+
+ return d->_tagList;
+}
+
+QStringList CatalogItem::argList( RegExpExtractor& te)
+{
+ if(!d->_haveArgList)
+ {
+ // FIXME: should care about plural forms in msgid
+ te.setString(msgid(true).first());
+ d->_argList = QStringList(te.matches());
+ }
+
+ return d->_argList;
+}
+
+
+bool CatalogItem::isFuzzy() const
+{
+ return d->_comment.find( QRegExp(",\\s*fuzzy") ) != -1;
+}
+
+bool CatalogItem::isCformat() const
+{
+ // Allow "possible-c-format" (from xgettext --debug) or "c-format"
+ // Note the regexp (?: ) is similar to () but it does not capture (so it is faster)
+ return d->_comment.find( QRegExp(",\\s*(?:possible-)c-format") ) == -1;
+}
+
+bool CatalogItem::isNoCformat() const
+{
+ return d->_comment.find( QRegExp(",\\s*no-c-format") ) == -1;
+}
+
+bool CatalogItem::isQtformat() const
+{
+ return d->_comment.find( QRegExp(",\\s*qt-format") ) == -1;
+}
+
+bool CatalogItem::isNoQtformat() const
+{
+ return d->_comment.find( QRegExp(",\\s*no-qt-format") ) == -1;
+}
+
+bool CatalogItem::isUntranslated() const
+{
+ return d->_msgstr.first().isEmpty();
+}
+
+PluralFormType CatalogItem::pluralForm() const
+{
+ if( d->_gettextPluralForm )
+ return Gettext;
+ if( d->_msgid.first().startsWith( "_n: " ) )
+ return KDESpecific;
+ else
+ return NoPluralForm;
+}
+
+int CatalogItem::totalLines() const
+{
+ int lines=0;
+ if(!d->_comment.isEmpty())
+ {
+ lines = d->_comment.contains('\n')+1;
+ }
+ int msgctxtLines=0;
+ if(!d->_msgctxt.isEmpty())
+ {
+ msgctxtLines=d->_msgctxt.contains('\n')+1;
+ }
+ int msgidLines=0;
+ QStringList::ConstIterator it;
+ for(it=d->_msgid.begin(); it != d->_msgid.end(); ++it)
+ {
+ msgidLines += (*it).contains('\n')+1;
+ }
+ int msgstrLines=0;
+ for(it=d->_msgstr.begin(); it != d->_msgstr.end(); ++it)
+ {
+ msgstrLines += (*it).contains('\n')+1;
+ }
+
+ if(msgctxtLines>1)
+ msgctxtLines++;
+ if(msgidLines>1)
+ msgidLines++;
+ if(msgstrLines>1)
+ msgstrLines++;
+
+ lines+=( msgctxtLines+msgidLines+msgstrLines );
+
+ return lines;
+}
+
+
+void CatalogItem::setSyntaxError(bool on)
+{
+ if(on && !d->_errors.contains("syntax error"))
+ d->_errors.append("syntax error");
+ else
+ d->_errors.remove("syntax error");
+}
+
+QPtrList<EditCommand> CatalogItem::removeFuzzy(bool doIt)
+{
+ QPtrList<EditCommand> editList;
+ editList.setAutoDelete(false);
+
+ QString comment=d->_comment;
+
+ if(isFuzzy())
+ {
+ EditCommand *cmd;
+ QRegExp fuzzyStr(",\\s*fuzzy");
+
+ int offset;
+ offset=comment.find(fuzzyStr);
+ while(offset>=0)
+ {
+ cmd = new DelTextCmd(offset,fuzzyStr.cap(),0);
+ cmd->setPart(Comment);
+ editList.append(cmd);
+
+ comment.remove(offset,fuzzyStr.cap().length());
+
+ offset=comment.find(fuzzyStr,offset+1);
+ }
+
+ // remove empty comment lines
+ if( comment.contains( QRegExp("^#\\s*$") ))
+ {
+ cmd = new DelTextCmd(0,comment,0);
+ cmd->setPart(Comment);
+ editList.append(cmd);
+
+ comment="";
+ }
+ if( comment.contains( QRegExp("\n#\\s*$") ))
+ {
+ offset=comment.find( QRegExp("\n#\\s*$") );
+ while(offset>=0)
+ {
+ cmd = new DelTextCmd(offset,comment.mid(offset),0);
+ cmd->setPart(Comment);
+ editList.append(cmd);
+
+ comment.remove(offset,comment.length()-offset);
+
+ offset=comment.find( QRegExp("\n#\\s*$"), offset+1 );
+ }
+ }
+ if( comment.contains( QRegExp("\n#\\s*\n") ))
+ {
+ offset=comment.find( QRegExp("\n#\\s*\n") )+1;
+ while(offset>=0)
+ {
+ int endIndex=comment.find("\n",offset)+1;
+
+ cmd = new DelTextCmd(offset,comment.mid(offset,endIndex-offset),0);
+ cmd->setPart(Comment);
+ editList.append(cmd);
+
+ comment.remove(offset,endIndex-offset);
+
+ offset=comment.find( QRegExp("\n#\\s*\n"), offset+1 );
+ }
+ }
+
+ if(doIt)
+ d->_comment=comment;
+
+ }
+
+ return editList;
+}
+
+
+
+QPtrList<EditCommand> CatalogItem::addFuzzy(bool doIt)
+{
+ QPtrList<EditCommand> editList;
+ editList.setAutoDelete(false);
+
+
+ if(!isFuzzy())
+ {
+ EditCommand *cmd;
+ int offset=d->_comment.length();
+
+ QString addStr;
+ if(offset > 0 && d->_comment[offset-1] != '\n')
+ {
+ addStr='\n';
+ }
+ addStr+="#, fuzzy";
+
+ cmd = new InsTextCmd(offset,addStr,0);
+ cmd->setPart(Comment);
+ editList.append(cmd);
+
+
+ if(doIt)
+ d->_comment+=addStr;
+ }
+
+ return editList;
+}
+
+
+void CatalogItem::processCommand(EditCommand* cmd, bool undo)
+{
+ kdDebug(KBABEL) << "CatalogItem::processCommand" << endl;
+ if(cmd->terminator()!=0)
+ return;
+
+ DelTextCmd* delcmd = (DelTextCmd*) cmd;
+
+ bool ins = true;
+ if (delcmd->type() == EditCommand::Delete )
+ ins = undo;
+ else if (delcmd->type() == EditCommand::Insert )
+ ins = !undo;
+ else
+ {
+ kdDebug(KBABEL) << "what kind of edit command is this?" << endl;
+ return;
+ }
+
+ if ( ins )
+ {
+ if(delcmd->part()==Msgstr)
+ {
+ if(delcmd->pluralNumber >= (int)d->_msgstr.count() )
+ {
+ for( uint i = d->_msgstr.count() ; i < (uint)(delcmd->pluralNumber+1) ; i++ )
+ d->_msgstr.append( "" );
+ }
+
+ (*(d->_msgstr).at(delcmd->pluralNumber)).insert(delcmd->offset,delcmd->str);
+ }
+ else if(delcmd->part()==Comment)
+ {
+ d->_comment.insert(delcmd->offset,delcmd->str);
+ }
+ }
+ else
+ { // del
+ if(delcmd->part()==Msgstr)
+ {
+ if(delcmd->pluralNumber >= (int)d->_msgstr.count() )
+ {
+ for( uint i = d->_msgstr.count() ; i < (uint)(delcmd->pluralNumber+1) ; i++ )
+ d->_msgstr.append( "" );
+ }
+
+ (*(d->_msgstr).at(delcmd->pluralNumber)).remove(delcmd->offset,delcmd->str.length());
+ }
+ else if(delcmd->part()==Comment)
+ {
+ d->_comment.remove(delcmd->offset,delcmd->str.length());
+ }
+ }
+}
+
+
+void CatalogItem::clear()
+{
+ if( !d ) d = new CatalogItemPrivate();
+ else {
+ d->_msgid.clear();
+ d->_msgstr.clear();
+ d->_errors.clear();
+
+ d->_tagList.clear();
+ d->_argList.clear();
+ }
+ d->_comment="";
+ d->_msgctxt="";
+ d->_valid=true;
+ d->_gettextPluralForm=false;
+ d->_haveTagList=false;
+ d->_haveArgList=false;
+
+ d->_msgid.append("");
+ d->_msgstr.append("");
+}
+
+void CatalogItem::operator=(const CatalogItem& rhs)
+{
+ d->_comment = rhs.d->_comment;
+ d->_msgctxt = rhs.d->_msgctxt;
+ d->_msgid = rhs.d->_msgid;
+ d->_msgstr = rhs.d->_msgstr;
+ d->_valid = rhs.d->_valid;
+ d->_errors = rhs.d->_errors;
+ d->_gettextPluralForm = rhs.d->_gettextPluralForm;
+}
+
+QString CatalogItem::nextError() const
+{
+ return d->_errors.first();
+}
+
+void CatalogItem::clearErrors()
+{
+ d->_errors.clear();
+}
+
+void CatalogItem::appendError(const QString& error )
+{
+ if( !d->_errors.contains( error ) )
+ d->_errors.append(error);
+}
+
+void CatalogItem::removeError(const QString& error )
+{
+ d->_errors.remove(error);
+}
+
+Project::Ptr CatalogItem::project() const
+{
+ return d->_project;
+}
+
+void CatalogItem::setProject( Project::Ptr project )
+{
+ d->_project = project;
+}
+
+// kate: space-indent on; indent-width 4; replace-tabs on;
diff --git a/kbabel/common/catalogitem.h b/kbabel/common/catalogitem.h
new file mode 100644
index 00000000..91e6cc25
--- /dev/null
+++ b/kbabel/common/catalogitem.h
@@ -0,0 +1,220 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer <matthias.kiefer@gmx.de>
+ 2002-2003 by Stanislav Visnovsky <visnovsky@kde.org>
+ Copyright (C) 2006 by Nicolas GOUTTE <goutte@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef CATALOGITEM_H
+#define CATALOGITEM_H
+
+#include <qstringlist.h>
+#include <qptrlist.h>
+
+#include "pluralforms.h"
+#include "editcmd.h"
+#include "catalogfileplugin.h"
+#include "kbproject.h"
+
+class QTextStream;
+class GettextFlexLexer;
+
+namespace KBabel
+{
+
+class RegExpExtractor;
+class CatalogItemPrivate;
+
+/**
+* This class represents an entry in a catalog.
+* It contains the comment, the Msgid and the Msgstr.
+* It defines some functions to query the state of the entry
+* (fuzzy, untranslated, cformat).
+*
+* @short Class, representing an entry in a catalog
+* @author Matthias Kiefer <matthias.kiefer@gmx.de>
+*/
+class KDE_EXPORT CatalogItem
+{
+
+public:
+ /** Constructor for empty item*/
+ CatalogItem(Project::Ptr project = 0);
+ /** Copy constructor */
+ CatalogItem(const CatalogItem&);
+ /** Destructor */
+ ~CatalogItem();
+
+ /**
+ * returns true, if the translation is fuzzy, this means
+ * if the string ", fuzzy" is contained in the comment
+ */
+ bool isFuzzy() const;
+
+ /**
+ * returns true, if the translation in c-format, this means
+ * if the string ", c-format" is contained in the comment
+ * @since 1.11.2 (KDE 3.5.2) not only "c-format" is supported but also
+ * "possible-c-format" (from the debug parameter of xgettext)
+ */
+ bool isCformat() const;
+
+ /**
+ * returns true, if the string ", no-c-format" is contained in the comment
+ */
+ bool isNoCformat() const;
+
+ /**
+ * returns true, if the translation in qt-format, this means
+ * if the string ", qt-format" is contained in the comment
+ * @since 1.11.2 (KDE 3.5.2)
+ */
+ bool isQtformat() const;
+
+ /**
+ * returns true,
+ * if the string ", no-qt-format" is contained in the comment
+ * @since 1.11.2 (KDE 3.5.2)
+ */
+ bool isNoQtformat() const;
+
+ /**
+ * returns true, if the Msgid is untranslated, this means the
+ * Msgstr is empty
+ */
+ bool isUntranslated() const;
+
+ /**
+ * @return type of the plural form, is any
+ */
+ PluralFormType pluralForm() const;
+
+ bool isValid() const;
+
+ void setSyntaxError(bool);
+
+ /** returns the number of lines, the entry will need in a file */
+ int totalLines() const;
+
+ /**
+ * removes the string ", fuzzy" from the comment
+ * @param doIt if false, the comment is not changed, just the
+ * commands for doing it are calculated
+ */
+ QPtrList<EditCommand> removeFuzzy(bool doIt=true);
+
+ /**
+ * adds the string ", fuzzy" to the comment
+ * @param doIt if false, the comment is not changed, just the
+ * commands for doing it are calculated
+ */
+ QPtrList<EditCommand> addFuzzy(bool doIt=true);
+
+
+ /** cleares the item */
+ void clear();
+
+
+ /** returns the comment of this entry */
+ QString comment() const;
+ /** returns the msgctxt of this entry */
+ QString msgctxt(const bool noNewlines = false) const;
+ /** returns the msgid of the entry */
+ QStringList msgid(const bool noNewlines = false) const;
+ /** returns the msgstr of the entry */
+ QStringList msgstr(const bool noNewlines = false) const;
+
+ /**
+ * @param pluralNr If this item is a gettext plural form item,
+ * it returns the plural form number pluralNr, else always the msgstr
+ * is returned
+ * @return the msgstr as list
+ */
+ QStringList msgstrAsList(int pluralNr=0) const;
+
+ void setComment(QString com);
+ void setMsgctxt(QString msg);
+ void setMsgid(QString msg);
+ void setMsgid(QStringList msg);
+ void setMsgstr(QString msg);
+ void setMsgstr(QStringList msg);
+
+ void setGettextPluralForm( bool _gettextPlurals );
+
+ void processCommand(EditCommand* cmd, bool undo=false);
+
+ Project::Ptr project() const;
+
+
+ /** @return a list of tags in the msgid */
+ QStringList tagList( RegExpExtractor& tagExtractor );
+
+ /** @return a list of args in the msgid */
+ QStringList argList( RegExpExtractor& argExtractor);
+
+ /**
+ * @return the list of all errors of this item
+ */
+ QStringList errors() const;
+
+ QString nextError() const;
+ void clearErrors();
+ void removeError(const QString& error);
+ void appendError(const QString& error);
+
+ /**
+ * makes some sanity checks and set status accordingly
+ * @return the new status of this item
+ * @see CatalogItem::Error
+ * @param accelMarker a char, that marks the keyboard accelerators
+ * @param contextInfo a regular expression, that determines what is
+ * the context information
+ * @param singularPlural a regular expression, that determines what is
+ * string with singular and plural form
+ * @param neededLines how many lines a string with singular-plural form
+ * must have
+ */
+ int checkErrors(QChar accelMarker, const QRegExp& contextInfo
+ , const QRegExp& singularPlural, const int neededLines);
+
+
+ void operator=(const CatalogItem& rhs);
+
+private:
+ void setProject( Project::Ptr project );
+
+ friend class Catalog;
+
+private:
+ CatalogItemPrivate* d;
+};
+
+}
+
+#endif // CATALOGITEM_H
diff --git a/kbabel/common/catalogitem_private.h b/kbabel/common/catalogitem_private.h
new file mode 100644
index 00000000..15c81fc7
--- /dev/null
+++ b/kbabel/common/catalogitem_private.h
@@ -0,0 +1,90 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2002 by Stanislav Visnovsky <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef CATALOGITEMPRIVATE_H
+#define CATALOGITEMPRIVATE_H
+
+#include <qstringlist.h>
+
+namespace KBabel
+{
+
+/**
+* This class represents data for an entry in a catalog.
+* It contains the comment, the Msgid and the Msgstr.
+* It defines some functions to query the state of the entry
+* (fuzzy, untranslated, cformat).
+*
+* @short Class, representing an entry in a catalog
+* @author Matthias Kiefer <matthias.kiefer@gmx.de>
+* @author Stanislav Visnovsky <visnovsky@kde.org>
+*/
+
+class CatalogItemPrivate
+{
+
+public:
+
+ QString _comment;
+ QString _msgctxt;
+ QStringList _msgid;
+ QStringList _msgstr;
+
+ QStringList _tagList;
+ QStringList _argList;
+
+ bool _valid;
+ bool _haveTagList;
+ bool _haveArgList;
+ QStringList _errors;
+
+ /** flag, if this entry is a plural forms entry */
+ bool _gettextPluralForm;
+
+ friend class CatalogItem;
+
+ KBabel::Project::Ptr _project;
+
+ CatalogItemPrivate()
+ {
+ _comment = "";
+ _valid=false;
+ _haveTagList=false;
+ _haveArgList=false;
+ _gettextPluralForm=false;
+ }
+};
+
+}
+
+#endif // CATALOGITEMPRIVATE_H
diff --git a/kbabel/common/catalogsettings.cpp b/kbabel/common/catalogsettings.cpp
new file mode 100644
index 00000000..480f4cb9
--- /dev/null
+++ b/kbabel/common/catalogsettings.cpp
@@ -0,0 +1,258 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+**************************************************************************** */
+#include "catalogsettings.h"
+#include "kbprojectsettings.h"
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kemailsettings.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kprocess.h>
+#include <ktempfile.h>
+
+#include <stdlib.h>
+
+#include <qfile.h>
+#include <qtextcodec.h>
+#include <qregexp.h>
+
+#include <stdlib.h>
+
+using namespace KBabel;
+
+QString KBabel::charsetString(const QTextCodec *codec)
+{
+ if(codec)
+ {
+ QString encodingStr = codec->mimeName();
+ if ( encodingStr.startsWith("CP " ) )
+ encodingStr.remove( 2, 1 );
+ else if ( encodingStr.startsWith("IBM " ) )
+ encodingStr.replace( "IBM ", "CP" );
+ return encodingStr;
+ }
+ else
+ return QString::null;
+}
+
+QString KBabel::GNUPluralForms(const QString& lang)
+{
+ KTempFile infile, outfile;
+
+ QTextStream* str = infile.textStream();
+
+ *str << "# SOME DESCRIPTIVE TITLE." << endl;
+ *str << "# Copyright (C) YEAR Free Software Foundation, Inc." << endl;
+ *str << "# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR." << endl;
+ *str << "#" << endl;
+ *str << "#, fuzzy" << endl;
+ *str << "msgid \"\"" << endl;
+ *str << "msgstr \"\"" << endl;
+ *str << "\"Project-Id-Version: PACKAGE VERSION\\n\"" << endl;
+ *str << "\"POT-Creation-Date: 2002-06-25 03:23+0200\\n\"" << endl;
+ *str << "\"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n\"" << endl;
+ *str << "\"Last-Translator: FULL NAME <EMAIL@ADDRESS>\\n\"" << endl;
+ *str << "\"Language-Team: LANGUAGE <LL@li.org>\\n\"" << endl;
+ *str << "\"MIME-Version: 1.0\\n\"" << endl;
+ *str << "\"Content-Type: text/plain; charset=CHARSET\\n\"" << endl;
+ *str << "\"Content-Transfer-Encoding: ENCODING\\n\"" << endl;
+
+ infile.close();
+
+ KProcess msginit;
+
+ msginit << "msginit";
+ msginit
+ << "-l"
+ << lang
+ << "-i"
+ << infile.name()
+ << "-o"
+ << outfile.name()
+ << "--no-translator"
+ << "--no-wrap" ;
+
+ msginit.start( KProcess::Block );
+
+ QString res("");
+
+ if( msginit.normalExit() )
+ {
+ // parse out the plural form string
+ QFile f(outfile.name());
+ if( f.open (IO_ReadOnly) )
+ {
+ QTextStream str(&f);
+
+ QString line;
+ do {
+ line = str.readLine();
+
+ if( line.startsWith( "\"Plural-Forms:" ) )
+ {
+ kdDebug() << "Plural form line: " << line << endl;
+ QRegExp re( "^\"Plural-Forms: *(.*)\\\\n\"" );
+ re.search( line );
+ res = re.cap(1);
+ break;
+ }
+ } while (!str.atEnd() );
+ }
+ else
+ {
+ kdWarning() << "Cannot open the file with plural form definition" << endl;
+ }
+ }
+
+ infile.unlink();
+ outfile.unlink();
+
+ return res;
+}
+
+QString KBabel::charsetString(const int e)
+{
+ QString encodingStr;
+
+ switch(e)
+ {
+ case ProjectSettingsBase::Locale:
+ {
+ QTextCodec *codec=QTextCodec::codecForLocale();
+ if(codec)
+ encodingStr=charsetString(codec);
+ else
+ encodingStr="unknown";
+
+ break;
+ }
+ case ProjectSettingsBase::UTF8:
+ {
+ encodingStr="UTF-8";
+ break;
+ }
+ case ProjectSettingsBase::UTF16:
+ {
+ encodingStr="UTF-16";
+ break;
+ }
+ }
+
+ return encodingStr;
+}
+
+QString Defaults::Identity::authorName()
+{
+ KEMailSettings emSet;
+ return emSet.getSetting(KEMailSettings::RealName);
+}
+
+QString Defaults::Identity::authorLocalizedName()
+{
+ return authorName();
+}
+
+QString Defaults::Identity::authorEmail()
+{
+ KEMailSettings emSet;
+ return emSet.getSetting(KEMailSettings::EmailAddress);
+}
+
+QString Defaults::Identity::mailingList()
+{
+ QString lang=Defaults::Identity::languageCode();
+ int temp=lang.find("_");
+ lang=lang.left(temp);
+ return lang+"@li.org";
+}
+
+QString Defaults::Identity::languageCode()
+{
+ // first try to get the language from KDE settings
+ KLocale *locale = KGlobal::locale();
+ QString lang;
+ if(locale)
+ {
+ lang=locale->languageList().first();
+ }
+
+ if(lang.isEmpty())
+ {
+ lang=getenv("LC_ALL");
+ if(lang.isEmpty())
+ {
+ lang=getenv("LC_MESSAGES");
+ if(lang.isEmpty())
+ {
+ lang=getenv("LANG");
+ }
+ }
+ }
+
+ return lang;
+}
+
+QString Defaults::Identity::timezone()
+{
+ QString timezone=getenv("TIMEZONE");
+ if(timezone.isEmpty())
+ timezone="GMT";
+
+ return timezone;
+}
+
+QStringList Defaults::Tag::tagExpressions()
+{
+ QStringList list;
+
+ list.append("</[A-Za-z0-9\\n]+>");
+ list.append("<[A-Za-z0-9\\n]+[^>]*/?>");
+ list.append("http:\\/\\/[a-zA-Z0-9\\.\\-_/~]+");
+ list.append("mailto:[a-z0-9\\.\\-_]+@[a-z0-9\\.\\-_]+");
+ list.append("<?[a-z0-9\\.\\-_]+@[a-z0-9\\.\\-_]+>?");
+ list.append("&[a-z,A-Z,\\-,0-9,#\\.]*;");
+
+ return list;
+}
+
+QStringList Defaults::Tag::argExpressions()
+{
+ QStringList list;
+
+ list.append("%[ndioxXucsfeEgGp]");
+ list.append("%([0-9]+(\\$))?[-+'#0]?[0-9]*(.[0-9]+)?[hlL]?[dioxXucsfeEgGp]");
+ list.append("%[0-9]+");
+
+ return list;
+}
diff --git a/kbabel/common/catalogsettings.h b/kbabel/common/catalogsettings.h
new file mode 100644
index 00000000..f87ec673
--- /dev/null
+++ b/kbabel/common/catalogsettings.h
@@ -0,0 +1,176 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2001-2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+**************************************************************************** */
+#ifndef CATALOGSETTINGS_H
+#define CATALOGSETTINGS_H
+
+#include <qstring.h>
+#include <qregexp.h>
+#include <qdatetime.h>
+#include <kdemacros.h>
+
+class QTextCodec;
+class QStringList;
+
+namespace KBabel
+{
+
+struct KDE_EXPORT SaveSettings
+{
+ bool autoUpdate;
+ bool updateLastTranslator;
+ bool updateRevisionDate;
+ bool updateLanguageTeam;
+ bool updateCharset;
+ bool updateEncoding;
+
+ bool updateProject;
+ bool updateDescription;
+ QString descriptionString;
+ bool updateTranslatorCopyright;
+ int FSFCopyright;
+
+ int encoding;
+ bool useOldEncoding;
+
+ Qt::DateFormat dateFormat;
+ QString customDateFormat;
+
+ QString projectString;
+
+ bool autoSyntaxCheck;
+ bool saveObsolete;
+
+ int autoSaveDelay;
+};
+
+struct KDE_EXPORT IdentitySettings
+{
+ QString authorName;
+ QString authorLocalizedName;
+ QString authorEmail;
+ QString languageName;
+ QString languageCode;
+ QString mailingList;
+ QString timeZone;
+
+ /**
+ * The number of plural forms. If <= 0 the number is determined
+ * automatically.
+ */
+ int numberOfPluralForms;
+ /**
+ * Whether the %n argument should be always present in translation
+ */
+ bool checkPluralArgument;
+
+ QString gnuPluralFormHeader;
+};
+
+
+struct KDE_EXPORT MiscSettings
+{
+ /**
+ * The char, that marks keyboard accelerators.
+ * Default is '&' as used by Qt
+ */
+ QChar accelMarker;
+
+ /**
+ * The regular expression for what is context information.
+ * Default is "^_:.+" as used in KDE
+ */
+ QRegExp contextInfo;
+
+ /**
+ * The regular expression for strings that contain a message for
+ * singular and one for plural
+ */
+ QRegExp singularPlural;
+
+ /**
+ * The method used for compresion of email attachments. Use
+ * tar/bzip2 if true, tar/gzip if false.
+ * Default is true.
+ */
+ bool useBzip;
+
+ /**
+ * Use compression for single file attachments.
+ * Default is true.
+ */
+ bool compressSingleFile;
+};
+
+struct TagSettings
+{
+ /**
+ * A list of regular expressions defining tags
+ */
+ QStringList tagExpressions;
+ /**
+ * A list of regular expressions defining arguments
+ */
+ QStringList argExpressions;
+};
+
+KDE_EXPORT QString charsetString(const int encoding);
+KDE_EXPORT QString charsetString(const QTextCodec *codec);
+KDE_EXPORT QString GNUPluralForms(const QString& lang);
+
+namespace Defaults
+{
+ class KDE_EXPORT Identity
+ {
+ public:
+ static QString authorName();
+ static QString authorLocalizedName();
+ static QString authorEmail();
+ static QString languageCode();
+ static QString mailingList();
+ static QString timezone();
+ };
+
+ class KDE_EXPORT Tag
+ {
+ public:
+ static QStringList tagExpressions();
+ static QStringList argExpressions();
+ };
+
+}
+
+}
+
+
+#endif
diff --git a/kbabel/common/catalogview.h b/kbabel/common/catalogview.h
new file mode 100644
index 00000000..03056c43
--- /dev/null
+++ b/kbabel/common/catalogview.h
@@ -0,0 +1,64 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef CATALOGVIEW_H
+#define CATALOGVIEW_H
+
+namespace KBabel
+{
+
+class EditCommand;
+
+/**
+ * This class represents a base class for a @ref Catalog view. It declares
+ * an abstract method @ref update to be redefined by the actual
+ * view. Using this method, the catalog the view is registered for
+ * will inform the views about changes in the catalog.
+ *
+ * @short This class represents a base class for a catalog view.
+ * @author Matthias Kiefer <matthias.kiefer@gmx.de>
+ */
+class CatalogView
+{
+public:
+ /** The only method to be redefined in inherited classes.
+ * This method is called by @ref Catalog to update the view
+ * in case there are changes.
+ * @param cmd the command line performed on the catalog
+ * @param undo this is used for undo, reverse the operation
+ */
+ virtual void update(EditCommand* cmd, bool undo=false)=0;
+};
+
+}
+
+#endif // CATALOGVIEW_H
diff --git a/kbabel/common/diff.cpp b/kbabel/common/diff.cpp
new file mode 100644
index 00000000..7a54e4d3
--- /dev/null
+++ b/kbabel/common/diff.cpp
@@ -0,0 +1,465 @@
+/* **************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2001 by Matthias Kiefer <kiefer@kde.org>
+ charDiff algorithm by Wolfram Diestel <wolfram@steloj.de>
+ wordDiff algorithm by Nick Shaforostoff <shafff@ukr.net>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+************************************************************************** */
+
+#include "diff.h"
+
+#include <kdebug.h>
+
+
+LCSprinter::LCSprinter(const QStringList &s_1, const QStringList &s_2, QValueVector<LCSMarker> *b_, const uint nT_, uint index):s1(s_1),s2(s_2),b(b_),nT(nT_)
+{
+ it1=s1.begin();
+ it2=s2.begin();
+ printLCS(index);
+}
+
+void LCSprinter::printLCS(uint index)
+{
+ //fprintf(stderr,"%2d. %2d. %2d. %2d\n",(uint)(*b)[index],nT,index%nT, index);
+ if (index % nT == 0 || index < nT)
+ {
+ //original LCS algo doesnt have to deal with ins before first common
+ uint bound = index%nT;
+ for (index=0; index<bound; ++index)
+ {
+ resultString.append("<KBABELADD>");
+ resultString.append(*it2);
+ ++it2;
+ resultString.append("</KBABELADD>");
+ }
+
+ return;
+ }
+
+ if (ARROW_UP_LEFT == (*b)[index])
+ {
+ printLCS(index-nT-1);
+ resultString.append(*it1);
+ ++it1;
+ ++it2;
+ return;
+ }
+ else if (ARROW_UP == (*b)[index])
+ {
+ printLCS(index-nT);
+ resultString.append("<KBABELDEL>");
+ resultString.append(*it1);
+ ++it1;
+ resultString.append("</KBABELDEL>");
+ return;
+ }
+ else
+ {
+ printLCS(index-1);
+ resultString.append("<KBABELADD>");
+ resultString.append(*it2);
+ ++it2;
+ resultString.append("</KBABELADD>");
+ return;
+ }
+
+}
+
+
+
+QString wordDiff(const QString& str1, const QString& str2)
+{
+ //separate punctuation marks etc from words as _only_ they may have changed
+ QStringList s1, s2;
+
+ uint i=0;
+ uint j=0;
+ uint l1=str1.length();
+ uint l2=str2.length();
+ QString temp;
+ temp.reserve(16);
+ /*
+ while ( i<l1 )
+ {
+ if (str1[i]==QChar(0x003C) && (str1[i+1]==QChar(0x002F) || str1[i+1].isLetter()) ) // 0x003C="<", 0x002F="/"
+ {// skip tag
+ while(i<l1 && str1[i]!=QChar(0x003E)) temp += str1[i++];
+ if (i++ <l1) temp += QChar(0x003E);
+ s1.append(temp);
+ temp.truncate(0);
+ }
+
+ while ( i<l1 && str1[i].isLetter() )
+ {
+ temp += str1[i++];
+ }
+ if (!temp.isEmpty())
+ {
+ s1.append(temp);
+ temp.truncate(0);
+ };
+
+ if (str1[i]==QChar(0x003C) && (str1[i+1]==QChar(0x002F) || str1[i+1].isLetter()) ) // 0x003C="<", 0x002F="/"
+ {// skip tag
+ while(i<l1 && str1[i]!=QChar(0x003E)) temp += str1[i++];
+ if (i++ <l1) temp += QChar(0x003E);
+ s1.append(temp);
+ temp.truncate(0);
+ }
+
+ while ( i<l1 && !(str1[i].isLetter() || str1[i]==QChar(0x003C)) )
+ {
+ temp += str1[i++];
+ }
+ if (!temp.isEmpty())
+ {
+ s1.append(temp);
+ temp.truncate(0);
+ };
+ }
+
+ i=0;
+ while ( i<l2 )
+ {
+ if (str2[i]==QChar(0x003C) && (str2[i+1]==QChar(0x002F) || str2[i+1].isLetter()) ) // 0x003C="<", 0x002F="/"
+ {// skip tag
+ while(i<l2 && str2[i]!=QChar(0x003E)) temp += str2[i++];
+ if (i++ <l2) temp += QChar(0x003E);
+ s2.append(temp);
+ temp.truncate(0);
+ }
+
+ while ( i<l2 && str2[i].isLetter() )
+ {
+ temp += str2[i++];
+ }
+ if (!temp.isEmpty())
+ {
+ s2.append(temp);
+ temp.truncate(0);
+ };
+ //FIXME bounds
+ if (str2[i]==QChar(0x003C) && (str2[i+1]==QChar(0x002F) || str2[i+1].isLetter()) ) // 0x003C="<", 0x002F="/"
+ {// skip tag
+ while(i<l2 && str2[i]!=QChar(0x003E)) temp += str2[i++];
+ if (i++ <l2) temp += QChar(0x003E);
+ s2.append(temp);
+ temp.truncate(0);
+ }
+
+ while ( i<l2 && !(str2[i].isLetter() || str2[i]==QChar(0x003C)) )
+ {
+ temp += str2[i++];
+ }
+ if (!temp.isEmpty())
+ {
+ s2.append(temp);
+ temp.truncate(0);
+ };
+ }
+*/
+
+ while ( i<l1 )
+ {
+ while ( i<l1 && str1[i].isLetter() )
+ {
+ temp += str1[i++];
+ }
+ if (!temp.isEmpty())
+ {
+ s1.append(temp);
+ temp.truncate(0);
+ };
+
+ while ( i<l1 && !str1[i].isLetter() )
+ {
+ s1.append(QString(str1[i++]));
+ }
+ }
+
+ i=0;
+ while ( i<l2 )
+ {
+ while ( i<l2 && str2[i].isLetter() )
+ {
+ temp += str2[i++];
+ }
+ if (!temp.isEmpty())
+ {
+ s2.append(temp);
+ temp.truncate(0);
+ };
+
+ while ( i<l2 && !str2[i].isLetter() )
+ {
+ s2.append(QString(str2[i++]));
+ }
+ }
+
+ uint mX = s1.count();
+ uint nY = s2.count();
+
+ uint mT = mX+1;
+ uint nT = nY+1;
+
+ QValueVector<LCSMarker> b(mT*nT, NOTHING);
+ QValueVector<uint> c(mT*nT, 0);
+
+
+// calculate the LCS
+ b[0] = FINAL;
+ uint index_cache;
+ QStringList::iterator it1, it2;
+
+ for (i=1, it1 = s1.begin(); i<mT; ++i, ++it1)
+ {
+ for (j=1, it2 = s2.begin(); j<nT; ++j, ++it2)
+ {
+ index_cache = i*nT+j;
+ if ((*it1)==(*it2))
+ {
+ c[index_cache] = c[index_cache-nT-1] + 1;
+ b[index_cache] = ARROW_UP_LEFT;
+ }
+ else if (c[index_cache-nT] >= c[index_cache-1])
+ {
+ c[index_cache] = c[index_cache-nT];
+ b[index_cache] = ARROW_UP;
+ }
+ else
+ {
+ c[index_cache] = c[index_cache-1];
+ b[index_cache] = ARROW_LEFT;
+ }
+ }
+ }
+
+ c.clear();
+
+
+ LCSprinter printer(s1, s2, &b, nT, index_cache);
+
+ /*//debug
+ fprintf(stderr,"b:\n");
+ for (i=0; i<=mT; i++) {
+ for (j=0; j<nY; j++) {
+// fprintf(stderr,"[%3d]%1d.",i*nT+j,(uint) b[i*nT+j]);
+ fprintf(stderr,"%1d.",(uint) b[i*nT+j]);
+}
+ fprintf(stderr,"%1d\n",(uint) b[i*nT+j]);
+}
+ fprintf(stderr,"\n");
+
+ // print the c table
+ fprintf(stderr,"c:\n");
+ for (i=0; i<=mX; i++) {
+ for (j=0; j<nY; j++) {
+ fprintf(stderr,"%2d.",(uint) c[i*nY+j]);
+}
+ fprintf(stderr,"%2d\n",(uint) c[i*nY+j]);
+}
+ fprintf(stderr,"\n");
+ */
+
+ return printer.getString();
+}
+
+
+
+
+/*
+// old algorithm by Wolfram Diestel <wolfram@steloj.de>
+QString Diff::charDiff(QString s1, QString s2)
+{
+ int n = 3;
+ s1+="xxx";
+ s2+="xxx";
+
+ int pos1=0;
+ int pos2=0;
+ int len1 = s1.length();
+ int len2 = s2.length();
+ QString resultstr;
+ bool found = true;
+ bool swap = false;
+ while (found && pos1+n < len1 && pos2+n < len2)
+ {
+ // while strings are equal, increase positions
+ int len = 0;
+ while (pos1+len < len1 && pos2+len < len2 &&
+ (s1[pos1+len] == s2[pos2+len]))
+ {
+ len++;
+ }
+
+ // write first result
+ resultstr += s1.mid(pos1,len);
+ pos1 += len;
+ pos2 += len;
+
+ // If strings are not equal try to find equal substrings of
+ // length n. For this increase positions alternating like
+ // 0 1, 1 0, 0 2, 1 1, 2 0, 0 3, 1 2, 2 1, 3 0 etc.
+
+ int x = 1;
+ found = false;
+
+ // If one position is already at the end stop processing
+ if (pos1+n >= len1 || pos2+n >= len2)
+ {
+ break;
+ }
+
+
+ // evtl. exchange
+ if (len2 - pos2 < len1 - pos1)
+ {
+ swap=true;
+
+ int pos = pos1;
+ pos1 = pos2;
+ pos2 = pos;
+
+ QString s = s1;
+ s1 = s2;
+ s2 = s;
+
+ int len = len1;
+ len1 = len2;
+ len2 = len;
+ }
+
+ while( !found && (pos1+x < len1 || pos2+x <len2))
+ {
+ int p1;
+ int p2;
+ for(p1 = 0, p2 = x; p1 <= x; p1++, p2--)
+ {
+ if( pos1+p1+n >= len1 || pos2+p2+n >= len2)
+ break;
+
+ if(s1.mid(pos1+p1,n) == s2.mid(pos2+p2,n))
+ {
+ found = true;
+
+ // evtl. exchange back
+ if(swap)
+ {
+ int pos = pos1;
+ pos1 = pos2;
+ pos2 = pos;
+
+ QString s = s1;
+ s1 = s2;
+ s2 = s;
+
+ int len = len1;
+ len1 = len2;
+ len2 = len;
+
+ int p = p1;
+ p1 = p2;
+ p2 = p;
+
+ swap=false;
+ }
+
+
+ // write current result
+ if (p1 > 0)
+ {
+ resultstr += "<KBABELDEL>";
+ resultstr += s1.mid(pos1,p1);
+ resultstr += "</KBABELDEL>";
+ pos1 += p1;
+ }
+
+ if (p2 > 0 )
+ {
+ resultstr += "<KBABELADD>";
+ resultstr += s2.mid(pos2,p2);
+ resultstr += "</KBABELADD>";
+ pos2 += p2;
+ }
+
+ break;
+ }
+ }
+
+ x++;
+
+ }
+
+ }
+
+ bool removed=false;
+
+ // evtl. exchange back
+ if(swap)
+ {
+ int pos = pos1;
+ pos1 = pos2;
+ pos2 = pos;
+
+ QString s = s1;
+ s1 = s2;
+ s2 = s;
+
+ int len = len1;
+ len1 = len2;
+ len2 = len;
+
+ swap=false;
+ }
+
+ // if there is a rest, add it
+ if(pos1+n < len1)
+ {
+ resultstr += "<KBABELDEL>";
+ resultstr += s1.mid(pos1,len1-pos1-n);
+ resultstr += "</KBABELDEL>";
+ removed=true;
+ }
+
+ if(pos2+n < len2)
+ {
+ resultstr += "<KBABELADD>";
+ resultstr += s2.mid(pos2,len2-pos2-n);
+ resultstr += "</KBABELADD>";
+ removed=true;
+ }
+
+ if( !removed )
+ {
+ resultstr.truncate( resultstr.length()-3 );
+ }
+
+ return resultstr;
+}
+*/
diff --git a/kbabel/common/diff.h b/kbabel/common/diff.h
new file mode 100644
index 00000000..4e7dfb72
--- /dev/null
+++ b/kbabel/common/diff.h
@@ -0,0 +1,88 @@
+/* **************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2001 by Matthias Kiefer <kiefer@kde.org>
+ charDiff algorithm by Wolfram Diestel <wolfram@steloj.de>
+ wordDiff algorithm by Nick Shaforostoff <shafff@ukr.net>
+ (based on Markus Stengel's GPL implementation of LCS-Delta algorithm as it is described in "Introduction to Algorithms", MIT Press, 2001, Second Edition, written by Thomas H. Cormen et. al. It uses dynamic programming to solve the Longest Common Subsequence (LCS) problem. - http://www.markusstengel.de/text/en/i_4_1_5_3.html)
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+************************************************************************** */
+#ifndef DIFF_H
+#define DIFF_H
+
+#include <qvaluevector.h>
+#include <qstringlist.h>
+
+typedef enum
+{
+ NOTHING = 0,
+ ARROW_UP = 1,
+ ARROW_LEFT = 2,
+ ARROW_UP_LEFT = 3,
+ FINAL = 4
+} LCSMarker;
+
+
+/**
+ * Word-by-word diff algorithm
+ *
+ * @short Word-by-word diff algorithm
+ * @author Nick Shaforostoff <shafff@ukr.net>
+ */
+ QString wordDiff(const QString& oldString, const QString& newString);
+
+
+/**
+ * This class is for keeping "global" params of recursive function
+ *
+ * @short Class for keeping "global" params of recursive function
+ * @author Nick Shaforostoff <shafff@ukr.net>
+ */
+ class LCSprinter
+{
+ public:
+ LCSprinter(const QStringList &s_1, const QStringList &s_2, QValueVector<LCSMarker>* b_, const uint nT_, uint index);
+ void printLCS(uint index);
+ inline QString getString();
+
+ ~LCSprinter() {};
+ private:
+ QStringList s1, s2, resultString;
+ uint nT;//for use 1d vector as 2d
+ QValueVector<LCSMarker> *b;
+ QStringList::iterator it1, it2;
+};
+
+
+inline QString LCSprinter::getString()
+{
+ return resultString.join("").replace(QChar('\n'), ""); //w/o replace we'd get whole line colored
+}
+
+#endif // DIFF_H
+
diff --git a/kbabel/common/editcmd.cpp b/kbabel/common/editcmd.cpp
new file mode 100644
index 00000000..1643ed0b
--- /dev/null
+++ b/kbabel/common/editcmd.cpp
@@ -0,0 +1,106 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include "editcmd.h"
+#include <qregexp.h>
+
+using namespace KBabel;
+
+EditCommand::EditCommand()
+ :_part(UndefPart),
+ _index(-1)
+{
+}
+
+EditCommand::EditCommand(const int index, const Part part)
+ :_part(part),
+ _index(index)
+{
+}
+
+
+ // have to handle deletion of current selection
+DelTextCmd::DelTextCmd(int _offset, const QString &_str, int _pluralNumber )
+ : EditCommand(),
+ offset( _offset ),
+ str ( _str ),
+ pluralNumber( _pluralNumber )
+{
+}
+
+bool DelTextCmd::merge( EditCommand* other)
+{
+ if(other->terminator()!=0)
+ return false;
+
+ DelTextCmd* o = (DelTextCmd*)other;
+
+ if ( o->index() == index() && o->part() == part()
+ && o->type() == type() && o->pluralNumber==pluralNumber )
+ {
+ DelTextCmd* o = (DelTextCmd*) other;
+ if ( offset + int(str.length()) == o->offset && !str.contains(QRegExp("^\\s$")) )
+ {
+ o->str.prepend( str );
+ o->offset = offset;
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+InsTextCmd::InsTextCmd(int offset,const QString &str, int pluralNumber )
+ : DelTextCmd( offset, str, pluralNumber )
+{
+}
+
+bool InsTextCmd::merge( EditCommand* other)
+{
+ if(other->terminator()!=0)
+ return false;
+
+ DelTextCmd* o = (DelTextCmd*)other;
+
+ if ( o->index()==index() && o->part() == part()
+ && o->type() == type() && o->pluralNumber==pluralNumber )
+ {
+ if ( offset == o->offset + int(o->str.length()) && !str.contains(QRegExp("^\\s$")) )
+ {
+ o->str += str;
+ return true;
+ }
+ }
+ return false;
+}
+
diff --git a/kbabel/common/editcmd.h b/kbabel/common/editcmd.h
new file mode 100644
index 00000000..458d2c57
--- /dev/null
+++ b/kbabel/common/editcmd.h
@@ -0,0 +1,112 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+**************************************************************************** */
+#ifndef EDITCMD_H
+#define EDITCMD_H
+
+#include "itempart.h"
+
+#include <qstring.h>
+#include <kdemacros.h>
+
+namespace KBabel
+{
+
+class KDE_EXPORT EditCommand
+{
+public:
+ enum Commands { Invalid, Begin, End, Insert, Delete };
+
+ EditCommand();
+ EditCommand( const int index, const Part part );
+ virtual ~EditCommand() {};
+ virtual Commands type() const { return Invalid; }
+ virtual int terminator() const { return 0; }
+
+ int index() const { return _index; }
+ void setIndex( int index ) { _index=index; }
+ Part part() const { return _part; }
+ void setPart(Part part) {_part=part;}
+
+ virtual bool merge( EditCommand* ) { return false;}
+
+private:
+ Part _part;
+ int _index;
+};
+
+
+class KDE_EXPORT BeginCommand : public EditCommand
+{
+public:
+ BeginCommand( const int index, const Part part ) : EditCommand(index,part) {}
+ virtual Commands type() const { return Begin; }
+ virtual int terminator() const { return 1; }
+};
+
+
+class KDE_EXPORT EndCommand : public EditCommand
+{
+public:
+ EndCommand( const int index, const Part part ) : EditCommand(index,part) {}
+ virtual Commands type() const { return End; }
+ virtual int terminator() const { return -1; }
+};
+
+
+
+class KDE_EXPORT DelTextCmd : public EditCommand
+{
+public:
+ int offset;
+ QString str;
+ int pluralNumber;
+
+ // have to handle deletion of current selection
+ DelTextCmd(int offset, const QString &str, int pluralNumber );
+ virtual Commands type() const { return Delete; }
+
+ bool merge( EditCommand* other);
+};
+
+class KDE_EXPORT InsTextCmd : public DelTextCmd
+{
+
+public:
+ InsTextCmd(int offset,const QString &str, int pluralNumber );
+ virtual Commands type() const { return Insert; }
+
+ bool merge( EditCommand* other);
+};
+
+}
+
+#endif // SETTINGS_H
diff --git a/kbabel/common/exportplugin.cpp b/kbabel/common/exportplugin.cpp
new file mode 100644
index 00000000..99a727f8
--- /dev/null
+++ b/kbabel/common/exportplugin.cpp
@@ -0,0 +1,81 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002-2003 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#include "catalogfileplugin.h"
+
+#include <qstringlist.h>
+
+#include <kdebug.h>
+#include <ktrader.h>
+
+using namespace KBabel;
+
+struct KBabel::CatalogExportPluginPrivate
+{
+ bool _stop;
+};
+
+CatalogExportPlugin::CatalogExportPlugin(QObject* parent, const char* name) : QObject(parent,name)
+{
+ d = new CatalogExportPluginPrivate;
+ d->_stop=false;
+}
+
+CatalogExportPlugin::~CatalogExportPlugin()
+{
+ delete d;
+}
+
+QStringList CatalogExportPlugin::availableExportMimeTypes()
+{
+ QStringList result;
+
+ KTrader::OfferList offers = KTrader::self()->query("KBabelFilter", "exist [X-KDE-Export]");
+
+ for( KTrader::OfferListIterator ptr = offers.begin(); ptr!=offers.end() ; ++ptr )
+ {
+ result += (*ptr)->property("X-KDE-Export").toStringList();
+ }
+
+ return result;
+}
+
+void CatalogExportPlugin::stop()
+{
+ d->_stop = true;
+}
+
+bool CatalogExportPlugin::isStopped() const
+{
+ return d->_stop;
+}
diff --git a/kbabel/common/findoptions.h b/kbabel/common/findoptions.h
new file mode 100644
index 00000000..45c29e25
--- /dev/null
+++ b/kbabel/common/findoptions.h
@@ -0,0 +1,86 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2001 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef FINDOPTIONS_H
+#define FINDOPTIONS_H
+
+#include <qregexp.h>
+
+class QString;
+class QChar;
+
+namespace KBabel
+{
+
+class FindOptions
+{
+public:
+ QString findStr;
+
+ bool caseSensitive;
+ bool wholeWords;
+ bool fromCursor;
+ bool backwards;
+ bool isRegExp;
+
+ bool inMsgid;
+ bool inMsgstr;
+ bool inComment;
+
+ bool ignoreAccelMarker;
+ bool ignoreContextInfo;
+
+ bool askForNextFile;
+ bool askForSave; // whether should ask before saving or save automatically when loading next file
+ bool inAllFiles; // whether search should be done in all files
+ bool inMarkedFiles; // whether search should be restricted to marked ones
+ bool inTemplates;
+
+ // these are non-persistent options - not saved into configuration database
+ bool askFile; // whether findNext should ask catalog manager for next file
+ QRegExp contextInfo; // actual settings of context info regular expression
+ QChar accelMarker; // actual settings of accelerator marker
+
+};
+
+class ReplaceOptions : public FindOptions
+{
+public:
+ QString replaceStr;
+ bool ask;
+};
+
+}
+
+#endif
diff --git a/kbabel/common/importplugin.cpp b/kbabel/common/importplugin.cpp
new file mode 100644
index 00000000..d763e670
--- /dev/null
+++ b/kbabel/common/importplugin.cpp
@@ -0,0 +1,194 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002-2003 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#include "catalogfileplugin.h"
+#include "importplugin_private.h"
+
+#include "catalog.h"
+
+#include <qstringlist.h>
+
+#include <kdebug.h>
+#include <ktrader.h>
+
+using namespace KBabel;
+
+CatalogImportPlugin::CatalogImportPlugin(QObject* parent, const char* name) : QObject(parent,name)
+{
+ d = new CatalogImportPluginPrivate;
+ d->_catalog = 0;
+ d->_started = false;
+ d->_stopped = false;
+}
+
+CatalogImportPlugin::~CatalogImportPlugin()
+{
+ delete d;
+}
+
+void CatalogImportPlugin::appendCatalogItem( const CatalogItem& item, const bool obsolete )
+{
+ if( obsolete )
+ d->_obsoleteEntries.append(item);
+ else
+ d->_entries.append(item);
+}
+
+void CatalogImportPlugin::setCatalogExtraData( const QStringList& data )
+{
+ d->_catalogExtraData=data;
+ d->_updateCatalogExtraData=true;
+}
+
+void CatalogImportPlugin::setGeneratedFromDocbook( const bool generated )
+{
+ d->_generatedFromDocbook = generated;
+ d->_updateGeneratedFromDocbook = true;
+}
+
+void CatalogImportPlugin::setErrorIndex(const QValueList<uint>& errors)
+{
+ d->_errorList = errors;
+ d->_updateErrorList = true;
+}
+
+void CatalogImportPlugin::setFileCodec(QTextCodec* codec)
+{
+ d->_codec=codec;
+ d->_updateCodec = true;
+}
+
+void CatalogImportPlugin::setHeader( const CatalogItem& item )
+{
+ d->_header=item;
+ d->_updateHeader=true;
+}
+
+void CatalogImportPlugin::setMimeTypes( const QString& mimetypes )
+{
+ d->_mimeTypes=mimetypes;
+}
+
+ConversionStatus CatalogImportPlugin::open(const QString& file, const QString& mimetype, Catalog* catalog)
+{
+ d->_stopped=false;
+ d->_catalog=catalog;
+ startTransaction();
+
+ ConversionStatus result = load(file, mimetype);
+ if( d->_stopped )
+ {
+ d->_started=false;
+ return STOPPED;
+ }
+
+ if( result == OK || result == RECOVERED_PARSE_ERROR || result == RECOVERED_HEADER_ERROR )
+ commitTransaction();
+
+ return result;
+}
+
+void CatalogImportPlugin::startTransaction()
+{
+ d->_started = (d->_catalog!=0);
+
+ d->_updateCodec = false;
+ d->_updateCatalogExtraData = false;
+ d->_updateGeneratedFromDocbook = false;
+ d->_updateErrorList = false;
+ d->_updateHeader = false;
+ d->_mimeTypes = "text/plain";
+ d->_entries.clear();
+}
+
+void CatalogImportPlugin::commitTransaction()
+{
+ if( d->_started )
+ {
+ d->_catalog->clear();
+
+ // fill in the entries
+ QValueVector<CatalogItem> e;
+ e.reserve( d->_entries.count() );
+ for( QValueList<CatalogItem>::const_iterator it = d->_entries.begin(); it != d->_entries.end(); ++it )
+ {
+ e.append( *it );
+ }
+ d->_catalog->setEntries( e );
+
+ d->_catalog->setObsoleteEntries( d->_obsoleteEntries );
+
+ if( d->_updateCodec ) d->_catalog->setFileCodec(d->_codec);
+ if( d->_updateCatalogExtraData )
+ d->_catalog->setCatalogExtraData(d->_catalogExtraData);
+ if( d->_updateGeneratedFromDocbook )
+ d->_catalog->setGeneratedFromDocbook(d->_generatedFromDocbook);
+ if( d->_updateHeader )
+ d->_catalog->setHeader(d->_header);
+ // generate before setting errors, since it clears the error list
+ d->_catalog->generateIndexLists();
+ if( d->_updateErrorList )
+ d->_catalog->setErrorIndex(d->_errorList);
+
+ d->_catalog->setImportPluginID(id());
+ d->_catalog->setMimeTypes( d->_mimeTypes );
+ }
+
+ d->_started = false;
+}
+
+QStringList CatalogImportPlugin::availableImportMimeTypes()
+{
+ QStringList result;
+
+ KTrader::OfferList offers = KTrader::self()->query("KBabelFilter", "exist [X-KDE-Import]");
+
+ for( KTrader::OfferListIterator ptr = offers.begin(); ptr!=offers.end() ; ++ptr )
+ {
+ result += (*ptr)->property("X-KDE-Import").toStringList();
+ }
+
+ return result;
+}
+
+bool CatalogImportPlugin::isStopped() const
+{
+ return d->_stopped;
+}
+
+void CatalogImportPlugin::stop()
+{
+ d->_stopped = true;
+}
+
+#include "catalogfileplugin.moc"
diff --git a/kbabel/common/importplugin_private.h b/kbabel/common/importplugin_private.h
new file mode 100644
index 00000000..3c45919c
--- /dev/null
+++ b/kbabel/common/importplugin_private.h
@@ -0,0 +1,69 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002-2003 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef IMPORTPLUGINPRIVATE_H
+#define IMPORTPLUGINPRIVATE_H
+
+#include "catalogitem.h"
+
+class QTextCodec;
+
+namespace KBabel {
+
+class Catalog;
+
+class CatalogImportPluginPrivate
+{
+public:
+ Catalog* _catalog;
+ bool _started;
+ bool _stopped;
+
+ QValueList<CatalogItem> _entries;
+ QValueList<CatalogItem> _obsoleteEntries;
+ CatalogItem _header;
+ bool _generatedFromDocbook;
+ QTextCodec* _codec;
+ QValueList<uint> _errorList;
+ QStringList _catalogExtraData;
+ QString _mimeTypes;
+
+ bool _updateHeader;
+ bool _updateGeneratedFromDocbook;
+ bool _updateCodec;
+ bool _updateErrorList;
+ bool _updateCatalogExtraData;
+};
+
+}
+
+#endif
diff --git a/kbabel/common/itempart.h b/kbabel/common/itempart.h
new file mode 100644
index 00000000..842f195b
--- /dev/null
+++ b/kbabel/common/itempart.h
@@ -0,0 +1,37 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002-2005 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+**************************************************************************** */
+#ifndef ITEMPART_H
+#define ITEMPART_H
+
+enum Part {UndefPart, Msgid, Msgstr, Comment};
+
+#endif
diff --git a/kbabel/common/kbabel-projectrename.upd b/kbabel/common/kbabel-projectrename.upd
new file mode 100644
index 00000000..f2e8510b
--- /dev/null
+++ b/kbabel/common/kbabel-projectrename.upd
@@ -0,0 +1,13 @@
+Id=kde34
+File=kbabel.defaultproject
+Group=Header
+Author-Email,AuthorEmail
+Author-Name,AuthorName
+Local-Author-Name,LocalAuthorName
+Update-Charset,UpdateCharset
+Update-Encoding,UpdateEncoding
+Update-Language-Team,UpdateLanguageTeam
+Update-Last-Translator,UpdateLastTranslator
+Update-Project,UpdateProject
+Update-Revision,UpdateRevision
+#eof
diff --git a/kbabel/common/kbabeldatatool.h b/kbabel/common/kbabeldatatool.h
new file mode 100644
index 00000000..57d9f771
--- /dev/null
+++ b/kbabel/common/kbabeldatatool.h
@@ -0,0 +1,63 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2003 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef KBABELDATATOOL_H
+#define KBABELDATATOOL_H
+
+#include <kdatatool.h>
+
+namespace KBabel
+{
+
+/**
+ * This class represents a base class for a KBabel @ref KDataTool.
+ * It supports automatic settings management.
+ *
+ * @short This class represents a base class for a KBabel data tool.
+ */
+class KBabelDataTool: public KDataTool
+{
+ Q_OBJECT
+
+protected:
+ KBabelDataTool( QObject* parent, const char* name ) : KDataTool( parent, name ) {}
+public slots:
+ /** The only method to be redefined in inherited classes.
+ * This method is called everytime the settings are changed.
+ * @param project is ID of the project, for which the settings changed.
+ */
+ virtual void settingsChanged(const QString &project) = 0;
+};
+
+}
+
+#endif // KBABELDATATOOL_H
diff --git a/kbabel/common/kbabelfilter.desktop b/kbabel/common/kbabelfilter.desktop
new file mode 100644
index 00000000..f9573ad2
--- /dev/null
+++ b/kbabel/common/kbabelfilter.desktop
@@ -0,0 +1,60 @@
+[Desktop Entry]
+Type=ServiceType
+X-KDE-ServiceType=KBabelFilter
+Comment=KBabel filter
+Comment[bg]=Филтър - KBabel
+Comment[br]=Sil KBabel
+Comment[ca]=Filtre de KBabel
+Comment[cs]=KBabel filtr
+Comment[cy]=Hidlydd KBabel
+Comment[da]=KBabel-filter
+Comment[de]=KBabel-Filter
+Comment[el]=ΦίλτÏο KBabel
+Comment[es]=Filtro de KBabel
+Comment[et]=KBabeli filter
+Comment[eu]=KBabel iragazkia
+Comment[fa]=پالایۀ KBabel
+Comment[fi]=KBabel-suodatin
+Comment[fr]=Filtre pour KBabel
+Comment[ga]=Scagaire KBabel
+Comment[gl]=Filtro de KBabel
+Comment[he]=מסנן KBabel
+Comment[hi]=के-बेबल फ़िलà¥à¤Ÿà¤°
+Comment[hu]=KBabel-szűrő
+Comment[is]=KBabel sía
+Comment[it]=Filtro KBabel
+Comment[ja]=KBabel フィルタ
+Comment[ka]=KBabel ფილტრი
+Comment[kk]=KBabel ÑүзгіÑÑ–
+Comment[lt]=KBabel filtras
+Comment[ms]=Penapis KBabel
+Comment[nb]=KBabel-filter
+Comment[nds]=KBabel-Filter
+Comment[ne]=केबà¥à¤¯à¤¾à¤¬à¤² फिलà¥à¤Ÿà¤°
+Comment[nl]=KBabel-filter
+Comment[nn]=KBabel-filter
+Comment[pa]=KBabel ਫਿਲਟਰ
+Comment[pl]=Filtr KBabel
+Comment[pt]=Filtro do KBabel
+Comment[pt_BR]=Filtro KBabel
+Comment[ru]=Фильтр KBabel
+Comment[sk]=Filter pre KBabel
+Comment[sl]=Filter KBabel
+Comment[sr]=KBabel-ов филтер
+Comment[sr@Latn]=KBabel-ov filter
+Comment[sv]=Kbabel-filter
+Comment[ta]=Kபாபேல௠வடிகடà¯à®Ÿà®¿
+Comment[tg]=Филтри KBabel
+Comment[tr]=KBabel süzgeci
+Comment[uk]=Фільтр KBabel
+Comment[zh_CN]=KBabel 过滤器
+Comment[zh_TW]=KBabel éŽæ¿¾å™¨
+
+[PropertyDef::X-KDE-Import]
+Type=QStringList
+
+[PropertyDef::X-KDE-Export]
+Type=QStringList
+
+[PropertyDef::X-KDE-Available]
+Type=QString
diff --git a/kbabel/common/kbmailer.cpp b/kbabel/common/kbmailer.cpp
new file mode 100644
index 00000000..fb3ab3b1
--- /dev/null
+++ b/kbabel/common/kbmailer.cpp
@@ -0,0 +1,244 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002-2003 by Marco Wegner <mail@marcowegner.de>
+ 2004 by Stanislav Visnovsky <visnovsky@kde.org>
+ Copyright (C) 2006 by Nicolas GOUTTE <goutte@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#include <qfileinfo.h>
+#include <qregexp.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qwidget.h>
+
+#include <kapplication.h>
+#include <kio/netaccess.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <ktar.h>
+#include <kurl.h>
+#include <kdebug.h>
+#include <ktempdir.h>
+#include <kinputdialog.h>
+
+#include "kbmailer.h"
+
+using namespace KBabel;
+
+KBabelMailer::KBabelMailer( QWidget* parent, Project::Ptr project)
+ : _project( project ), m_parent( parent )
+{
+ m_tempDir.setAutoDelete( true );
+ readConfig();
+}
+
+KBabelMailer::~KBabelMailer()
+{
+ saveConfig( );
+}
+
+void KBabelMailer::sendOneFile(const QString& fileName)
+{
+ if (!singleFileCompression) {
+ kapp->invokeMailer("", "", "", "", "", "", fileName);
+ } else {
+ const QString archive ( createArchive( QStringList( fileName ), QFileInfo( fileName ).baseName() ) );
+ if ( !archive.isEmpty() ) {
+ kapp->invokeMailer("", "", "", "", "", "", archive);
+ }
+ }
+}
+
+void KBabelMailer::sendOneFile( const KURL& url)
+{
+#if KDE_IS_VERSION( 3, 5, 0)
+ const KURL localUrl( KIO::NetAccess::mostLocalURL( url, m_parent ) );
+#else
+ const KURL localUrl( url );
+#endif
+ if ( localUrl.isLocalFile() )
+ {
+ sendOneFile( localUrl.path() );
+ return;
+ }
+
+ if (!singleFileCompression) {
+ QString fileName( url.filename() );
+ if ( fileName.isEmpty() )
+ {
+ fileName = "attachment";
+ }
+ // ### TODO: the current implementation has the default to possibly overwrite an already existing temporary file
+ QString tempName( m_tempDir.name() );
+ tempName += fileName;
+ if ( KIO::NetAccess::download( url, tempName, m_parent ) )
+ kapp->invokeMailer("", "", "", "", "", "", fileName);
+ else
+ {
+ KMessageBox::error( m_parent, i18n("Error while trying to download file %1.").arg( url.prettyURL() ) );
+ }
+ }
+ else
+ {
+ const QString archive ( createArchive( QStringList( url.url() ), url.filename() ) );
+ if ( !archive.isEmpty() ) {
+ kapp->invokeMailer("", "", "", "", "", "", archive);
+ }
+ }
+}
+
+void KBabelMailer::sendFiles(QStringList fileList, const QString& initialName)
+{
+ const QString archive ( createArchive( fileList, initialName ) );
+ if ( !archive.isEmpty() ) {
+ kapp->invokeMailer("", "", "", "", "", "", archive);
+ }
+}
+
+QString KBabelMailer::createArchive(QStringList fileList, QString initialName)
+{
+ if ( m_tempDir.name().isEmpty() )
+ {
+ kdWarning() << "KBabelMailer has not a valid temporary directory!" << endl;
+ return QString(); // No temporary directory!
+ }
+
+ // do nothing if there are no files in the list
+ if (fileList.empty())
+ return QString::null;
+
+ // determine the name of the archive, do nothing if none is given
+ // or Cancel was pressed
+ initialName = ( initialName.isEmpty() ? QString("translations") : initialName );
+ bool ok = false;
+ QStringList list( archiveList );
+ list.prepend( initialName );
+ QString archiveName ( KInputDialog::getItem( i18n("Save"),
+ i18n( "Enter the name of the archive without file extension" ),
+ archiveList, 0, true, &ok, m_parent ) );
+ if ( !ok || archiveName.isEmpty() )
+ return QString();
+
+ // file extensions are determined from the type of compression
+ archiveName.remove( QRegExp( "\\.tar\\.(gz|bz2)$" ) );
+
+ // Update the list of archive names, keep only the ten most recent ones.
+ archiveList.remove( archiveName );
+ archiveList.prepend( archiveName );
+ if ( archiveList.count( ) > 10 )
+ archiveList.pop_back();
+
+ // set the correct extension and mimetype
+ QString mimetype;
+ if (bzipCompression) {
+ archiveName += ".tar.bz2";
+ mimetype = "application/x-bzip2";
+ } else {
+ archiveName += ".tar.gz";
+ mimetype = "application/x-gzip";
+ }
+
+ return buildArchive (fileList, m_tempDir.name()+archiveName, mimetype, true);
+}
+
+QString KBabelMailer::buildArchive(QStringList fileList, QString archiveName, QString mimetype, bool remove)
+{
+ Q_UNUSED( remove );
+ // create a new archive
+ KTar archive(archiveName, mimetype);
+ if (!archive.open(IO_WriteOnly)) {
+ KMessageBox::error( m_parent, i18n("Error while trying to create archive file.") );
+ return QString::null;
+ }
+
+ // add files to this archive
+ QStringList::const_iterator it;
+ for (it = fileList.constBegin(); it != fileList.constEnd(); ++it) {
+#if KDE_IS_VERSION( 3, 5, 0 )
+ // Try to get a local URL instead of a remote one
+ const KURL url( KIO::NetAccess::mostLocalURL( KURL::fromPathOrURL( *it ), m_parent ) );
+#else
+ const KURL url( KURL::fromPathOrURL( *it ) );
+#endif
+ QString poTempName;
+ if ( !KIO::NetAccess::download( url, poTempName, m_parent ) ) {
+ KMessageBox::error( m_parent, i18n("Error while trying to read file %1.").arg( url.prettyURL() ) );
+ continue;
+ }
+
+ // The files in the archive are stored relatively to the PO base dir
+ // but only if "PoBaseDir" in the config file is set and the files
+ // actually reside in one of its subdirectories. Else they are stored
+ // without relative path.
+ QString poArchFileName = url.path();
+ if (_poBaseDir.isEmpty( ) || poArchFileName.find(_poBaseDir) != 0)
+ poArchFileName = QFileInfo( poArchFileName ).fileName();
+ else
+ poArchFileName.remove( QRegExp( "^" + QRegExp::escape( _poBaseDir ) + "/?" ) );
+ if ( !archive.addLocalFile( poTempName, poArchFileName ) )
+ {
+ KMessageBox::error( m_parent, i18n("Error while trying to copy file %1 into archive.").arg( url.prettyURL() ) );
+ }
+
+ KIO::NetAccess::removeTempFile(poTempName);
+ }
+ archive.close();
+
+ return archive.fileName();
+}
+
+void KBabelMailer::readConfig()
+{
+ // The relevant variables are never stored in catalogmanagerrc but in
+ // project config file. Therefore they are read from the project.
+
+ MiscSettings _settings = _project->miscSettings();
+
+ bzipCompression = _settings.useBzip;
+ singleFileCompression = _settings.compressSingleFile;
+
+ KConfig* conf = _project->config();
+
+ conf->setGroup ("Misc");
+ archiveList = conf->readListEntry("MailArchiveNames");
+
+ _poBaseDir = _project->catManSettings().poBaseDir;
+}
+
+void KBabelMailer::saveConfig()
+{
+ // For an explanation see readConfig( )
+ KConfig* _config = _project->config();
+
+ _config->setGroup("Misc");
+ _config->writeEntry("MailArchiveNames", archiveList);
+}
+
diff --git a/kbabel/common/kbmailer.h b/kbabel/common/kbmailer.h
new file mode 100644
index 00000000..7df5ce9d
--- /dev/null
+++ b/kbabel/common/kbmailer.h
@@ -0,0 +1,166 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002-2003 by Marco Wegner <mail@marcowegner.de>
+ 2004 by Stanislav Visnovsky <visnovsky@kde.org>
+ Copyright (C) 2006 by Nicolas GOUTTE <goutte@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#ifndef KBMAILER_H
+#define KBMAILER_H
+
+#include <kbproject.h>
+#include <kdemacros.h>
+#include <ktempdir.h>
+
+class QWidget;
+
+class KURL;
+
+namespace KBabel
+{
+
+/**
+ * Utility class for providing the capability to send compressed mail
+ * archives from within KBabel and the Catalog Manager.
+ *
+ * @short Utility class for compressed mail attachments.
+ * @author Marco Wegner <mail@marcowegner.de>
+ *
+ * @internal
+ */
+class KDE_EXPORT KBabelMailer
+{
+ public:
+ /**
+ * Constructor.
+ *
+ * @param parent The parent widget.
+ * @param project The project to be used.
+ * @since 1.11.2 (KDE 3.5.2): @p parent parameter
+ */
+ KBabelMailer( QWidget* parent, Project::Ptr project);
+ virtual ~KBabelMailer();
+
+ /**
+ * Send only one file as a mail attachment. The file can either be sent
+ * as a compressed or an uncompressed file.
+ *
+ * @param fileName the name of the file to be sent.
+ */
+ void sendOneFile(const QString& fileName);
+ /**
+ * Send only one file as a mail attachment. The file can either be sent
+ * as a compressed or an uncompressed file.
+ *
+ * @param url the URL of the file to be sent.
+ * @since 1.11.2 (KDE 3.5.2)
+ */
+ void sendOneFile(const KURL& url);
+ /**
+ * Send several files as a mail attachment. The files will be included in
+ * an archive.
+ *
+ * @param fileList contains the names of the files to be sent.
+ * @param initialName the possible name of the archive
+ */
+ void sendFiles(QStringList fileList, const QString& initialName = QString::null);
+ /**
+ * Sets the the PO files' base directory.
+ *
+ * @param dir the PO file base dir.
+ */
+ void setPOBaseDir(const QString& dir) { _poBaseDir = dir; }
+
+
+ /**
+ * This is where the archive is actually created.
+ *
+ * @param fileList contains the names of the files to be included in
+ * the archive.
+ * @param initialName the name used as initial name when the archive
+ * name is queried.
+ *
+ * @return name of the archive if it was created successfully,
+ * otherwise QString::null.
+ */
+ QString createArchive(QStringList fileList, QString initialName);
+
+ /**
+ * Write the archive file.
+ */
+ QString buildArchive(QStringList fileList, QString fileName, QString mimetype, bool remove = true);
+ private:
+ /**
+ * Read the config file to extract the values for compression
+ * method and compression of single files.
+ */
+ void readConfig();
+ /**
+ * Save the config settings, only the list of recent archive names for now.
+ */
+ void saveConfig( );
+
+
+ private:
+ /**
+ * Temporary directory
+ * @since 1.11.2 (KDE 3.5.2)
+ */
+ KTempDir m_tempDir;
+
+ /**
+ * Whether to use bzip2 as compression method. If false use gzip.
+ */
+ bool bzipCompression;
+ /**
+ * Whether to compress single files as well.
+ */
+ bool singleFileCompression;
+ /**
+ * This QStringList stores the recently used archive names.
+ */
+ QStringList archiveList;
+ /**
+ * The project object.
+ */
+ Project::Ptr _project;
+ /**
+ * The path to the PO Base directory
+ */
+ QString _poBaseDir;
+
+ /// The parent widget
+ QWidget* m_parent;
+};
+
+}
+
+#endif // KBMAILER_H
diff --git a/kbabel/common/kbproject.cpp b/kbabel/common/kbproject.cpp
new file mode 100644
index 00000000..38996b51
--- /dev/null
+++ b/kbabel/common/kbproject.cpp
@@ -0,0 +1,477 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2004 by Stanislav Visnovsky <visnovsky@kde.org>
+ Copyright (C) 2006 by Nicolas GOUTTE <goutte@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#include "resources.h"
+#include "kbproject.h"
+#include "kbprojectmanager.h"
+#include "kbprojectsettings.h"
+
+#include <qfileinfo.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kmimetype.h>
+#include <kspell.h>
+
+namespace KBabel
+{
+
+Project::Project( const QString& file ) :
+ QObject ()
+ , _filename (file)
+ , _name (i18n("unnamed"))
+ , _valid (false)
+ , _config (NULL)
+ , _settings (NULL)
+{
+ QFileInfo info(file);
+
+ if(info.isDir())
+ return;
+
+ if(info.exists())
+ {
+ // ### TODO: can a setting file only be a text/plain file?
+ // ### TODO: why not use KMimeType::findByPath if the fileis always local?
+ // first, for existing file check the MIME type
+ // it has to be text file
+ KMimeType::Ptr mime = KMimeType::findByURL( KURL::fromPathOrURL( file ) );
+
+ if ( mime->name() == "text/plain" )
+ {
+ // Plain text, no problem!
+ }
+ else if ( mime->name() == "application/x-zerosize" )
+ {
+ // Empty files are allowed too
+ kdWarning() << "Empty KBabel project file!" << endl;
+ }
+ else if ( mime->name() == "application/octet-stream" )
+ {
+ // this can happen if the file has some very long lines
+ kdWarning() << "KBabel project file detected as octet-stream! Perhaps there are very long lines in it!" << endl;
+ }
+ else
+ {
+ // Unknown mime type, abort!
+ // ### TODO: should the user not be asked instead?
+ kdWarning () << "File type is " << mime->name() << endl;
+ return;
+ }
+ }
+
+ _config = KSharedConfig::openConfig (_filename, false, false);
+ kdDebug (KBABEL) << "Opened project " << _filename << endl;
+
+ // read the project name
+ _config->setGroup( "Project" );
+ _name = _config->readEntry( "Name", QString() );
+ if ( _name.isEmpty() )
+ _name = "Default-Project"; // set default project name
+
+ // ### FIXME: why is the Version number not written to the project file?
+ if ( _config->readEntry( "Version", QString() ) != "1.0.1" )
+ {
+ kdWarning() << "Old project format assumed" << endl;
+
+ // transform old entries to the new ones
+ _config->setGroup( "Header");
+
+ // TODO remove obsolete entries as well
+ if (_config->hasKey("Author-Email") && !_config->hasKey("AuthorEmail"))
+ {
+ _config->writeEntry ("AuthorEmail", _config->readEntry ("Author-Email", ""));
+ _config->deleteEntry ("Author-Email");
+ }
+
+ if (_config->hasKey("Author-Name") && !_config->hasKey("AuthorName"))
+ {
+ _config->writeEntry ("AuthorName", _config->readEntry ("Author-Name", ""));
+ _config->deleteEntry ("Author-Name");
+ }
+
+ if (_config->hasKey("Local-Author-Name") && !_config->hasKey("LocalAuthorName"))
+ {
+ _config->writeEntry ("LocalAuthorName", _config->readEntry ("Local-Author-Name", ""));
+ _config->deleteEntry ("Local-Author-Name");
+ }
+
+ if (_config->hasKey("Update-Charset") && !_config->hasKey("UpdateCharset"))
+ {
+ _config->writeEntry ("UpdateCharset", _config->readEntry ("Update-Charset", ""));
+ _config->deleteEntry ("Update-Charset");
+ }
+
+ if (_config->hasKey("Update-Encoding") && !_config->hasKey("UpdateEncoding"))
+ {
+ _config->writeEntry ("UpdateEncoding", _config->readEntry ("Update-Encoding", ""));
+ _config->deleteEntry ("Update-Encoding");
+ }
+
+ if (_config->hasKey("Update-Language-Team") && !_config->hasKey("UpdateLanguageTeam"))
+ {
+ _config->writeEntry ("UpdateLanguageTeam", _config->readEntry ("Update-Language-Team", ""));
+ _config->deleteEntry ("Update-Language-Team");
+ }
+
+ if (_config->hasKey("Update-Last-Translator") && !_config->hasKey("UpdateLastTranslator"))
+ {
+ _config->writeEntry ("UpdateLastTranslator", _config->readEntry ("Update-Last-Translator", ""));
+ _config->deleteEntry ("Update-Last-Translator");
+ }
+
+ if (_config->hasKey("Update-Project") && !_config->hasKey("UpdateProject"))
+ {
+ _config->writeEntry ("UpdateProject", _config->readEntry ("Update-Project", ""));
+ _config->deleteEntry ("Update-Project");
+ }
+
+ if (_config->hasKey("Update-Revision") && !_config->hasKey("UpdateRevision"))
+ {
+ _config->writeEntry ("UpdateRevision", _config->readEntry ("Update-Revision", ""));
+ _config->deleteEntry ("Update-Revision");
+ }
+
+ _config->sync();
+ }
+
+ _valid = true;
+
+ _settings = new KBabel::ProjectSettingsBase( _config );
+ _settings->readConfig();
+}
+
+Project::~Project ()
+{
+ if (_settings)
+ {
+ // store the project name
+ _settings->setVersion( "1.0.1" );
+ _settings->setName(_name);
+
+ kdDebug () << "Writing configuration" << endl;
+ _settings->writeConfig();
+
+ delete _settings;
+ }
+
+ // unregister in project manager
+ kdDebug () << "Freeing project " << _filename << endl;
+ ProjectManager::remove (this);
+}
+
+KConfig* Project::config ()
+{
+ return _config;
+}
+
+KSharedConfig* Project::sharedConfig( void )
+{
+ return _config;
+}
+
+ProjectSettingsBase* Project::settings ()
+{
+ return _settings;
+}
+
+IdentitySettings Project::identitySettings ()
+{
+ IdentitySettings settings;
+
+ settings.authorName=_settings->authorName();
+ settings.authorLocalizedName=_settings->localAuthorName();
+ settings.authorEmail=_settings->authorEmail();
+ settings.languageName=_settings->language();
+ settings.languageCode=_settings->languageCode();
+ settings.mailingList=_settings->mailinglist();
+ settings.timeZone=_settings->timezone();
+
+ settings.numberOfPluralForms=_settings->pluralForms();
+
+ if( settings.numberOfPluralForms < -1 )
+ {
+ kdWarning() << "Invalid number of plural forms, ignoring: " << settings.numberOfPluralForms << endl;
+ settings.numberOfPluralForms = 2;
+ }
+ settings.checkPluralArgument=_settings->checkPluralArgument();
+ settings.gnuPluralFormHeader=_settings->pluralFormsHeader();
+
+ return settings;
+}
+
+SaveSettings Project::saveSettings ()
+{
+ SaveSettings settings;
+
+ settings.autoUpdate=_settings->autoUpdate();
+ settings.updateLastTranslator=_settings->updateLastTranslator();
+ settings.updateRevisionDate=_settings->updateRevisionDate();
+ settings.updateLanguageTeam=_settings->updateLanguageTeam();
+ settings.updateCharset=_settings->updateCharset();
+ settings.updateEncoding=_settings->updateEncoding();
+ settings.encoding=_settings->encoding();
+ settings.useOldEncoding=_settings->useOldEncoding();
+
+ settings.updateProject=_settings->updateProject();
+ settings.projectString=_settings->projectString();
+
+ settings.autoSyntaxCheck = _settings->autoSyntaxCheck();
+ settings.saveObsolete = _settings->saveObsolete();
+ settings.customDateFormat = _settings->customDateFormat();
+ settings.dateFormat = (Qt::DateFormat)_settings->dateFormat();
+ settings.updateDescription = _settings->updateDescription();
+ settings.descriptionString = _settings->descriptionString();
+ settings.updateTranslatorCopyright = _settings->updateTranslatorCopyright();
+ settings.FSFCopyright = _settings->fSFCopyright();
+
+ settings.autoSaveDelay=_settings->autoSaveDelay();
+
+ return settings;
+}
+
+
+MiscSettings Project::miscSettings ()
+{
+ MiscSettings settings;
+
+ QString temp=_settings->accelMarker();
+ if(temp.length() > 0)
+ {
+ settings.accelMarker=temp[0];
+ }
+
+ temp = _settings->contextInfo();
+
+ settings.contextInfo.setPattern(temp);
+
+ temp = _settings->singularPlural();
+ settings.singularPlural.setPattern(temp);
+
+ settings.useBzip = _settings->bZipCompression();
+ settings.compressSingleFile = _settings->compressSingleFile();
+
+ return settings;
+}
+
+SpellcheckSettings Project::spellcheckSettings ()
+{
+ SpellcheckSettings settings;
+
+ settings.noRootAffix=_settings->noRootAffix();
+ settings.runTogether=_settings->runTogether();
+ settings.spellEncoding=_settings->spellEncoding();
+ settings.spellClient=_settings->spellClient();
+ settings.spellDict=_settings->spellDictionary();
+ settings.rememberIgnored=_settings->rememberIgnored();
+ settings.ignoreURL=_settings->ignoreURL();
+ settings.onFlySpellcheck=_settings->onFlySpellCheck();
+
+ settings.valid=true;
+
+ return settings;
+}
+
+SourceContextSettings Project::sourceContextSettings ()
+{
+ SourceContextSettings settings;
+
+ settings.codeRoot=_settings->codeRoot();
+ settings.sourcePaths=_settings->paths();
+
+ return settings;
+}
+
+CatManSettings Project::catManSettings ()
+{
+ CatManSettings settings;
+
+ settings.poBaseDir=_settings->poBaseDir();
+ settings.potBaseDir=_settings->potBaseDir();
+ settings.openWindow=_settings->openWindow();
+
+ settings.killCmdOnExit=_settings->killCmdOnExit();
+ settings.indexWords=_settings->indexWords();
+ settings.msgfmt=_settings->msgfmt();
+
+
+ settings.dirCommands = _settings->dirCommands();
+ settings.dirCommandNames = _settings->dirCommandNames();
+
+ settings.fileCommands = _settings->fileCommands();
+ settings.fileCommandNames = _settings->fileCommandNames();
+
+ settings.ignoreURL=_settings->ignoreURL();
+
+ settings.flagColumn=_settings->showFlagColumn();
+ settings.fuzzyColumn=_settings->showFuzzyColumn();
+ settings.untranslatedColumn=_settings->showUntranslatedColumn();
+ settings.totalColumn=_settings->showTotalColumn();
+ settings.cvsColumn=_settings->showCVSColumn();
+ settings.revisionColumn=_settings->showRevisionColumn();
+ settings.translatorColumn=_settings->showTranslatorColumn();
+
+ return settings;
+}
+
+void Project::setSettings (IdentitySettings settings)
+{
+ _settings->setAuthorName(settings.authorName);
+ _settings->setLocalAuthorName(settings.authorLocalizedName);
+ _settings->setAuthorEmail(settings.authorEmail);
+ _settings->setAuthorEmail(settings.authorEmail);
+ _settings->setLanguage(settings.languageName);
+ _settings->setLanguageCode(settings.languageCode);
+ _settings->setMailinglist(settings.mailingList);
+ _settings->setTimezone(settings.timeZone);
+ _settings->setPluralForms(settings.numberOfPluralForms);
+ _settings->setCheckPluralArgument(settings.checkPluralArgument);
+ _settings->setPluralFormsHeader(settings.gnuPluralFormHeader);
+
+ _settings->writeConfig();
+
+ emit signalIdentitySettingsChanged();
+ emit signalSettingsChanged();
+}
+
+void Project::setSettings (SaveSettings settings)
+{
+ _settings->setAutoUpdate(settings.autoUpdate);
+ _settings->setUpdateLastTranslator(settings.updateLastTranslator);
+ _settings->setUpdateRevisionDate(settings.updateRevisionDate);
+ _settings->setUpdateLanguageTeam(settings.updateLanguageTeam);
+ _settings->setUpdateCharset(settings.updateCharset);
+ _settings->setUpdateEncoding(settings.updateEncoding);
+ _settings->setEncoding(settings.encoding);
+ _settings->setUseOldEncoding(settings.useOldEncoding);
+
+ _settings->setUpdateProject(settings.updateProject);
+ _settings->setProjectString(settings.projectString);
+
+ _settings->setAutoSyntaxCheck(settings.autoSyntaxCheck);
+ _settings->setSaveObsolete(settings.saveObsolete);
+ _settings->setCustomDateFormat(settings.customDateFormat);
+ _settings->setDateFormat(settings.dateFormat);
+ _settings->setUpdateDescription(settings.updateDescription);
+ _settings->setDescriptionString(settings.descriptionString);
+ _settings->setUpdateTranslatorCopyright(settings.updateTranslatorCopyright);
+ _settings->setFSFCopyright(settings.FSFCopyright);
+
+ _settings->setAutoSaveDelay(settings.autoSaveDelay);
+
+ _settings->writeConfig();
+
+ emit signalSaveSettingsChanged();
+ emit signalSettingsChanged();
+}
+
+
+void Project::setSettings (MiscSettings settings)
+{
+ _settings->setAccelMarker(settings.accelMarker);
+ _settings->setContextInfo(settings.contextInfo.pattern());
+ _settings->setSingularPlural(settings.singularPlural.pattern());
+ _settings->setBZipCompression(settings.useBzip);
+ _settings->setCompressSingleFile(settings.compressSingleFile);
+
+ _settings->writeConfig();
+
+ emit signalMiscSettingsChanged();
+ emit signalSettingsChanged();
+}
+
+void Project::setSettings (SpellcheckSettings settings)
+{
+ _settings->setNoRootAffix(settings.noRootAffix);
+ _settings->setRunTogether(settings.runTogether);
+ _settings->setSpellEncoding(settings.spellEncoding);
+ _settings->setSpellClient(settings.spellClient);
+ _settings->setSpellDictionary(settings.spellDict);
+ _settings->setRememberIgnored(settings.rememberIgnored);
+ _settings->setIgnoreURL(settings.ignoreURL);
+ _settings->setOnFlySpellCheck(settings.onFlySpellcheck);
+
+ _settings->writeConfig();
+
+ emit signalSpellcheckSettingsChanged();
+ emit signalSettingsChanged();
+}
+
+void Project::setSettings (SourceContextSettings settings)
+{
+ KConfigGroupSaver saver(_config,"SourceContext");
+
+ _settings->setCodeRoot(settings.codeRoot);
+ _settings->setPaths(settings.sourcePaths);
+
+ _settings->writeConfig();
+
+ emit signalSourceContextSettingsChanged();
+ emit signalSettingsChanged();
+}
+
+void Project::setSettings (CatManSettings settings)
+{
+ _settings->setPoBaseDir(settings.poBaseDir);
+ _settings->setPotBaseDir(settings.potBaseDir);
+ _settings->setOpenWindow(settings.openWindow);
+
+ _settings->setKillCmdOnExit(settings.killCmdOnExit);
+ _settings->setIndexWords(settings.indexWords);
+
+ _settings->setDirCommands(settings.dirCommands);
+ _settings->setDirCommandNames(settings.dirCommandNames);
+
+ _settings->setFileCommands(settings.fileCommands);
+ _settings->setFileCommandNames(settings.fileCommandNames);
+
+ _settings->setValidationIgnoreURL(settings.ignoreURL);
+
+ _settings->setShowFlagColumn(settings.flagColumn);
+ _settings->setShowFuzzyColumn(settings.fuzzyColumn);
+ _settings->setShowUntranslatedColumn(settings.untranslatedColumn);
+ _settings->setShowTotalColumn(settings.totalColumn);
+ _settings->setShowCVSColumn(settings.cvsColumn);
+ _settings->setShowRevisionColumn(settings.revisionColumn);
+ _settings->setShowTranslatorColumn(settings.translatorColumn);
+
+ _settings->writeConfig();
+
+ emit signalCatManSettingsChanged();
+ emit signalSettingsChanged();
+}
+
+}
+
+#include "kbproject.moc"
diff --git a/kbabel/common/kbproject.h b/kbabel/common/kbproject.h
new file mode 100644
index 00000000..1e1ebc79
--- /dev/null
+++ b/kbabel/common/kbproject.h
@@ -0,0 +1,109 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2004 by Stanislav Visnovsky <visnovsky@kde.org>
+ Copyright (C) 2006 by Nicolas GOUTTE <goutte@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef KBPROJECT_H
+#define KBPROJECT_H
+
+#include <qstring.h>
+
+#include <kconfig.h>
+#include "catalogsettings.h"
+#include "projectsettings.h"
+
+namespace KBabel
+{
+ class ProjectSettingsBase;
+
+ class KDE_EXPORT Project : public QObject, public KShared
+ {
+ Q_OBJECT
+ public:
+ typedef KSharedPtr <Project> Ptr;
+
+ Project( const QString& file );
+ virtual ~Project ();
+
+ QString filename () const { return _filename; }
+ QString name () const { return _name; }
+
+ void setName( const QString& name ) { _name = name; }
+
+ KConfig* config ();
+ /**
+ * Returns the KSharedConfig pointer of the project data
+ * @since 1.11.2 (KDE 3.5.2)
+ */
+ KSharedConfig* sharedConfig( void );
+
+ ProjectSettingsBase* settings ();
+
+ bool valid () { return _valid; }
+
+ IdentitySettings identitySettings ();
+ SaveSettings saveSettings ();
+ MiscSettings miscSettings ();
+ SpellcheckSettings spellcheckSettings ();
+ SourceContextSettings sourceContextSettings ();
+ CatManSettings catManSettings ();
+
+ void setSettings(KBabel::CatManSettings newSettings);
+ void setSettings(KBabel::SaveSettings newSettings);
+ void setSettings(KBabel::IdentitySettings newSettings);
+ void setSettings(KBabel::MiscSettings newSettings);
+ void setSettings(KBabel::SpellcheckSettings newSettings);
+ void setSettings(KBabel::SourceContextSettings newSettings);
+
+ signals:
+ void signalIdentitySettingsChanged();
+ void signalSaveSettingsChanged();
+ void signalMiscSettingsChanged();
+ void signalSpellcheckSettingsChanged();
+ void signalSourceContextSettingsChanged();
+ void signalCatManSettingsChanged();
+
+ /**
+ * This is general purpose signal emitted additionally
+ * to the signals above.
+ */
+ void signalSettingsChanged();
+
+ private:
+ QString _filename;
+ QString _name;
+ bool _valid;
+ KSharedConfig::Ptr _config;
+ ProjectSettingsBase* _settings;
+ };
+
+}
+
+#endif // KBPROJECT_H
diff --git a/kbabel/common/kbprojectmanager.cpp b/kbabel/common/kbprojectmanager.cpp
new file mode 100644
index 00000000..048c530a
--- /dev/null
+++ b/kbabel/common/kbprojectmanager.cpp
@@ -0,0 +1,101 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#include <kdebug.h>
+#include <kstandarddirs.h>
+
+#include "kbprojectmanager.h"
+
+namespace KBabel
+{
+
+QPtrList<Project> ProjectManager::p_list;
+QString ProjectManager::strDefaultProjectName = QString();
+
+Project::Ptr ProjectManager::open( const QString& file )
+{
+ kdDebug() << k_funcinfo << " " << file << endl;
+ // TODO: ensure full path
+ // TODO: isn't a map better?
+ for(QPtrList<Project>::ConstIterator it = p_list.constBegin();
+ it != p_list.constEnd(); ++it)
+ {
+ if ((*it)->filename() == file)
+ {
+ kdDebug() << k_funcinfo << " returning existing project " << (void*) it << endl;
+ return (*it);
+ }
+ }
+
+ Project::Ptr f = new Project (file);
+
+ if( ! f->valid() )
+ {
+ kdWarning() << "New invalid project for " << file << endl;
+ return NULL;
+ }
+
+ kdDebug() << k_funcinfo << " creating new project " << (void*) f << endl;
+ p_list.append (f);
+ return f;
+}
+
+void ProjectManager::close( Project::Ptr project)
+{
+ // this does nothing, we don't really close projects ATM, just sync the configuration
+ kdDebug() << k_funcinfo << " closing project " << (void*) project << " count: " << project.count() << endl;
+ project->config()->sync();
+}
+
+QString ProjectManager::defaultProjectName( void )
+{
+ if ( strDefaultProjectName.isEmpty() )
+ strDefaultProjectName = locateLocal("config", "kbabel.defaultproject" );
+ return strDefaultProjectName;
+}
+
+Project::Ptr ProjectManager::create()
+{
+ kdWarning() << k_funcinfo << " was called!" << endl;
+ // TODO:
+ return 0;
+}
+
+void ProjectManager::remove( Project* ref )
+{
+ kdDebug() << k_funcinfo << " Final remove of project " << (void*) ref << " count remaining: " << ref->_KShared_count() << endl;
+ p_list.remove (ref);
+}
+
+}
+
diff --git a/kbabel/common/kbprojectmanager.h b/kbabel/common/kbprojectmanager.h
new file mode 100644
index 00000000..418183bb
--- /dev/null
+++ b/kbabel/common/kbprojectmanager.h
@@ -0,0 +1,62 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef KBPROJECTMANAGER_H
+#define KBPROJECTMANAGER_H
+
+#include <qstring.h>
+#include <qptrlist.h>
+#include <kdemacros.h>
+
+#include "kbproject.h"
+
+namespace KBabel
+{
+
+ class KDE_EXPORT ProjectManager
+ {
+ public:
+ static Project::Ptr open( const QString& file );
+ static void close( Project::Ptr project );
+ static Project::Ptr create();
+ static QString defaultProjectName( void );
+
+ friend class Project;
+ private:
+ static void remove (Project*);
+ static QPtrList<Project> p_list;
+ static QString strDefaultProjectName;
+ };
+
+}
+
+#endif // KBPROJECTMANAGER_H
diff --git a/kbabel/common/kbprojectsettings.kcfg b/kbabel/common/kbprojectsettings.kcfg
new file mode 100644
index 00000000..784189ec
--- /dev/null
+++ b/kbabel/common/kbprojectsettings.kcfg
@@ -0,0 +1,354 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile arg="true"/>
+ <include>catalogsettings.h</include>
+ <include>projectsettings.h</include>
+
+ <entry name="ValidateIgnoreFuzzy" type="Bool">
+ <label>If the validation tools should ignore fuzzy translations</label>
+ <default>false</default>
+ </entry>
+ <entry name="ValidateMarkAsFuzzy" type="Bool">
+ <label>If the validation tools should mark error entries as fuzzy</label>
+ <default>false</default>
+ </entry>
+ <group name="CatalogManager">
+ <entry name="DirCommandNames" type="StringList">
+ <label>List of command names for directories</label>
+ <default>Make,Make install,CVS Update</default>
+ </entry>
+ <entry name="DirCommands" type="StringList">
+ <label>List of commands for directories</label>
+ <default>make,make install,cvs update</default>
+ </entry>
+ <entry name="FileCommandNames" type="StringList">
+ <label>List of command names for files</label>
+ <default>Start application,Compile,CVS Conflict Resolution</default>
+ </entry>
+ <entry name="FileCommands" type="StringList">
+ <label>List of commands for files</label>
+ <default>@PACKAGE@,msgfmt -o @PACKAGE@.gmo @PACKAGE@.po,cervisia @PODIR@ --resolve @PACKAGE@.po</default>
+ </entry>
+ <entry name="IndexWords" type="Bool">
+ <label>If the file cache should contain also index of words for faster searching</label>
+ <default>false</default>
+ </entry>
+ <entry name="KillCmdOnExit" type="Bool">
+ <label>If the Catalog Manager should kill all running its gettext tools at exit</label>
+ <default>true</default>
+ </entry>
+ <entry name="msgfmt" type="Bool">
+ <label></label>
+ <default>true</default>
+ </entry>
+ <entry name="Marker" type="StringList">
+ <label>List of files marked</label>
+ </entry>
+ <entry name="OpenWindow" type="Bool">
+ <label>If the files should be open in new KBabel editor windows</label>
+ <default>false</default>
+ </entry>
+ <entry name="PoBaseDir" type="String">
+ <label>The base directory for PO files (translations)</label>
+ <default></default>
+ </entry>
+ <entry name="PotBaseDir" type="String">
+ <label>The base directory for POT files (templates to be translated)</label>
+ <default></default>
+ </entry>
+ <entry name="ShowTotalColumn" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="ShowCVSColumn" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="ShowFlagColumn" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="ShowFuzzyColumn" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="ShowRevisionColumn" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="ShowTranslatorColumn" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="ShowUntranslatedColumn" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="ValidationIgnoreURL" type="String">
+ <label>
+ </label>
+ <default code="true">KBabel::Defaults::CatalogManager::ignoreURL()</default>
+ </entry>
+ </group>
+ <group name="Header">
+ <entry name="AuthorEmail" type="String">
+ <label>Email of the translator</label>
+ <default code="true">Defaults::Identity::authorEmail()</default>
+ </entry>
+ <entry name="AuthorName" type="String">
+ <label>Name of the translator (non-localized)</label>
+ <default code="true">Defaults::Identity::authorName()</default>
+ </entry>
+ <entry name="AutoSaveDelay" type="UInt">
+ <label>Delay in minutes between autosaves. 0 disables autosave.</label>
+ <default>0</default>
+ </entry>
+ <entry name="AutoSyntaxCheck" type="Bool">
+ <label>If the syntax should be checked before save</label>
+ <default>true</default>
+ </entry>
+ <entry name="AutoUpdate" type="Bool">
+ <label>If the header should be automatically updated on save</label>
+ <default>true</default>
+ </entry>
+ <entry name="CheckPluralArgument" type="Bool">
+ <label>If the plural argument is required to be a part of translation</label>
+ <default>true</default>
+ </entry>
+ <entry name="CustomDateFormat" type="String">
+ <label>Custom date format used if DateFormat specifies that</label>
+ <default>%Y-%m-%d %H:%M%z</default>
+ </entry>
+ <entry name="DateFormat" type="Enum">
+ <label>Format of the dates stored</label>
+ <choices>
+ <choice name="Custom"/>
+ <choice name="Default"/>
+ <choice name="Local"/>
+ </choices>
+ <default>Default</default>
+ </entry>
+ <entry name="DescriptionString" type="String">
+ <label>Description of the translation</label>
+ <default>translation of @PACKAGE@.po to @LANGUAGE@</default>
+ </entry>
+ <entry name="Encoding" type="Enum">
+ <label>The encoding of the file</label>
+ <choices>
+ <choice name="Locale"/>
+ <choice name="UTF8"/>
+ <choice name="UTF16"/>
+ </choices>
+ <default>UTF8</default>
+ </entry>
+ <entry name="FSFCopyright" type="Enum">
+ <label>The way how to handle Free Software Foundation header</label>
+ <choices>
+ <choice name="Remove"/>
+ <choice name="Update"/>
+ <choice name="NoChange"/>
+ <choice name="RemoveLine"/>
+ </choices>
+ <default>Update</default>
+ </entry>
+ <entry name="Language" type="String">
+ <label>English name of the language</label>
+ <default></default>
+ </entry>
+ <entry name="LanguageCode" type="String">
+ <label>ISO 631 language code</label>
+ <default code="true">Defaults::Identity::languageCode()</default>
+ </entry>
+ <entry name="LocalAuthorName" type="String">
+ <label>Localized name of the author</label>
+ <default></default>
+ </entry>
+ <entry name="Mailinglist" type="String">
+ <label>Mailing list for i18n of the langauge</label>
+ <default code="true">Defaults::Identity::mailingList()</default>
+ </entry>
+ <entry name="PluralForms" type="UInt">
+ <label>Number of plural forms for the language</label>
+ <default>2</default>
+ </entry>
+ <entry name="PluralFormsHeader" type="String">
+ <label>Plural forms specification for GNU gettext</label>
+ <default></default>
+ </entry>
+ <entry name="ProjectString" type="String">
+ <label>Macro-based string to fill Project GNU header</label>
+ <default>@PACKAGE@</default>
+ </entry>
+ <entry name="SaveObsolete" type="Bool">
+ <label>If the obsolete translation entries should be saved</label>
+ <default>false</default>
+ </entry>
+ <entry name="Timezone" type="String">
+ <label>Timezone of the translation (needed for updating time stamps)</label>
+ <default code="true">Defaults::Identity::timezone()</default>
+ </entry>
+ <entry name="UpdateCharset" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="UpdateEncoding" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="UpdateLanguageTeam" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="UpdateLastTranslator" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="UpdateProject" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="UpdateRevisionDate" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="UpdateDescription" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="UpdateTranslatorCopyright" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="UseOldEncoding" type="Bool">
+ <label>If the saving should preserve the encoding of the file, if already defined
+ </label>
+ <default>true</default>
+ </entry>
+ </group>
+ <group name="Misc">
+ <entry name="AccelMarker" type="String">
+ <label>Marker for accelerators</label>
+ <default>&amp;</default>
+ </entry>
+ <entry name="BZipCompression" type="Bool">
+ <label>If the files should be compressed for mailing</label>
+ <default>true</default>
+ </entry>
+ <entry name="CompressSingleFile" type="Bool">
+ <label>If even single file should be compressed for mailing</label>
+ <default>true</default>
+ </entry>
+ <entry name="ContextInfo" type="String">
+ <label>Regular expression for identifying a context information in original text</label>
+ <default>^_:((?!\\n\n).)+\\n\n</default>
+ </entry>
+ <entry name="MailArchiveNames" type="StringList">
+ <label>List of recent mailed archives</label>
+ <default></default>
+ </entry>
+ <entry name="SingularPlural" type="String">
+ <label>Regular expression for identifying a KDE plural form</label>
+ <default>_n:\s</default>
+ </entry>
+ <entry name="DiffBaseDir" type="String">
+ <label>
+ </label>
+ <default></default>
+ </entry>
+ <entry name="UseDBForDiff" type="Enum">
+ <label>
+ </label>
+ <choices>
+ <choice name="File"/>
+ <choice name="Database"/>
+ <choice name="Msgstr"/>
+ </choices>
+ <default>Database</default>
+ </entry>
+ </group>
+ <group name="Project">
+ <entry name="Name" type="String">
+ <label>Name of the project</label>
+ <default></default>
+ </entry>
+ <entry name="Version" type="String">
+ <label>Version of the configuration file</label>
+ <default></default>
+ </entry>
+ </group>
+ <group name="Spellcheck">
+ <entry name="IgnoreURL" type="String">
+ <label>
+ </label>
+ <default code="true">Defaults::Spellcheck::ignoreURL()</default>
+ </entry>
+ <entry name="NoRootAffix" type="Bool">
+ <label>
+ </label>
+ <default code="true">Defaults::Spellcheck::noRootAffix()</default>
+ </entry>
+ <entry name="OnFlySpellCheck" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="RememberIgnored" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="RunTogether" type="Bool">
+ <label>
+ </label>
+ <default code="true">Defaults::Spellcheck::runTogether()</default>
+ </entry>
+ <entry name="SpellClient" type="UInt">
+ <label>
+ </label>
+ <default code="true">Defaults::Spellcheck::spellClient()</default>
+ </entry>
+ <entry name="SpellDictionary" type="String">
+ <label>
+ </label>
+ <default code="true">Defaults::Spellcheck::spellDictionary()</default>
+ </entry>
+ <entry name="SpellEncoding" type="UInt">
+ <label>
+ </label>
+ <default code="true">Defaults::Spellcheck::spellEncoding()</default>
+ </entry>
+ </group>
+ <group name="Tags">
+ <entry name="TagExpressions" type="String">
+ <label>
+ </label>
+ <default code="yes">Defaults::Tags::tagExpressions()</default>
+ </entry>
+ </group>
+ <group name="SourceContext">
+ <entry name="CodeRoot" type="String">
+ <default></default>
+ </entry>
+ <entry name="Paths" type="StringList">
+ <default>@PACKAGEDIR@/@PACKAGE@/@COMMENTPATH@,@CODEROOT@/@PACKAGEDIR@/@PACKAGE@/@COMMENTPATH@,@CODEROOT@/@PACKAGE@/@COMMENTPATH@,@POFILEDIR@/@COMMENTPATH@,@POFILEDIR@/../@COMMENTPATH@</default>
+ </entry>
+ </group>
+</kcfg>
diff --git a/kbabel/common/kbprojectsettings.kcfgc b/kbabel/common/kbprojectsettings.kcfgc
new file mode 100644
index 00000000..bf7df895
--- /dev/null
+++ b/kbabel/common/kbprojectsettings.kcfgc
@@ -0,0 +1,7 @@
+File=kbprojectsettings.kcfg
+NameSpace=KBabel
+ClassName=ProjectSettingsBase
+Singleton=false
+Mutators=true
+GlobalEnums=true
+
diff --git a/kbabel/common/libgettext/Makefile.am b/kbabel/common/libgettext/Makefile.am
new file mode 100644
index 00000000..eca54fda
--- /dev/null
+++ b/kbabel/common/libgettext/Makefile.am
@@ -0,0 +1,15 @@
+# this might be a naive way of seeing it, but
+# automake does not support C++ flex files.
+#LEX_OUTPUT_ROOT = lex.GettextBase
+#AM_LFLAGS = -+
+
+CLEANFILES = pofiles.cc
+
+noinst_LTLIBRARIES = libgettext.la
+
+libgettext_la_SOURCES = pofiles.cc
+
+pofiles.cc: $(srcdir)/pofiles.ll
+ $(LEX) -+ -opofiles.cc $(srcdir)/pofiles.ll
+
+noinst_HEADERS = tokens.h pofiles.h
diff --git a/kbabel/common/libgettext/pofiles.h b/kbabel/common/libgettext/pofiles.h
new file mode 100644
index 00000000..cf2e3ec8
--- /dev/null
+++ b/kbabel/common/libgettext/pofiles.h
@@ -0,0 +1,52 @@
+/*
+ This file is part of KBabel
+
+ Copyright (c) 2005 by Stanislav Visnovsky <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#ifndef POFILES_H
+#define POFILES_H
+
+#undef yyFlexLexer
+#define yyFlexLexer GettextBaseFlexLexer
+#include <FlexLexer.h>
+
+class GettextFlexLexer: public GettextBaseFlexLexer {
+public:
+ int lastToken;
+
+ GettextFlexLexer(std::istream*stream) : GettextBaseFlexLexer(stream) {}
+
+ int yylex()
+ {
+ return lastToken = GettextBaseFlexLexer::yylex();
+ }
+};
+
+#endif
diff --git a/kbabel/common/libgettext/pofiles.ll b/kbabel/common/libgettext/pofiles.ll
new file mode 100644
index 00000000..7466487a
--- /dev/null
+++ b/kbabel/common/libgettext/pofiles.ll
@@ -0,0 +1,107 @@
+
+/*
+ This file is a part of KBabel
+
+ Copyright (c) 2005 by Stanislav Visnovsky <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+%{
+#define YY_NO_UNPUT
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include "tokens.h"
+
+
+%}
+
+%option prefix="GettextBase"
+
+%option noyywrap
+
+/* Any end of line */
+EOL [\r\n]
+/* No end of line */
+NOEOL [^\r\n]
+
+%%
+
+
+
+[ ]*{EOL}+ ; /* This catches empty lines or a LF after a CR */
+
+msgid {
+ return T_MSGID;
+ }
+msgid_plural {
+ return T_MSGIDPLURAL;
+ }
+msgstr\[[0-9]+\] {
+ return T_MSGSTR;
+ }
+msgstr {
+ return T_MSGSTR;
+ }
+msgctxt {
+ return T_MSGCTXT;
+ }
+#~{NOEOL}* {
+ return T_OBSOLETE;
+ }
+
+#{NOEOL}* {
+ return T_COMMENT;
+ }
+
+\"({NOEOL}*(\\\")?)*\"{EOL} {
+ yytext[strlen(yytext)-2] = 0;
+ yytext++;
+ return T_STRING;
+ }
+
+[a-z]+ |
+. ;
+
+<<EOF>> {
+ return T_EOF;
+ }
+
+%%
diff --git a/kbabel/common/libgettext/tokens.h b/kbabel/common/libgettext/tokens.h
new file mode 100644
index 00000000..dfbf693d
--- /dev/null
+++ b/kbabel/common/libgettext/tokens.h
@@ -0,0 +1,45 @@
+/*
+ This file is a part of KBabel
+
+ Copyright (c) 2005 by Stanislav Visnovsky <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#ifndef POTOKENS_H
+#define POTOKENS_H
+
+#define T_EOF 256
+#define T_COMMENT 257
+#define T_STRING 258
+#define T_MSGID 259
+#define T_MSGSTR 260
+#define T_OBSOLETE 261
+#define T_MSGIDPLURAL 262
+#define T_MSGCTXT 263
+
+#endif
diff --git a/kbabel/common/msgfmt.cpp b/kbabel/common/msgfmt.cpp
new file mode 100644
index 00000000..ef8ca895
--- /dev/null
+++ b/kbabel/common/msgfmt.cpp
@@ -0,0 +1,147 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include "msgfmt.h"
+
+#include <kapplication.h>
+#include <kprocess.h>
+
+#include <qfileinfo.h>
+#include <qdir.h>
+#include <qfile.h>
+#include <qregexp.h>
+#include <qtextstream.h>
+#include <qstring.h>
+
+#include <stdlib.h>
+
+using namespace KBabel;
+
+Msgfmt::Msgfmt(QObject* parent,const char* name)
+ : QObject(parent , name)
+{
+}
+
+Msgfmt::Status Msgfmt::checkSyntax(QString file,QString& output, bool gnu)
+{
+ Status stat=Ok;
+ // this method does not return the right retrun values at the moment :-(
+
+ KProcess proc;
+
+ connect(&proc,SIGNAL(receivedStdout(KProcess*, char*, int)),
+ this,SLOT(addToOutput(KProcess*,char *, int )));
+ connect(&proc,SIGNAL(receivedStderr(KProcess *, char *, int)),
+ this,SLOT(addToOutput(KProcess*,char *, int)));
+
+ // remove last output
+ _output="";
+
+
+ proc << "msgfmt" << "--statistics" << "-o" << "/dev/null" << file;
+
+ if( gnu )
+ {
+ proc << "-vc";
+ }
+
+ if(!proc.start(KProcess::Block,KProcess::Stderr))
+ {
+ stat=NoExecutable;
+ }
+ else if(proc.normalExit())
+ {
+ if( proc.exitStatus() || _output.contains(QRegExp("^.+:\\d+:")) ) // little workaround :-(
+ stat=SyntaxError;
+ }
+ else
+ stat=Error;
+
+ output=_output;
+
+
+ return stat;
+}
+
+Msgfmt::Status Msgfmt::checkSyntaxInDir(QString dir,QString regexp,QString& output)
+{
+ Status stat=Ok;
+
+ // this method does not return the right return values at the moment :-(
+ KProcess proc;
+ proc.setUseShell(true);
+
+ connect(&proc,SIGNAL(receivedStdout(KProcess*, char*, int)),
+ this,SLOT(addToOutput(KProcess*,char *, int )));
+ connect(&proc,SIGNAL(receivedStderr(KProcess *, char *, int)),
+ this,SLOT(addToOutput(KProcess*,char *, int)));
+
+ // remove last output
+ _output="";
+
+ proc << "IFS='\n'; msgfmt --statistics -o /dev/null "
+ "$(find" << KProcess::quote(dir) << "-name" << KProcess::quote(regexp) << ")";
+
+ if(!proc.start(KProcess::Block,KProcess::Stderr))
+ {
+ stat=NoExecutable;
+ }
+ else if(proc.normalExit())
+ {
+ if( proc.exitStatus() || _output.contains(QRegExp("^.+:\\d+:")) ) // little workaround :-(
+ stat=SyntaxError;
+ }
+ else
+ stat=Error;
+
+ output=_output;
+
+
+ return stat;
+}
+
+
+
+void Msgfmt::addToOutput(KProcess*,char *buffer, int buflen)
+{
+ QString newString = QString::fromLocal8Bit(buffer, buflen);
+
+ _output+=newString;
+}
+
+
+QString Msgfmt::tempSaveName()
+{
+ return kapp->tempSaveName("/tmp/kbabel_msgfmt.po");
+}
+
+#include "msgfmt.moc"
diff --git a/kbabel/common/msgfmt.h b/kbabel/common/msgfmt.h
new file mode 100644
index 00000000..bf983b2f
--- /dev/null
+++ b/kbabel/common/msgfmt.h
@@ -0,0 +1,65 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef MSGFMT_H
+#define MSGFMT_H
+
+#include <qobject.h>
+#include <kdemacros.h>
+
+class KProcess;
+class QString;
+
+namespace KBabel
+{
+
+class KDE_EXPORT Msgfmt : private QObject
+{
+ Q_OBJECT
+public:
+ enum Status{NoExecutable,Ok,SyntaxError,HeaderError,Error,Unsupported};
+ Msgfmt(QObject* parent=0,const char* name=0);
+
+ Status checkSyntax(QString file,QString& output, bool gnu = false);
+ Status checkSyntaxInDir(QString dir,QString regexp,QString& output);
+
+private slots:
+ void addToOutput(KProcess*,char *buffer, int buflen);
+
+private:
+ static QString tempSaveName();
+ QString _output;
+};
+
+}
+
+#endif // MSGFMT_H
diff --git a/kbabel/common/pluralforms.h b/kbabel/common/pluralforms.h
new file mode 100644
index 00000000..f65dba01
--- /dev/null
+++ b/kbabel/common/pluralforms.h
@@ -0,0 +1,38 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002-2005 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef PLURALFORMS_H
+#define PLURALFORMS_H
+
+enum PluralFormType{NoPluralForm, Gettext, KDESpecific};
+
+#endif
diff --git a/kbabel/common/poinfo.cpp b/kbabel/common/poinfo.cpp
new file mode 100644
index 00000000..b7beba7d
--- /dev/null
+++ b/kbabel/common/poinfo.cpp
@@ -0,0 +1,781 @@
+/*
+ This file is part of KBabel
+ Copyright (C) 2002 Stefan Asserhäll <stefan.asserhall@telia.com>
+ 2003-2005 Stanislav Visnovsky <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#include "poinfo.h"
+
+#include "catalogitem.h"
+#include "findoptions.h"
+#include "msgfmt.h"
+#include "resources.h"
+
+#include <kapplication.h>
+#include <kio/netaccess.h>
+#include <kstandarddirs.h>
+#include <ksavefile.h>
+
+#include <qdatastream.h>
+#include <qdatetime.h>
+#include <qdict.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qregexp.h>
+#include <qtextcodec.h>
+
+#include "libgettext/pofiles.h"
+#include "libgettext/tokens.h"
+
+#include <fstream>
+
+using namespace KBabel;
+
+// A PO-file cache item
+struct poInfoCacheItem
+{
+ PoInfo info;
+ QDateTime lastModified;
+};
+
+inline QDataStream& operator << ( QDataStream& stream, poInfoCacheItem* item )
+{
+ // Note: if you change anything here, do not forget to increase the #define POINFOCACHE_VERSION
+ stream << item->info.total;
+ stream << item->info.fuzzy;
+ stream << item->info.untranslated;
+ stream << item->info.project;
+ stream << item->info.creation;
+ stream << item->info.revision;
+ stream << item->info.lastTranslator;
+ stream << item->info.languageTeam;
+ stream << item->info.mimeVersion;
+ stream << item->info.contentType;
+ stream << item->info.encoding;
+ stream << item->info.others;
+ stream << item->info.headerComment;
+ stream << item->lastModified;
+ return stream;
+}
+
+inline QDataStream& operator >> ( QDataStream& stream, poInfoCacheItem* item )
+{
+ stream >> item->info.total;
+ stream >> item->info.fuzzy;
+ stream >> item->info.untranslated;
+ stream >> item->info.project;
+ stream >> item->info.creation;
+ stream >> item->info.revision;
+ stream >> item->info.lastTranslator;
+ stream >> item->info.languageTeam;
+ stream >> item->info.mimeVersion;
+ stream >> item->info.contentType;
+ stream >> item->info.encoding;
+ stream >> item->info.others;
+ stream >> item->info.headerComment;
+ stream >> item->lastModified;
+ return stream;
+}
+
+// Cache of PO-file items
+static QDict<poInfoCacheItem> _poInfoCache;
+
+// File name of cache
+static QString _poInfoCacheName;
+
+// flag to stop current reading
+bool PoInfo::stopStaticRead;
+
+bool PoInfo::_gettextPluralForm;
+
+// Note: We only read the cache file if the data seems usable. If not, we will re-generate the data.
+void PoInfo::cacheRead()
+{
+ QFile cacheFile( _poInfoCacheName );
+ if( cacheFile.open( IO_ReadOnly ) ) {
+ QDataStream s( &cacheFile );
+
+ // Check the file cache version.
+ // If it is not the current version, we do not read the cache file
+ Q_UINT32 version;
+ s >> version;
+ if( version != POINFOCACHE_VERSION ) {
+ // Wrong POINFOCACHE_VERSION, so abort
+ kdDebug(KBABEL) << "Wrong cache file version: " << version << endl;
+ return;
+ }
+
+ /*
+ * Check the version of the QDataStream with which the cache file was written
+ *
+ * If the cache file was written by an incompatible future version of Qt,
+ * the cache file will not be read.
+ *
+ * On the other side, a cache file written by a previous version of Qt can be read,
+ * by setting the version of the QDataStream used.
+ */
+ Q_INT32 qdatastreamVersion;
+ s >> qdatastreamVersion;
+ if( qdatastreamVersion > 0 && qdatastreamVersion <= s.version() ) {
+ s.setVersion( qdatastreamVersion );
+ }
+ else {
+ // QDataStream version seems stupid, so abort
+ kdDebug(KBABEL) << "Wrong QDataStream version: " << qdatastreamVersion << endl;
+ return;
+ }
+
+ QString url;
+ while( !s.atEnd() ) {
+ poInfoCacheItem* item = new poInfoCacheItem;
+ s >> url;
+ s >> item;
+ _poInfoCache.insert( url, item );
+ }
+ cacheFile.close();
+ }
+}
+
+void PoInfo::cacheWrite()
+{
+ // We use KSaveFile as otherwise we have no management about the cache file's integrity
+ // (especially if two instances would write into the same cache file)
+ KSaveFile cacheFile( _poInfoCacheName );
+
+ QDataStream* stream = cacheFile.dataStream();
+
+ if( stream ) {
+
+ // Write the cache file version
+ // We choose to fix a format (Q_UINT32) for compatibility (Qt version, platforms, architectures)
+ const Q_UINT32 version = POINFOCACHE_VERSION;
+ *stream << version;
+
+ // Write the version of the QDataStream
+ // Here too we choose a fixed format (Q_INT32) for compatibility
+ const Q_INT32 qdatastreamVersion = stream->version();
+ *stream << qdatastreamVersion;
+
+ QDictIterator<poInfoCacheItem> it( _poInfoCache ); // iterator for dict
+ for ( ; it.current(); ++it ) {
+ if( QFile::exists( it.currentKey() ) ) {
+ *stream << it.currentKey();
+ *stream << it.current();
+ }
+ }
+ if ( !cacheFile.close() ) {
+ kdWarning(KBABEL) << "Could not write cache file: " << _poInfoCacheName << endl;
+ }
+ }
+ else {
+ kdWarning(KBABEL) << "Could not create QDataStream for cache file: " << _poInfoCacheName << endl;
+ cacheFile.abort();
+ }
+}
+
+bool PoInfo::cacheFind(const QString url, PoInfo& info)
+{
+ // Read cache if it has not been read, and set up post routine to write it
+ static bool _cacheIsRead = false;
+ if( !_cacheIsRead ) {
+ _cacheIsRead = true;
+ _poInfoCacheName = locateLocal("cache", "kbabel/poinfocache");
+ cacheRead();
+ }
+
+ poInfoCacheItem *item = _poInfoCache.find( url );
+ if( item ) {
+ QFileInfo fi( url );
+
+ if( fi.lastModified() == item->lastModified ) {
+ info = item->info;
+ return true;
+ }
+ }
+ return false;
+}
+
+void PoInfo::cacheSave(const QString url, PoInfo& info)
+{
+ poInfoCacheItem *item = new poInfoCacheItem;
+ QFileInfo fi( url );
+
+ item->info = info;
+ item->lastModified = fi.lastModified();
+ _poInfoCache.insert( url, item );
+}
+
+QTextCodec* PoInfo::codecForFile(QString gettextHeader)
+{
+ QRegExp regexp("Content-Type:\\s*\\w+/[-\\w]+;?\\s*charset\\s*=\\s*(\\S+)\\s*\\\\n");
+ if( regexp.search(gettextHeader) == -1 )
+ {
+ kdDebug(KBABEL) << "no charset entry found" << endl;
+ return 0;
+ }
+
+ const QString charset = regexp.cap(1);
+ kdDebug(KBABEL) << "charset: " << charset << endl;
+
+ QTextCodec* codec=0;
+
+ if(!charset.isEmpty())
+ {
+ // "CHARSET" is the default charset entry in a template (pot).
+ // characters in a template should be either pure ascii or
+ // at least utf8, so utf8-codec can be used for both.
+ if( charset == "CHARSET")
+ {
+ codec=QTextCodec::codecForName("utf8");
+ kdDebug(KBABEL)
+ << QString("file seems to be a template: using utf8 encoding.")
+ << endl;
+ }
+ else
+ {
+ codec=QTextCodec::codecForName(charset.latin1());
+ }
+
+ if(!codec)
+ {
+ kdWarning(KBABEL) << "charset found, but no codec available, using UTF8 instead" << endl;
+ codec=QTextCodec::codecForName("utf8");
+ }
+ }
+ else
+ {
+ // No charset? So it is probably ASCII, therefore UTF-8
+ kdWarning(KBABEL) << "No charset defined! Assuming UTF-8!" << endl;
+ codec=QTextCodec::codecForName("utf8");
+ }
+
+ return codec;
+}
+
+PoInfo PoInfo::headerInfo(const CatalogItem& headerItem)
+{
+ // A header of a Gettext .po/.pot file is made of entries of the kind:
+ // key:value\n
+ // Note that the "line" defined by the \n can be different than the line of the file.
+
+ // We join all lines of the header and then split the result again at the \n sequence
+ const QStringList header=QStringList::split("\\n",headerItem.msgstrAsList().join(QString()));
+
+ PoInfo info;
+
+ // extract information from the header
+ QStringList::const_iterator it;
+
+ // The header of a Gettext .po file is consisted of lines of key and value
+ for(it=header.begin();it!=header.end();++it)
+ {
+ bool knownKey=false;
+ // We search for the : character, which is the separator between key and value
+ const int res=(*it).find(':');
+ if (res>=0)
+ {
+ knownKey=true; // We know most keys, if not it will be changed to false in the "else" case
+ const QString key=(*it).left(res).simplifyWhiteSpace();
+ QString value=(*it).mid(res+1);
+ // "Chop" the \n at the end
+ if (value.endsWith("\\n"))
+ value.remove(value.length()-2,2); // ### Qt4: use value.chop(2)
+ value=value.simplifyWhiteSpace();
+ kdDebug(KBABEL) << "Header key: " << key << " value: " << value << endl;
+ if (key=="Project-Id-Version")
+ info.project=value;
+ else if (key=="POT-Creation-Date")
+ info.creation=value;
+ else if (key=="PO-Revision-Date")
+ info.revision=value;
+ else if (key=="Last-Translator")
+ info.lastTranslator=value;
+ else if (key=="Language-Team")
+ info.languageTeam=value;
+ else if (key=="MIME-Version")
+ info.mimeVersion=value;
+ else if (key=="Content-Type")
+ info.contentType=value;
+ else if (key=="Content-Transfer-Encoding")
+ info.encoding=value;
+ else
+ {
+ kdDebug(KBABEL)<<"Unknown key: "<<key<<endl;
+ knownKey=false;
+ }
+ }
+ if (!knownKey)
+ {
+ QString line=(*it);
+
+ if(line.right(2)=="\\n")
+ line.remove(line.length()-2,2); // ### Qt4: use value.chop(2)
+
+ if(!info.others.isEmpty())
+ info.others+='\n';
+
+ info.others+=line.simplifyWhiteSpace();
+ }
+ }
+
+ info.headerComment=headerItem.comment();
+
+ return info;
+}
+
+
+ConversionStatus PoInfo::info(const QString& url, PoInfo& info, QStringList &wordList, bool updateWordList, bool interactive)
+{
+ return PoInfo::info( url, info, wordList, updateWordList, interactive, true);
+}
+
+ConversionStatus PoInfo::info(const QString& url, PoInfo& info, QStringList &wordList, bool updateWordList, bool interactive, bool msgfmt)
+{
+ stopStaticRead = false;
+
+ if( !updateWordList && PoInfo::cacheFind( url, info ) )
+ return OK;
+
+ QString target;
+ if(KIO::NetAccess::download(KURL( url ), target, 0))
+ {
+ QFile file(target);
+
+ if ( msgfmt )
+ {
+ // First check file with msgfmt to be sure, it is syntactically correct
+ Msgfmt msgfmt;
+ QString output;
+ Msgfmt::Status stat = msgfmt.checkSyntax( target , output );
+ if(stat == Msgfmt::SyntaxError)
+ {
+ KIO::NetAccess::removeTempFile(target);
+ return PARSE_ERROR;
+ }
+ }
+
+
+ std::ifstream* stream = new std::ifstream( file.name().local8Bit());
+ if( stream->is_open() )
+ {
+ CatalogItem temp;
+
+ info.total=0;
+ info.fuzzy=0;
+ info.untranslated=0;
+
+ GettextFlexLexer* lexer = new GettextFlexLexer( stream );
+
+ lexer->yylex();
+
+ // now parse the rest of the file
+ ConversionStatus success=OK;
+
+ while( lexer->lastToken != T_EOF && success==OK)
+ {
+ if( interactive ) kapp->processEvents(10);
+
+ if( stopStaticRead )
+ {
+ KIO::NetAccess::removeTempFile(target);
+ delete lexer;
+ delete stream;
+ return OK;
+ }
+
+ success=fastRead(temp,lexer,false);
+
+ if(success==OK || success==RECOVERED_PARSE_ERROR)
+ {
+ success=OK;
+
+ if( temp.comment().contains("\n#~") ) continue; // skip obsolete
+
+ if( temp.msgid().first().isEmpty()) //header
+ {
+ if( temp.isFuzzy() ) temp.removeFuzzy();
+
+ //find out the codec
+ QTextCodec* codec = codecForFile( temp.msgstr().first() );
+ if( !codec ) return PARSE_ERROR;
+
+ // convert from UTF-8 using codec
+ temp.setComment( codec->toUnicode(temp.comment().utf8()) );
+ temp.setMsgstr( codec->toUnicode(temp.msgstr().first().utf8()) );
+
+ PoInfo infoCounts = info;
+ info=PoInfo::headerInfo(temp);
+ info.total = infoCounts.total;
+ info.fuzzy = infoCounts.fuzzy;
+ info.untranslated = infoCounts.untranslated;
+ continue; // do not update counters and word list for header
+ }
+
+ info.total++;
+
+ if(temp.isFuzzy())
+ info.fuzzy++;
+ else if(temp.isUntranslated())
+ info.untranslated++;
+
+ if( updateWordList )
+ {
+ // FIXME: should care about plural forms in msgid
+ QString st = temp.msgid().first().simplifyWhiteSpace().lower();
+ QStringList sl = QStringList::split( ' ', st );
+ while(!sl.isEmpty())
+ {
+ QString w = sl.first();
+ sl.pop_front();
+ if( !wordList.contains(w) ) wordList.append( w );
+ }
+ st = temp.msgstr().join(" " ).simplifyWhiteSpace().lower();
+ sl = QStringList::split( ' ', st );
+ while(!sl.isEmpty())
+ {
+ QString w = sl.first();
+ sl.pop_front();
+ if( !wordList.contains(w) ) wordList.append( w );
+ }
+ st = temp.comment().simplifyWhiteSpace().lower();
+ sl = QStringList::split( ' ', st );
+ while(!sl.isEmpty())
+ {
+ QString w = sl.first();
+ sl.pop_front();
+ if( !wordList.contains(w) ) wordList.append( w );
+ }
+ }
+ }
+ }
+
+ delete lexer;
+ delete stream;
+
+ if(success==PARSE_ERROR)
+ {
+ KIO::NetAccess::removeTempFile(target);
+ return PARSE_ERROR;
+ }
+ }
+ else
+ {
+ delete stream;
+ KIO::NetAccess::removeTempFile(target);
+ return NO_PERMISSIONS;
+ }
+
+ KIO::NetAccess::removeTempFile(target);
+ if( target == url )
+ PoInfo::cacheSave( url, info );
+ return OK;
+ }
+ else
+ {
+ return OS_ERROR;
+ }
+
+ return OK;
+}
+
+bool PoInfo::findInFile( const QString& url, FindOptions options )
+{
+ enum {Begin, Comment, Msgid, Msgstr, Msgctxt} part = Begin;
+
+ stopStaticRead = false;
+ QString target;
+ if(KIO::NetAccess::download(KURL( url ), target, 0))
+ {
+ std::ifstream* stream = new std::ifstream( target.local8Bit());
+ if(stream->is_open())
+ {
+ KIO::NetAccess::removeTempFile(target);
+
+ GettextFlexLexer* lexer = new GettextFlexLexer( stream );
+
+ lexer->yylex();
+
+ // prepare the search
+
+ QString searchStr = options.findStr;
+ QRegExp regexp( searchStr );
+
+ if( options.isRegExp )
+ regexp.setCaseSensitive( options.caseSensitive );
+
+ // first read header
+ CatalogItem temp;
+
+ ConversionStatus status = fastRead( temp, lexer, true );
+ if( status != OK || !temp.msgid().first().isEmpty() )
+ {
+ delete lexer;
+ delete stream;
+ return false; // header is not at the beginning, broken file
+ }
+
+ QTextCodec* codec = codecForFile( temp.msgstr().first() );
+ if( !codec )
+ {
+ return false;
+ }
+
+ // now parse the rest of the file
+ QString text;
+ int pos,len;
+
+ while(lexer->lastToken != T_EOF)
+ {
+ switch( lexer->lastToken ) {
+ case T_COMMENT: {
+ part = Comment;
+ if( !options.inComment ) break;
+ text = codec->toUnicode(lexer->YYText());
+ if( options.isRegExp )
+ pos=regexp.search(text, 0 );
+ else
+ pos=text.find(searchStr,0,options.caseSensitive);
+ if( pos >= 0)
+ {
+ if( options.wholeWords) {
+ len = searchStr.length();
+ QString pre = text.mid(pos-1,1);
+ QString post = text.mid(pos+len,1);
+ if( !pre.contains( QRegExp("[a-zA-Z0-9]")) &&
+ !post.contains( QRegExp("[a-zA-Z0-9]") )
+ ) {
+ delete lexer;
+ delete stream;
+ return true;
+ }
+ }
+ else {
+ delete lexer;
+ delete stream;
+ return true;
+ };
+ }
+ break;
+ }
+ case T_STRING: {
+ if( part == Msgid && !options.inMsgid ) break;
+ else if( part == Msgstr && !options.inMsgstr ) break;
+ // HACK: We ignore any string following a msgctxt, as it does not change a statistic
+ else if( part == Msgctxt ) break;
+
+ text = codec->toUnicode(lexer->YYText());
+
+ if( options.ignoreContextInfo )
+ {
+ pos = options.contextInfo.search(text);
+ len = options.contextInfo.matchedLength();
+ if( pos >= 0 )
+ text.remove( pos, len );
+ }
+
+ if( options.ignoreAccelMarker )
+ {
+ pos = text.find( options.accelMarker );
+ if( pos >= 0 )
+ text.remove( pos, 1 );
+ }
+
+ if( options.isRegExp )
+ pos=regexp.search(text, 0 );
+ else
+ pos=text.find(searchStr,0,options.caseSensitive);
+
+ if( pos >= 0)
+ {
+ if( options.wholeWords) {
+ len = searchStr.length();
+ QString pre = text.mid(pos-1,1);
+ QString post = text.mid(pos+len,1);
+ if( !pre.contains( QRegExp("[a-zA-Z0-9]")) &&
+ !post.contains( QRegExp("[a-zA-Z0-9]") )
+ ) {
+ delete lexer;
+ delete stream;
+ return true;
+ }
+ }
+ else {
+ delete lexer;
+ delete stream;
+ return true;
+ };
+ }
+ break;
+ }
+ case T_MSGSTR: {
+ part = Msgstr;
+ break;
+ }
+ case T_MSGID:
+ case T_MSGIDPLURAL: {
+ kapp->processEvents(10);
+
+ // if stopped, return not found
+ if( stopStaticRead )
+ {
+ delete lexer;
+ delete stream;
+ return false;
+ }
+ part = Msgid;
+ break;
+ }
+ case T_MSGCTXT: {
+ part = Msgctxt;
+ break;
+ }
+ }
+ lexer->yylex();
+ }
+ delete lexer;
+ delete stream;
+ }
+ }
+ return false;
+}
+
+// this does not like any incorrect files
+ConversionStatus PoInfo::fastRead( CatalogItem& item, GettextFlexLexer *lexer, bool storeText)
+{
+ item.clear();
+ _gettextPluralForm = false;
+
+ // comment
+ if( lexer->lastToken == T_COMMENT )
+ {
+ QString _comment = QString::fromUtf8(lexer->YYText());
+ while( lexer->yylex() == T_COMMENT )
+ _comment += "\n"+QString::fromUtf8(lexer->YYText());
+ item.setComment( _comment );
+// kdDebug(KBABEL) << "Comment: " << _comment << endl;
+ }
+
+ //obsolete
+ if( lexer->lastToken == T_OBSOLETE ) {
+ lexer->yylex();
+ item.setComment("#~\n#~");
+ return OK;
+ }
+
+ // msgctxt
+ if( lexer->lastToken == T_MSGCTXT ) {
+ // HACK: we simply ignore the context, as it does not change a statistic
+ do {
+ lexer->yylex();
+ } while ( lexer->lastToken == T_STRING );
+ }
+
+ // msgid
+ if( lexer->lastToken != T_MSGID ) return PARSE_ERROR;
+
+ if( lexer->yylex() != T_STRING ) return PARSE_ERROR;
+ QStringList msgids = item.msgid();
+ QStringList::Iterator it = msgids.begin();
+ *it = QString::fromUtf8(lexer->YYText());
+ if( storeText )
+ while( lexer->yylex() == T_STRING )
+ (*it) += ("\n"+ QString::fromUtf8(lexer->YYText()) );
+ else {
+ if( lexer->yylex() == T_STRING ) // this is not header
+ {
+ *it = "SKIPPED";
+ while( lexer->yylex() == T_STRING );
+ }
+ }
+ item.setMsgid( msgids );
+
+// kdDebug(KBABEL) << "Msgid: " << *it << endl;
+
+ if( lexer->lastToken == T_MSGIDPLURAL )
+ {
+ _gettextPluralForm = true;
+ if( lexer->yylex() != T_STRING ) return PARSE_ERROR;
+ QStringList msgids = item.msgid();
+ it = msgids.fromLast();
+ *it = QString::fromUtf8(lexer->YYText());
+ if( storeText )
+ while( lexer->yylex() == T_STRING )
+ (*it)+="\n"+ QString::fromUtf8(lexer->YYText());
+ else while( lexer->yylex() == T_STRING );
+ item.setMsgid( msgids );
+// kdDebug(KBABEL) << "Msgid_plural: " << *it << endl;
+ }
+
+ // msgstr
+ if( lexer->lastToken != T_MSGSTR ) return PARSE_ERROR;
+
+ if( !_gettextPluralForm )
+ {
+ if( lexer->yylex() != T_STRING ) return PARSE_ERROR;
+
+ QStringList msgstrs = item.msgstr();
+ it = msgstrs.begin();
+ *it = QString::fromUtf8(lexer->YYText());
+ if( storeText || item.msgid().first().isEmpty() ) // if we should store the text or it is a header
+ while( lexer->yylex() == T_STRING )
+ (*it)+= ("\n"+ QString::fromUtf8(lexer->YYText()));
+ else
+ if( lexer->yylex() == T_STRING ) // check next token, whether it is really translated
+ {
+ *it = "SKIPPED";
+ while( lexer->yylex() == T_STRING );
+ }
+ item.setMsgstr( msgstrs );
+// kdDebug(KBABEL) << "Msgstr: " << *it << endl;
+ }
+ else
+ {
+ QStringList msgstrs = item.msgstr();
+ QString s = QString::fromUtf8(lexer->YYText());
+ while( lexer->lastToken == T_MSGSTR && s.contains( QRegExp("^msgstr\\[[0-9]+\\]" ) ) )
+ {
+ if( lexer->yylex() != T_STRING ) return PARSE_ERROR;
+ it = msgstrs.fromLast();
+ *it = QString::fromUtf8(lexer->YYText());
+
+ if( storeText )
+ do {
+ (*it)+="\n"+QString::fromUtf8(lexer->YYText());
+ } while( lexer->yylex() == T_STRING );
+ else while( lexer->yylex() == T_STRING );
+// kdDebug(KBABEL) << "Msgstr: " << *it << endl;
+ s = QString::fromUtf8(lexer->YYText());
+ }
+ item.setMsgstr( msgstrs );
+ }
+
+ return OK;
+}
+
+// kate: space-indent on; indent-width 4; replace-tabs on;
diff --git a/kbabel/common/poinfo.h b/kbabel/common/poinfo.h
new file mode 100644
index 00000000..21b8d72d
--- /dev/null
+++ b/kbabel/common/poinfo.h
@@ -0,0 +1,157 @@
+/*
+ This file is part of KBabel
+ Copyright (C) 2002 Stefan Asserhäll <stefan.asserhall@telia.com>
+ 2003-2005 Stanislav Visnovsky <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#ifndef POINFO_H
+#define POINFO_H
+
+
+#include "catalogfileplugin.h"
+
+#include <kdebug.h>
+
+#include <qstring.h>
+
+/**
+ * @brief File cache version number.
+ *
+ * @note If the existing file is outdated, it will not be read,
+ * instead we will overwrite it with a new file.
+ */
+#define POINFOCACHE_VERSION 2
+
+class GettextFlexLexer;
+
+namespace KBabel {
+
+class FindOptions;
+
+/**
+ * PO-file information class, with transparent caching of information.
+ */
+class KDE_EXPORT PoInfo
+{
+public:
+ int total;
+ int fuzzy;
+ int untranslated;
+
+ QString project;
+ QString creation;
+ QString revision;
+ QString lastTranslator;
+ QString languageTeam;
+ QString mimeVersion;
+ QString contentType;
+ QString encoding;
+ QString others;
+
+ QString headerComment;
+
+ /**
+ * Find PO-file information in the cache.
+ *
+ * @param url The URL of the PO-file.
+ * @param info Returned cached information.
+ * @return true if found, false otherwise.
+ */
+ static bool cacheFind(const QString url, PoInfo& info);
+
+ /**
+ * Save PO-file information in the cache.
+ *
+ * @param url The URL of the PO-file.
+ * @param info Information to save.
+ */
+ static void cacheSave(const QString url, PoInfo& info);
+
+ /**
+ * @brief Get information about the PO file
+ *
+ * @param url The path (not an URL) of the file
+ * @param info The information retrieved from the file
+ * @param wordList ???
+ * @param updateWordList ???
+ * @param interactive Can the function interact with the user?
+ * @param msgfmt Should each file be checked with Gettext's msgfmt before
+ * being parsed?
+ * @since KBabel 1.11 (KDE 3.5)
+ */
+ static ConversionStatus info(const QString& url,PoInfo& info, QStringList &wordList, bool updateWordList, bool interactive, bool msgfmt);
+
+ /**
+ * @brief Get information about the PO file
+ *
+ * @param url The path (not an URL) of the file
+ * @param info The information retrieved from the file
+ * @param wordList ???
+ * @param updateWordList ???
+ * @param interactive Can the function interact with the user?
+ * @deprecated
+ * @note This function is missing in KBabel 1.11 (KDE 3.5).
+ * The function was re-introduced for binary-compatibility in
+ * KBabel 1.11.1 (KDE 3.5.1)
+ * @note This function always call Gettext's mgfmt before parsing each file
+ */
+ static ConversionStatus info(const QString& url,PoInfo& info, QStringList &wordList, bool updateWordList, bool interactive = true);
+
+ static PoInfo headerInfo(const CatalogItem&);
+ static bool findInFile(const QString& url, FindOptions options );
+
+ static bool stopStaticRead;
+
+ /**
+ * reads header information from the file and searches for charset
+ * information.
+ * @param gettextHeader text containing gettext headers
+ *
+ * @return Codec for found charset or 0, if no information has been found
+ */
+ static QTextCodec* codecForFile(QString gettextHeader);
+
+ /**
+ * @brief Write the entire cache.
+ */
+ static void cacheWrite();
+private:
+ /**
+ * Read the entire cache.
+ */
+ static void cacheRead();
+
+ static ConversionStatus fastRead( CatalogItem& item, GettextFlexLexer* lexer, bool storeText );
+
+ static bool _gettextPluralForm;
+};
+
+}
+
+#endif // POINFO_H
diff --git a/kbabel/common/projectsettings.cpp b/kbabel/common/projectsettings.cpp
new file mode 100644
index 00000000..3687c9d4
--- /dev/null
+++ b/kbabel/common/projectsettings.cpp
@@ -0,0 +1,126 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2001-2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include "projectsettings.h"
+#include "resources.h"
+
+#include <qstring.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+
+#include <kspell.h>
+
+QString KBabel::Defaults::Spellcheck::ignoreURL()
+{
+ QString _ignoreURL;
+
+ KStandardDirs * dirs = KGlobal::dirs();
+ if(dirs)
+ {
+ _ignoreURL = dirs->saveLocation("appdata");
+ if(_ignoreURL.right(1)!="/")
+ _ignoreURL+="/";
+ _ignoreURL += "spellignores";
+ }
+ return _ignoreURL;
+}
+
+KSpellConfig* KBabel::Defaults::Spellcheck::defaultsettings = NULL;
+
+bool KBabel::Defaults::Spellcheck::noRootAffix()
+{
+ if( ! defaultsettings )
+ {
+ defaultsettings = new KSpellConfig(0, "spellconfig");
+ }
+
+ return defaultsettings->noRootAffix();
+}
+
+bool KBabel::Defaults::Spellcheck::runTogether()
+{
+ if( ! defaultsettings )
+ {
+ defaultsettings = new KSpellConfig(0, "spellconfig");
+ }
+
+ return defaultsettings->runTogether();
+}
+
+int KBabel::Defaults::Spellcheck::spellClient()
+{
+ if( ! defaultsettings )
+ {
+ defaultsettings = new KSpellConfig(0, "spellconfig");
+ }
+
+ return defaultsettings->client();
+}
+
+QString KBabel::Defaults::Spellcheck::spellDictionary()
+{
+ if( ! defaultsettings )
+ {
+ defaultsettings = new KSpellConfig(0, "spellconfig");
+ }
+
+ return defaultsettings->dictionary();
+}
+
+int KBabel::Defaults::Spellcheck::spellEncoding()
+{
+ if( ! defaultsettings )
+ {
+ defaultsettings = new KSpellConfig(0, "spellconfig");
+ }
+
+ return defaultsettings->encoding();
+}
+
+QString KBabel::Defaults::CatalogManager::ignoreURL()
+{
+ QString _ignoreURL;
+
+ KStandardDirs * dirs = KGlobal::dirs();
+ if(dirs)
+ {
+ _ignoreURL = dirs->saveLocation("appdata");
+ if(_ignoreURL.right(1)!="/")
+ _ignoreURL+="/";
+ _ignoreURL += "validationignores";
+ }
+ return _ignoreURL;
+}
+
diff --git a/kbabel/common/projectsettings.h b/kbabel/common/projectsettings.h
new file mode 100644
index 00000000..186b21e5
--- /dev/null
+++ b/kbabel/common/projectsettings.h
@@ -0,0 +1,142 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2001-2005 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef PROJECTSETTINGS_H
+#define PROJECTSETTINGS_H
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qfont.h>
+#include <qcolor.h>
+#include <kurl.h>
+
+#include "catalogsettings.h"
+
+class KSpellConfig;
+
+namespace KBabel {
+
+struct SpellcheckSettings
+{
+ bool valid;
+ bool noRootAffix;
+ bool runTogether;
+ int spellEncoding;
+ int spellClient;
+ QString spellDict;
+
+ bool rememberIgnored;
+ QString ignoreURL;
+
+ bool onFlySpellcheck;
+
+ SpellcheckSettings() { valid=false; }
+};
+
+struct CatManSettings
+{
+ QString poBaseDir;
+ QString potBaseDir;
+
+ bool openWindow;
+
+ QStringList dirCommands;
+ QStringList dirCommandNames;
+ QStringList fileCommands;
+ QStringList fileCommandNames;
+
+ QString ignoreURL;
+
+ bool killCmdOnExit;
+ bool indexWords;
+ /// Should be msgfmt be run before processing a file?
+ bool msgfmt;
+
+ bool flagColumn;
+ bool fuzzyColumn;
+ bool untranslatedColumn;
+ bool totalColumn;
+ bool cvsColumn;
+ bool revisionColumn;
+ bool translatorColumn;
+
+};
+
+struct SourceContextSettings
+{
+ /**
+ * A path, which can be used as @CODEROOT@ variable in @ref sourcePaths .
+ * Defaults to empty string.
+ */
+ QString codeRoot;
+
+ /**
+ * List of paths, where the source file should be lookup. Can use @CODEROOT@ (replaced by @ref codeRoot),
+ * @PACKAGE@ (replaced by package name), @PACKAGEDIR@ (replaced by the
+ * longest known path of the package) and @COMMENTPATH@ (path extracted from comment specs.
+ */
+ QStringList sourcePaths;
+
+ void SourceContextSettins() { codeRoot = QString::null; sourcePaths.clear(); }
+};
+
+/**
+* This namespace provides static methods and variables to get the default
+* values of configuration values
+*/
+namespace Defaults
+{
+ class KDE_EXPORT Spellcheck
+ {
+ public:
+ static QString ignoreURL();
+ static bool noRootAffix();
+ static bool runTogether();
+ static int spellClient();
+ static QString spellDictionary();
+ static int spellEncoding();
+ private:
+ static KSpellConfig* defaultsettings;
+ };
+
+ class KDE_EXPORT CatalogManager
+ {
+ public:
+ static QString ignoreURL();
+ };
+}
+
+}
+
+#endif // PROJECTSETTINGS_H
diff --git a/kbabel/common/regexpextractor.cpp b/kbabel/common/regexpextractor.cpp
new file mode 100644
index 00000000..b69398c6
--- /dev/null
+++ b/kbabel/common/regexpextractor.cpp
@@ -0,0 +1,271 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2001 by Matthias Kiefer <matthias.kiefer@gmx.de>
+ 2002 by Stanislav Visnovsky <visnovsky@nenya.ms.mff.cuni.cz>
+
+ based on code of Andrea Rizzi <rizzi@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include "regexpextractor.h"
+
+#include <kdebug.h>
+#include <qregexp.h>
+
+using namespace KBabel;
+
+RegExpExtractor::RegExpExtractor(const QStringList& regexps) :
+ _regExpList( regexps )
+{
+ _string=QString::null;
+ _matches.setAutoDelete(true);
+}
+
+void RegExpExtractor::setString(QString string)
+{
+ _string=string;
+ processString();
+}
+
+uint RegExpExtractor::countMatches()
+{
+ return _matches.count();
+}
+
+QString RegExpExtractor::firstMatch()
+{
+ MatchedEntryInfo *ti = _matches.first();
+
+ if(ti)
+ return ti->extracted;
+
+ return QString::null;
+}
+
+QString RegExpExtractor::nextMatch()
+{
+ MatchedEntryInfo *ti=_matches.next();
+ if(!ti)
+ ti=_matches.first();
+
+ if(ti)
+ return ti->extracted;
+
+ return QString::null;
+}
+
+QString RegExpExtractor::match(uint tagnumber)
+{
+ MatchedEntryInfo *ti=_matches.at(tagnumber);
+ if(ti)
+ return ti->extracted;
+
+ return QString::null;
+}
+
+int RegExpExtractor::matchIndex(uint tagnumber)
+{
+ MatchedEntryInfo *ti=_matches.at(tagnumber);
+ if(ti)
+ return ti->index;
+
+ return -1;
+}
+
+QString RegExpExtractor::prevMatch()
+{
+ MatchedEntryInfo *ti=_matches.prev();
+ if(ti)
+ return ti->extracted;
+
+ return QString::null;
+}
+
+QString RegExpExtractor::lastMatch()
+{
+ MatchedEntryInfo *ti=_matches.last();
+ if(ti)
+ return ti->extracted;
+
+ return QString::null;
+}
+
+QStringList RegExpExtractor::matches()
+{
+ QStringList list;
+ MatchedEntryInfo *ti;
+ for(ti=_matches.first(); ti!=0; ti = _matches.next())
+ {
+ list.append(ti->extracted);
+ }
+
+ return list;
+}
+
+QString RegExpExtractor::plainString(bool keepPos)
+{
+ QString tmp=_string;
+
+ MatchedEntryInfo *ti;
+ for(ti=_matches.first(); ti != 0; ti=_matches.next())
+ {
+ uint len=ti->extracted.length();
+ QString s;
+ for(uint i=0; i<len; i++)
+ {
+ s+=' ';
+ }
+ tmp.replace(ti->index,len,s);
+
+ }
+ if(!keepPos)
+ {
+ tmp=tmp.simplifyWhiteSpace();
+ }
+
+ return tmp;
+}
+
+QString RegExpExtractor::matchesReplaced(const QString& replace)
+{
+ QString tmp=_string;
+
+ int posCorrection=0;
+ int replaceLen=replace.length();
+
+ MatchedEntryInfo *ti;
+ for(ti=_matches.first(); ti != 0; ti=_matches.next())
+ {
+ uint len=ti->extracted.length();
+ tmp.replace(ti->index + posCorrection,len,replace);
+
+ posCorrection+=(replaceLen-len);
+ }
+
+ return tmp;
+}
+
+void RegExpExtractor::processString()
+{
+ _matches.clear();
+
+ // if there is no regexp to be matched, quit
+ if( regExpList().empty() ) return;
+
+ QValueList<MatchedEntryInfo> tmpList;
+
+ bool found=false;
+ QString tmp=_string;
+ do
+ {
+ found=false;
+ QStringList::Iterator it;
+ for(it=_regExpList.begin();it!=_regExpList.end();++it)
+ {
+ int pos=-1;
+ QString tag;
+
+ QRegExp reg = QRegExp((*it));
+
+ pos = reg.search(tmp);
+ int len=reg.matchedLength();
+ if(pos>=0)
+ {
+ tag=tmp.mid(pos,len);
+ }
+
+ if(pos >= 0)
+ {
+ found=true;
+
+ MatchedEntryInfo ti;
+ ti.index=pos;
+ ti.extracted=tag;
+ tmpList.append(ti);
+
+ QString s;
+ for(uint i=0; i<tag.length(); i++)
+ {
+ s+=' ';
+ }
+ tmp.replace(pos,tag.length(),s);
+
+ break;
+ }
+ }
+ }
+ while( found );
+
+ uint num=tmpList.count();
+
+ for(uint i=0; i < num; i++)
+ {
+ uint n= 0;
+ uint min=_string.length();
+ uint counter=0;
+ QValueList<MatchedEntryInfo>::Iterator it;
+ for(it=tmpList.begin();it!=tmpList.end();++it)
+ {
+ if((*it).index < min)
+ {
+ min=(*it).index;
+ n=counter;
+ }
+
+ counter++;
+ }
+
+ it=tmpList.at(n);
+ MatchedEntryInfo *ti = new MatchedEntryInfo;
+ ti->index=(*it).index;
+ ti->extracted=(*it).extracted;
+ _matches.append(ti);
+ tmpList.remove(it);
+ }
+}
+
+QStringList RegExpExtractor::regExpList()
+{
+ return _regExpList;
+}
+
+void RegExpExtractor::setRegExpList( const QStringList& regexps )
+{
+ _regExpList = regexps;
+}
+
+void RegExpExtractor::addRegExpIdentifier(QString regExp)
+{
+ _regExpList.append(regExp);
+}
+
+void RegExpExtractor::deleteRegExpIdentifier(QString regExp)
+{
+ _regExpList.remove(regExp);
+}
+
diff --git a/kbabel/common/regexpextractor.h b/kbabel/common/regexpextractor.h
new file mode 100644
index 00000000..89703fba
--- /dev/null
+++ b/kbabel/common/regexpextractor.h
@@ -0,0 +1,158 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2001 by Matthias Kiefer <matthias.kiefer@gmx.de>
+
+ based on code of Andrea Rizzi <rizzi@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef _REGEXP_EXTRACTOR_H_
+#define _REGEXP_EXTRACTOR_H_
+
+#include <qptrlist.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qvaluelist.h>
+#include <qregexp.h>
+#include <kdemacros.h>
+
+namespace KBabel
+{
+
+struct KDE_EXPORT MatchedEntryInfo{
+ uint index;
+ QString extracted;
+};
+
+
+/**
+ * class to extract entries based on regexps from a string
+ * @author Andrea Rizzi <rizzi@kde.org>
+ */
+class KDE_EXPORT RegExpExtractor
+{
+
+public:
+ /**
+ * Create a regexp extractor for "string"
+ */
+ RegExpExtractor(const QStringList& regexps);
+
+ virtual ~RegExpExtractor() {}
+
+ /**
+ * Set the string of this extractor
+ */
+ void setString(QString string);
+
+ /**
+ * @return the number of matches found
+ */
+ uint countMatches();
+
+ /**
+ * @return the first match, and set the internal cursor to
+ * the beginning
+ */
+ QString firstMatch();
+
+ /**
+ * @return the next match and move cursor forward
+ */
+ QString nextMatch();
+
+ /**
+ * @return the n-th match. It also moves the cursor.
+ */
+ QString match(uint matchnumber);
+
+ /**
+ * @return the n-th match. It also moves the cursor. -1 is there
+ * is no such match.
+ */
+ int matchIndex(uint matchnumber);
+
+ /**
+ * @return the next match and move cursor forward
+ */
+ QString prevMatch();
+
+ /**
+ * @return the last match and move the cursor to the end
+ */
+ QString lastMatch();
+
+ /**
+ * @return a list of all matches
+ */
+ QStringList matches();
+
+ /**
+ * @return the string without matched text
+ *
+ * @param keepPos if false, the matches are just removed and so the
+ * position of the other words in the string will change. If true,
+ * the matches are replaced with ' ' and therefore the position of the
+ * words will not change
+ */
+ QString plainString(bool keepPos=false);
+
+ /**
+ * @return the string, where matches are replaced with the given string
+ */
+ QString matchesReplaced(const QString& replace);
+
+ //Functions that allow user to define his own regexps.
+
+ /**
+ * Add a regexp to the list of regexp identifier.
+ */
+ void addRegExpIdentifier(QString regexp);
+
+
+ /**
+ * Delete from the regexp list the regexp.
+ */
+ void deleteRegExpIdentifier(QString regexp);
+
+ void setRegExpList( const QStringList& regexps );
+
+ QStringList regExpList();
+
+protected:
+
+ void processString();
+ QPtrList<MatchedEntryInfo> _matches;
+ QString _string;
+ QStringList _regExpList;
+};
+
+
+}
+
+#endif
diff --git a/kbabel/common/resources.h b/kbabel/common/resources.h
new file mode 100644
index 00000000..d6054b43
--- /dev/null
+++ b/kbabel/common/resources.h
@@ -0,0 +1,43 @@
+/*
+ This file is part of KBabel
+
+ Copyright (c) 2005 by Stanislav Visnovsky <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#ifndef RESOURCES_H
+#define RESOURCES_H
+
+#include <kdebug.h>
+#define KBABEL 8107
+#define KBABEL_SEARCH 8108
+#define KBABEL_CATMAN 8109
+
+
+#endif // RESOURCES_H
+
diff --git a/kbabel/common/stringdistance.cpp b/kbabel/common/stringdistance.cpp
new file mode 100644
index 00000000..32cb9b96
--- /dev/null
+++ b/kbabel/common/stringdistance.cpp
@@ -0,0 +1,182 @@
+/* ****************************************************************************
+ Copyright (C) 2003-2004 Eva Brucherseifer <eva.brucherseifer@basyskom.com>
+ 2005 Stanislav visnovsky <visnovsky@kde.org>
+
+ This file is part of the KDE project
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#include "stringdistance.h"
+
+using namespace std;
+
+//! Debug-Messages 0 : off 1 : a few 10 : more
+int Distance::debug = 0;
+const int Distance::editCost_replace_base = 1;
+
+const int HammingDistance::editCost = 1;
+
+const int LevenshteinDistance::editCost_replace = 1;
+const int LevenshteinDistance::editCost_insert = 1;
+const int LevenshteinDistance::editCost_delete = 1;
+
+
+double relativeDistance(double distance, const QString& left_string, const QString& right_string)
+{
+ double maxsize=0;
+ double compsize=0;
+ maxsize = left_string.length();
+ compsize=right_string.length();
+ if (compsize>maxsize)
+ maxsize=compsize;
+ return distance/(double)maxsize;
+}
+
+
+/** This function walk trough the treeS(left & right) at the same time.
+ * There are in both entities the same number of trees!
+ * This function sums all the distances between all trees.
+ * For the calculation of the distance between two trees, it calls the function calculate.
+ */
+double Distance::operator()(const QString& left_string, const QString& right_string)
+{
+ m_distance = 0.00;
+ if (left_string == right_string)
+ return 0.00; // saves calculation time, both entities are the same
+
+ // swap strings, our matrix requires that
+ if (left_string.length () < right_string.length() )
+ {
+ m_distance = calculate(right_string, left_string);
+ }
+ else
+ {
+ m_distance = calculate(left_string, right_string);
+ }
+
+// if (debug > 0) cout << " --> total distance: " << m_distance << endl;
+ return m_distance;
+}
+
+/** This function calculates the distance between two nodes.
+ * For the calculation you can specify two variables gap & distance.
+ */
+int Distance::nodeDistance(const QString& left_letter, const QString& right_letter)
+{
+ if ( left_letter == right_letter )
+ {
+// if (debug > 0) cout << ".";
+ return 0;
+ }
+ else
+ {
+// if (debug > 0) cout << "!";
+ return editCostReplace();
+ }
+}
+
+/** This function walks along the treeS(left & right) at the same time.
+ * There are in both entities the same number of nodes, hopefully! But it doesn't care.
+ * This function sums all the distances between all nodes.
+ * For the calculation you can specify the distance between two nodes in variable distance
+ */
+double HammingDistance::calculate(const QString& left_string, const QString& right_string)
+{
+ double hammingDistance = 0.00;
+// if (debug > 0)
+// cout << left_string.length() << " " << right_string.length() << "\t";
+
+ unsigned int i=0;
+ unsigned int j=0;
+ for ( ; i != left_string.length() && j != right_string.length() ;
+ ++i,++j)
+ hammingDistance += double(nodeDistance(left_string[i], right_string[i]));
+ for ( ; i != left_string.length() ; ++i )
+ {
+ ++hammingDistance;
+// if (debug > 9) cout << "!";
+ }
+ for ( ; j != right_string.length() ; ++j)
+ {
+ ++hammingDistance;
+// if (debug > 9) cout << "!";
+ }
+ return hammingDistance;
+}
+
+
+/** This function walk along the treeS(left & right) at the same time.
+ * It uses the Levenshtein-algorithm for the calculation of the distance between two trees.
+ * A matrice D is generated which represent the distribution of distances between two trees.
+ * The last element represent the Levenshtein-distance.
+ */
+double LevenshteinDistance::calculate(const QString& left_string, const QString& right_string)
+{
+// if (debug > 0)
+// cout << left_string.length() << " " << right_string.length() << "\t";
+
+ unsigned int left_size = left_string.length()+1;
+ unsigned int right_size = right_string.length()+1;
+
+ int *_D = new int[left_size * right_size];
+
+ for (unsigned int i = 0 ; i < left_size * right_size; i++ )
+ _D[i] = 0;
+
+#define D(a,b) (_D[(a)+(b)*left_size])
+
+
+// boost::numeric::ublas::matrix<int> D(left_size, right_size);
+// D = zero_boost::numeric::ublas::matrix<int>(left_size, right_size);
+
+ unsigned int l,r;
+ D(0,0) = 0;
+ for(l = 1; l < left_size; l++)
+ D(l,0) = D(l-1,0) + editCost_delete;
+ for(r = 1; r < right_size; r++)
+ D(0,r) = D(0,r-1) + editCost_insert;
+
+ int tmp_value;
+ for(l = 1; l < left_size; l++)
+ {
+ for(r = 1; r < right_size; r++)
+ {
+ tmp_value = QMIN( ( D(l-1,r) + editCost_delete ),
+ ( D(l-1,r-1) + nodeDistance(left_string[l-1], right_string[r-1]) ) ) ;
+ D(l,r) = QMIN( tmp_value,
+ ( D(l,r-1) + editCost_insert ) );
+ }
+ }
+
+ double res (D(left_size-1,right_size-1));
+
+ delete[] _D;
+
+ return res;
+}
+
diff --git a/kbabel/common/stringdistance.h b/kbabel/common/stringdistance.h
new file mode 100644
index 00000000..6f5aa185
--- /dev/null
+++ b/kbabel/common/stringdistance.h
@@ -0,0 +1,131 @@
+/* ****************************************************************************
+ Copyright (C) 2003-2004 Eva Brucherseifer <eva.brucherseifer@basyskom.com>
+ 2005 Stanislav Visnovsky <visnovsky@kde.org>
+
+ This file is part of the KDE project
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#ifndef STRINGDISTANCE_H
+#define STRINGDISTANCE_H
+
+#include <qstring.h>
+
+//#include <boost/numeric/ublas/matrix.hpp>
+
+
+/** Private copy constructor and copy assignment ensure classes derived from
+ * class noncopyable cannot be copied.
+ * Taken from Boost library
+ * Contributed by Dave Abrahams
+ *
+ * If anyone needs a namespace here, please tell me at eva@rt.e-technik.tu-darmstadt.de
+ */
+class NonCopyable
+{
+protected:
+ NonCopyable(){}
+ virtual ~NonCopyable(){}
+private: // emphasize the following members are private
+ NonCopyable( const NonCopyable& );
+ const NonCopyable& operator=( const NonCopyable& );
+};
+
+
+/**
+ * @class Distance
+ * @author Eva Brucherseifer
+ *
+ * The class Distance calculates the distance
+ * between two Entities (left & right).
+ * It is the parent for other distance-classes.
+ */
+class Distance : public NonCopyable
+{
+public:
+ virtual ~Distance(){}
+ double operator()(const QString& left, const QString& right);
+
+ int editCostReplace() { return editCost_replace_base; }
+ static int debug;
+
+protected:
+ virtual double calculate(const QString& left_string, const QString& right_string) = 0;
+ int nodeDistance(const QString& left_letter, const QString& right_letter);
+ static const int editCost_replace_base;
+ double m_distance;
+};
+
+
+double relativeDistance(double distance, const QString& left_string, const QString right_string);
+
+
+/**
+ * @class HammingDistance
+ * @author Eva Brucherseifer
+ *
+ * The class HammingDistance is based on an algorithm
+ * of Hamming. It increase the distance if the nodes from
+ * the tree are not the same. Also called edit-distance.
+ */
+class HammingDistance : public Distance
+{
+protected:
+ virtual double calculate(const QString& left_string, const QString& right_string);
+ int editCostReplace() { return editCost; }
+ static const int editCost;
+};
+
+/**
+ * @class LevenshteinDistance
+ * @author Eva Brucherseifer
+ *
+ * The class LevenshteinDistance is based on an algorithm
+ * of Levenshtein. It search for the minimum distance of
+ * two trees. You can specify the distance between
+ * a gap & a node and between two different nodes.
+ */
+class LevenshteinDistance : public Distance
+{
+protected:
+ virtual double calculate(const QString& left_string, const QString& right_string);
+ int editCostReplace() { return editCost_replace; }
+ static const int editCost_replace;
+ static const int editCost_insert;
+ static const int editCost_delete;
+};
+
+
+/** wrapper function for replacement of fstrcmp from gettext */
+inline double fstrcmp(const QString& left, const QString& right)
+{
+ return LevenshteinDistance()(left,right);
+}
+
+
+#endif
diff --git a/kbabel/common/tagextractor.cpp b/kbabel/common/tagextractor.cpp
new file mode 100644
index 00000000..45b8ad9f
--- /dev/null
+++ b/kbabel/common/tagextractor.cpp
@@ -0,0 +1,54 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2001 by Matthias Kiefer <matthias.kiefer@gmx.de>
+ 2002 by Stanislav Visnovsky <visnovsky@nenya.ms.mff.cuni.cz>
+
+ based on code of Andrea Rizzi <rizzi@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include "catalogsettings.h"
+#include "tagextractor.h"
+
+#include <kglobal.h>
+#include <kconfig.h>
+
+using namespace KBabel;
+
+TagExtractor::TagExtractor() : RegExpExtractor(QStringList())
+{
+ KConfig* config = KGlobal::config();
+
+ config->setGroup("Tags");
+
+ QStringList s=config->readListEntry("TagExpressions");
+ if( s.empty() ) s = Defaults::Tag::tagExpressions();
+
+ RegExpExtractor::setRegExpList(s);
+}
+
diff --git a/kbabel/common/tagextractor.h b/kbabel/common/tagextractor.h
new file mode 100644
index 00000000..3845b9fd
--- /dev/null
+++ b/kbabel/common/tagextractor.h
@@ -0,0 +1,58 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2001 by Matthias Kiefer <matthias.kiefer@gmx.de>
+
+ based on code of Andrea Rizzi <rizzi@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef _TAG_EXTRACTOR_H_
+#define _TAG_EXTRACTOR_H_
+
+#include "regexpextractor.h"
+
+namespace KBabel
+{
+
+/**
+ * class to extract tags from a string
+ * @author Andrea Rizzi <rizzi@kde.org>
+ */
+class KDE_EXPORT TagExtractor : public RegExpExtractor
+{
+
+public:
+ /**
+ * Create a tag extractor by using default settings for tag expressions
+ */
+ TagExtractor();
+};
+
+}
+
+#endif
diff --git a/kbabel/commonui/Makefile.am b/kbabel/commonui/Makefile.am
new file mode 100644
index 00000000..e0ca94ce
--- /dev/null
+++ b/kbabel/commonui/Makefile.am
@@ -0,0 +1,40 @@
+## Makefile.am for libkbabelcommon
+
+# this is the program that gets installed. it's name is used for all
+# of the other Makefile.am variables
+noinst_LTLIBRARIES = libkbabelcommonui.la
+
+# set the include path for X, qt and KDE. Put local paths before all_includes.
+INCLUDES = -I$(srcdir)/../common -I../common -I$(srcdir)/../kbabeldict -I../kbabeldict $(all_includes)
+
+# which sources should be compiled
+libkbabelcommonui_la_SOURCES = klisteditor.ui context.cpp kactionselector.cpp \
+ toolselectionwidget.cpp toolaction.cpp \
+ finddialog.cpp roughtransdlg.cpp \
+ projectprefwidgets.cpp \
+ projectpref.cpp \
+ projectwizard.cpp \
+ projectwizardwidget.ui \
+ projectwizardwidget2.ui \
+ cmdedit.cpp \
+ diffpreferences.ui
+
+libkbabelcommonui_la_LIBADD = $(LIB_KIO) -lktexteditor ../common/libkbabelcommon.la ../kbabeldict/libkbabeldict.la
+
+libkbabelcommonui_la_LDFLAGS = $(all_libraries)
+
+# these are the headers for your project
+noinst_HEADERS = context.h kactionselector.h finddialog.h \
+ roughtransdlg.h projectprefwidgets.h projectpref.h \
+ cmdedit.h projectwizard.h
+
+# let automoc handle all of the meta source files (moc)
+METASOURCES = AUTO
+
+# we need to define our own service type for our plugins. It's data tool with a shortcut :-((
+kde_servicetypes_DATA = kbabel_validator.desktop kbabel_tool.desktop
+EXTRA_DIST = $(kde_servicetypes_DATA)
+
+context.lo: ../common/kbprojectsettings.h
+projectpref.lo: ../common/kbprojectsettings.h
+projectprefwidgets.lo: ../common/kbprojectsettings.h
diff --git a/kbabel/commonui/cmdedit.cpp b/kbabel/commonui/cmdedit.cpp
new file mode 100644
index 00000000..bfe95293
--- /dev/null
+++ b/kbabel/commonui/cmdedit.cpp
@@ -0,0 +1,298 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include "cmdedit.h"
+
+#include <qlistbox.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qtoolbutton.h>
+#include <klocale.h>
+#include <kdialog.h>
+
+
+CmdEdit::CmdEdit(QWidget* parent, const char* name)
+ : QWidget(parent,name)
+{
+ QGridLayout* layout = new QGridLayout( this , 1 , 1 );
+ layout->setSpacing( KDialog::spacingHint() );
+
+ QLabel* nameLabel = new QLabel( i18n("Command &Label:"), this);
+ QLabel* cmdLabel = new QLabel( i18n("Co&mmand:"), this);
+ layout->addWidget( nameLabel, 0 , 0 );
+ layout->addWidget( cmdLabel, 0 , 1 );
+
+ _cmdNameEdit = new QLineEdit( this , "cmdNameEdit" );
+ _cmdNameEdit->setMaxLength(20);
+ nameLabel->setBuddy(_cmdNameEdit);
+ layout->addWidget( _cmdNameEdit , 1 , 0 );
+
+ _cmdEdit = new QLineEdit( this , "cmdEdit" );
+ cmdLabel->setBuddy(_cmdEdit);
+ layout->addWidget( _cmdEdit , 1 , 1 );
+
+
+ _addButton = new QPushButton( i18n("&Add"), this );
+ _addButton->setEnabled(false);
+ layout->addWidget( _addButton , 1 , 2 );
+
+ _editButton = new QPushButton( i18n("&Edit"), this );
+ _editButton->setEnabled(false);
+ layout->addWidget( _editButton , 3 , 2 );
+
+ _removeButton = new QPushButton( i18n("&Remove"), this );
+ _removeButton->setEnabled(false);
+ layout->addWidget( _removeButton , 4 , 2 );
+
+ QHBoxLayout* hbox = new QHBoxLayout();
+ layout->addLayout(hbox,5,2);
+
+ _upButton = new QToolButton(UpArrow,this);
+ _upButton->setFixedSize(20,20);
+ _upButton->setEnabled(false);
+ hbox->addWidget( _upButton );
+
+ _downButton = new QToolButton(DownArrow,this);
+ _downButton->setFixedSize(20,20);
+ _downButton->setEnabled(false);
+ hbox->addWidget( _downButton);
+
+ _commandNames = new QListBox( this , "commandNamesBox" );
+ _commandNames->setMinimumSize(100, 100);
+ layout->addMultiCellWidget( _commandNames , 3 , 6 , 0 , 0);
+
+ _commands = new QListBox( this , "commandsBox" );
+ _commands->setMinimumSize(160, 100);
+ layout->addMultiCellWidget( _commands , 3 , 6 , 1 ,1 );
+
+
+ layout->setColStretch(0,1);
+ layout->setColStretch(1,2);
+ layout->setColStretch(2,0);
+
+ layout->addRowSpacing(2, KDialog::spacingHint());
+ layout->addRowSpacing(6, KDialog::spacingHint());
+
+ setMinimumSize(layout->sizeHint());
+
+
+ connect(_addButton , SIGNAL(clicked()) , this , SLOT(addCmd()) ) ;
+ connect(_editButton , SIGNAL(clicked()) , this , SLOT(editCmd()) );
+ connect(_removeButton , SIGNAL(clicked()) , this , SLOT(removeCmd()) );
+ connect(_upButton , SIGNAL(clicked()) , this , SLOT(upCmd()) ) ;
+ connect(_downButton , SIGNAL(clicked()) , this , SLOT(downCmd()) );
+
+ connect(_commands , SIGNAL(highlighted(int)) , this, SLOT(cmdHighlighted(int)) );
+ connect(_commandNames , SIGNAL(highlighted(int)) , this, SLOT(cmdNameHighlighted(int)) );
+ connect(_commands , SIGNAL(selected(int)) , this, SLOT(editCmd()) );
+ connect(_commandNames , SIGNAL(selected(int)) , this, SLOT(editCmd()) );
+
+ connect(_cmdEdit, SIGNAL(textChanged(const QString&)) , this , SLOT(checkAdd()) );
+ connect(_cmdNameEdit, SIGNAL(textChanged(const QString&)) , this , SLOT(checkAdd()) );
+}
+
+void CmdEdit::setCommands(const QStringList& commands,const QStringList& commandNames)
+{
+ _commands->clear();
+ _commands->insertStringList(commands);
+
+ _commandNames->clear();
+ _commandNames->insertStringList(commandNames);
+}
+
+void CmdEdit::commands(QStringList& commands, QStringList& commandNames)
+{
+ commands.clear();
+ commandNames.clear();
+
+ int items=_commands->count();
+
+ int i=0;
+ for( i=0 ; i< items ; i++)
+ {
+ commands.append( _commands->text(i) );
+ commandNames.append( _commandNames->text(i) );
+ }
+}
+
+void CmdEdit::addCmd()
+{
+ QString cmd = _cmdEdit->text();
+ QString cmdName = _cmdNameEdit->text();
+ _cmdEdit->clear();
+ _cmdNameEdit->clear();
+
+ if(_commands->currentText() == cmd || _commandNames->currentText() == cmdName)
+ {
+ int current = _commands->currentItem();
+ _commands->changeItem(cmd,current);
+ _commandNames->changeItem(cmdName,current);
+ }
+ else
+ {
+ _commands->insertItem(cmd);
+ _commandNames->insertItem(cmdName);
+ }
+
+ emit widgetChanged();
+}
+
+void CmdEdit::removeCmd()
+{
+ int current=_commands->currentItem();
+
+ _commands->removeItem(current);
+ _commandNames->removeItem(current);
+
+ if(_commands->count() == 0)
+ {
+ _removeButton->setEnabled(false);
+ _editButton->setEnabled(false);
+ _upButton->setEnabled(false);
+ _downButton->setEnabled(false);
+ }
+ else
+ {
+ if(current > (int)_commands->count()-1)
+ current=_commands->count()-1;
+
+ _commands->setSelected(current,true);
+ _commandNames->setSelected(current,true);
+ cmdHighlighted(current);
+ }
+
+ emit widgetChanged();
+}
+
+void CmdEdit::upCmd()
+{
+ QString cmd = _commands->currentText();
+ QString cmdName = _commandNames->currentText();
+ int index=_commands->currentItem();
+
+ _commands->removeItem(index);
+ _commandNames->removeItem(index);
+
+ _commands->insertItem(cmd , index-1);
+ _commandNames->insertItem(cmdName , index-1);
+
+ _commands->clearSelection();
+ _commandNames->clearSelection();
+
+ _commands->setSelected(index-1,true);
+ _commandNames->setSelected(index-1,true);
+
+ cmdHighlighted(index-1);
+
+ emit widgetChanged();
+}
+
+void CmdEdit::downCmd()
+{
+ QString cmd = _commands->currentText();
+ QString cmdName = _commandNames->currentText();
+ int index=_commands->currentItem();
+
+ _commands->removeItem(index);
+ _commandNames->removeItem(index);
+
+ _commands->insertItem(cmd , index+1);
+ _commandNames->insertItem(cmdName , index+1);
+
+ _commands->clearSelection();
+ _commandNames->clearSelection();
+
+ _commands->setSelected(index+1,true);
+ _commandNames->setSelected(index+1,true);
+
+ cmdHighlighted(index+1);
+
+ emit widgetChanged();
+}
+
+void CmdEdit::cmdHighlighted(int index)
+{
+ _commandNames->blockSignals(true);
+ _commandNames->setCurrentItem(index);
+ _commandNames->blockSignals(false);
+
+ _removeButton->setEnabled(true);
+ _editButton->setEnabled(true);
+
+ if(index == (int)(_commands->count()-1))
+ _downButton->setEnabled(false);
+ else
+ _downButton->setEnabled(true);
+
+ if(index==0)
+ _upButton->setEnabled(false);
+ else
+ _upButton->setEnabled(true);
+
+}
+
+void CmdEdit::cmdNameHighlighted(int index)
+{
+ _commands->blockSignals(true);
+ _commands->setCurrentItem(index);
+ _commands->blockSignals(false);
+
+ _removeButton->setEnabled(true);
+ _editButton->setEnabled(true);
+
+ if(index == (int)(_commands->count()-1))
+ _downButton->setEnabled(false);
+ else
+ _downButton->setEnabled(true);
+
+ if(index==0)
+ _upButton->setEnabled(false);
+ else
+ _upButton->setEnabled(true);
+}
+
+void CmdEdit::editCmd()
+{
+ _cmdEdit->setText(_commands->currentText());
+ _cmdNameEdit->setText(_commandNames->currentText());
+
+ emit widgetChanged();
+}
+
+void CmdEdit::checkAdd()
+{
+ _addButton->setEnabled( !(_cmdEdit->text().isEmpty() || _cmdNameEdit->text().isEmpty()) );
+}
+
+#include "cmdedit.moc"
diff --git a/kbabel/commonui/cmdedit.h b/kbabel/commonui/cmdedit.h
new file mode 100644
index 00000000..dc61679b
--- /dev/null
+++ b/kbabel/commonui/cmdedit.h
@@ -0,0 +1,94 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef CMDEDIT_H
+#define CMDEDIT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qwidget.h>
+#include <qstringlist.h>
+
+class QListBox;
+class QLineEdit;
+class QPushButton;
+class QToolButton;
+
+class CmdEdit : public QWidget
+{
+ Q_OBJECT
+public:
+ CmdEdit(QWidget* parent=0,const char* name=0);
+
+ void setCommands(const QStringList& commands,const QStringList& commandNames);
+ void commands(QStringList& commands, QStringList& commandNames);
+
+signals:
+ void widgetChanged();
+
+private slots:
+ /**
+ * reads command and commandName from the line edits and
+ * inserts them at the end of the listbox
+ */
+ void addCmd();
+ /**
+ * removes the currently selected command and commandName from the listbox
+ */
+ void removeCmd();
+
+ void upCmd();
+ void downCmd();
+
+ void editCmd();
+ void cmdHighlighted(int index);
+ void cmdNameHighlighted(int index);
+
+ void checkAdd();
+
+private:
+ QListBox* _commands;
+ QListBox* _commandNames;
+
+ QLineEdit* _cmdEdit;
+ QLineEdit* _cmdNameEdit;
+
+ QPushButton* _addButton;
+ QPushButton* _editButton;
+ QPushButton* _removeButton;
+ QToolButton* _upButton;
+ QToolButton* _downButton;
+};
+
+#endif // CMDEDIT_H
diff --git a/kbabel/commonui/context.cpp b/kbabel/commonui/context.cpp
new file mode 100644
index 00000000..db468795
--- /dev/null
+++ b/kbabel/commonui/context.cpp
@@ -0,0 +1,305 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002-2005 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include "context.h"
+#include "klisteditor.h"
+#include "kbprojectsettings.h"
+
+#include <qcombobox.h>
+#include <qfileinfo.h>
+#include <qframe.h>
+#include <qhbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qlistbox.h>
+#include <qpushbutton.h>
+#include <qregexp.h>
+#include <qvgroupbox.h>
+
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kdialog.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kurl.h>
+#include <kdeversion.h>
+#include <kio/netaccess.h>
+
+#include <klibloader.h>
+#include <ktrader.h>
+#include <ktexteditor/document.h>
+#include <ktexteditor/editinterface.h>
+#include <ktexteditor/selectioninterface.h>
+#include <ktexteditor/viewcursorinterface.h>
+
+SourceContext::SourceContext(QWidget *parent, KBabel::Project::Ptr project): QWidget(parent)
+ , m_parent( parent )
+ , _part(0)
+ , _view(0)
+ , _referenceCombo(0)
+ , _layout(0)
+ , _project(project)
+{
+ _referenceList.clear();
+ _referenceCombo = new QComboBox( this );
+ connect( _referenceCombo, SIGNAL(activated(int)), this, SLOT(updateToSelected(int)));
+
+ _layout= new QVBoxLayout(this);
+ _layout->addWidget(_referenceCombo);
+}
+
+void SourceContext::setContext( const QString& packageDir, const QString& packageName, const QString& gettextComment, const KURL& urlPoFile )
+{
+ if( !_part && !loadPart() ) return;
+ _referenceCombo->clear();
+ _referenceList = resolvePath( packageDir, packageName, gettextComment, urlPoFile );
+
+ for( QValueList<ContextInfo>::const_iterator it = _referenceList.constBegin(); it != _referenceList.constEnd(); ++it )
+ _referenceCombo->insertItem((*it).path);
+
+ _referenceCombo->setEnabled( !_referenceList.isEmpty() );
+ if( _referenceList.isEmpty() )
+ {
+ _part->setReadWrite( true );
+ // We have to simulate a new document (like with File/New) by using openStream and closeStream
+ _part->openStream("text/plain","kbabel:error"); // KBabel does not show the URL kbabel:error
+ _part->closeStream();
+ (dynamic_cast<KTextEditor::EditInterface *>(_part))->setText(i18n("Corresponding source file not found"));
+ _part->setReadWrite(false);
+ _part->setModified(false);
+ }
+ else
+ {
+ _referenceCombo->setCurrentItem(0);
+ updateToSelected(0);
+ }
+}
+
+void SourceContext::updateToSelected(int index)
+{
+ if( !_part ) return;
+ ContextInfo ci = *(_referenceList.at(index));
+ KURL newUrl( KURL::fromPathOrURL( ci.path ) );
+ if( _part->url() != newUrl )
+ {
+ _part->setReadWrite( true );
+ _part->openURL( newUrl );
+ }
+ _part->setReadWrite( false );
+ (dynamic_cast<KTextEditor::ViewCursorInterface *>(_view))->setCursorPosition(ci.line,0);
+ (dynamic_cast<KTextEditor::SelectionInterface *>(_part))->setSelection(ci.line-1,0,ci.line,0);
+}
+
+QValueList<ContextInfo> SourceContext::resolvePath( const QString& packageDir, const QString& packageName, const QString& gettextComment, const KURL& urlPoFile )
+{
+ //kdDebug() << "GETTEXTCOMMENT:" << gettextComment << endl;
+
+ // Find the directory name of the PO file, if the PO file is local
+ // ### TODO: find a way to allow remote files too
+ QString poDir;
+#if KDE_IS_VERSION( 3, 5, 0 )
+ const KURL localUrl( KIO::NetAccess::mostLocalURL( urlPoFile, m_parent ) );
+ if ( localUrl.isLocalFile() )
+ {
+ const QFileInfo fi( localUrl.path() );
+ poDir = fi.dirPath( true );
+ }
+#else
+ if ( urlPoFile.isLocalFile() )
+ {
+ const QFileInfo fi( urlPoFile.path() );
+ poDir = fi.dirPath( true );
+ }
+#endif
+
+#if 0
+ kdDebug() << "CONTEXT VARIABLE START" << endl;
+ kdDebug() << "@CODEROOT@: " << _project->settings()->codeRoot() << endl;
+ kdDebug() << "@PACKAGEDIR@: " << packageDir << endl;
+ kdDebug() << "@PACKAGE@: " << packageName << endl;
+ kdDebug() << "@POFILEDIR@: " << poDir << endl;
+ kdDebug() << "CONTEXT VARIABLE END" << endl;
+#endif
+
+ QStringList prefixes;
+ const QStringList paths = _project->settings()->paths();
+
+ for( QStringList::const_iterator it = paths.constBegin(); it!=paths.constEnd() ; ++it )
+ {
+ QString pref = (*it);
+
+ if ( !poDir.isEmpty() )
+ {
+ pref.replace( "@POFILEDIR@", poDir );
+ }
+ else if ( pref.find( "@POFILEDIR@ " ) != -1 )
+ continue; // No need to keep this path pattern, as we have no PO file dir
+
+ pref.replace( "@PACKAGEDIR@", packageDir);
+ pref.replace( "@PACKAGE@", packageName);
+ pref.replace( "@CODEROOT@", _project->settings()->codeRoot());
+ prefixes.append(pref);
+ }
+
+ QValueList<ContextInfo> rawRefList; // raw references
+ QRegExp re("^\\s*(.+):(\\d+)\\s*$"); // Reg. exp. for Gettext references
+ QRegExp rex( "^#. i18n: file (.+) line (\\d+)\\s*$" ); //Reg. exp. for KDE extractrc/extractattr references
+ QRegExp res( "^# [Ff]ile: (.+), line(?: number)?: (\\d+)\\s*$"); // Reg. exp. for "strict" PO format
+ const QStringList lines = QStringList::split( "\n", gettextComment );
+ for ( QStringList::const_iterator it = lines.constBegin() ; it != lines.constEnd() ; ++it)
+ {
+ const QString curLine = (*it).stripWhiteSpace();
+ if( curLine.startsWith( "#:" ) )
+ {
+ // We have a Gettext line with references
+ const QStringList references( QStringList::split( " ", curLine.mid( 2 ), false ) );
+ for ( QStringList::const_iterator it = references.constBegin(); it != references.constEnd(); ++it )
+ {
+ if ( re.exactMatch( (*it) ) )
+ {
+ ContextInfo ref;
+ ref.line = re.cap(2).toInt();
+ ref.path = re.cap(1);
+ // ### TODO KDE4: perhaps we should not do the replace if compiled for Windows
+ ref.path.replace( QChar( '\\' ), QChar( '/' ) );
+ rawRefList.append( ref );
+ }
+ }
+
+ }
+ else if ( curLine.startsWith( "#," ) )
+ {
+ // We have a Gettext option line. There is no source reference here.
+ continue;
+ }
+ else if ( curLine.startsWith( "#. i18n:") )
+ {
+ // We might have a KDE reference from extractrc/extractattr
+ if ( rex.exactMatch( (*it) ) )
+ {
+ ContextInfo ref;
+ ref.line = rex.cap(2).toInt();
+ ref.path = rex.cap(1);
+ // KDE is not extracted on Windows, so no backslash conversion is needed.
+ rawRefList.append( ref );
+ }
+ }
+ else if ( curLine.startsWith( "# F" ) || curLine.startsWith( "# f" ) )
+ {
+ // We might have a "strict PO" reference
+ if ( res.exactMatch( (*it) ) )
+ {
+ ContextInfo ref;
+ ref.line = res.cap(2).toInt();
+ ref.path = res.cap(1);
+ // ### TODO KDE4: perhaps we should not do the replace if compiled for Windows
+ ref.path.replace( QChar( '\\' ), QChar( '/' ) );
+ rawRefList.append( ref );
+ }
+ }
+ else
+ continue;
+ }
+
+ // Now that we have gathered the references, we need to convert them to absolute paths
+ QValueList<ContextInfo> results;
+ for ( QValueList<ContextInfo>::const_iterator it = rawRefList.constBegin(); it != rawRefList.constEnd(); ++it )
+ {
+ const int lineNum = (*it).line;
+ const QString fileName = (*it).path;
+ for ( QStringList::const_iterator it1 = prefixes.constBegin(); it1 != prefixes.constEnd(); ++it1 )
+ {
+ QString path = (*it1);
+ path.replace( "@COMMENTPATH@", fileName);
+
+ //kdDebug() << "CONTEXT PATH: " << path << endl; // DEBUG
+ QFileInfo pathInfo( path );
+ if( pathInfo.exists() )
+ {
+ ContextInfo ref;
+ ref.path = pathInfo.absFilePath();
+ ref.line = lineNum;
+ results.append(ref);
+ }
+ }
+ }
+
+ return results;
+}
+
+bool SourceContext::loadPart()
+{
+ KTrader::OfferList offers = KTrader::self()->query( "KTextEditor/Document" );
+ if( offers.count() < 1 )
+ {
+ KMessageBox::error(this,i18n("KBabel cannot start a text editor component.\n"
+ "Please check your KDE installation."));
+ _part=0;
+ _view=0;
+ return false;
+ }
+ KService::Ptr service = *offers.begin();
+ KLibFactory *factory = KLibLoader::self()->factory( service->library().latin1() );
+ if( !factory )
+ {
+ KMessageBox::error(this,i18n("KBabel cannot start a text editor component.\n"
+ "Please check your KDE installation."));
+ _part=0;
+ _view=0;
+ return false;
+ }
+ _part = static_cast<KTextEditor::Document *>( factory->create( this, 0, "KTextEditor::Document" ) );
+
+ if( !_part )
+ {
+ KMessageBox::error(this,i18n("KBabel cannot start a text editor component.\n"
+ "Please check your KDE installation."));
+ _part=0;
+ _view=0;
+ return false;
+ }
+ _view = _part->createView( this, 0 );
+ _layout->addWidget(static_cast<QWidget *>(_view), 1);
+ static_cast<QWidget *>(_view)->show();
+
+ return true;
+}
+
+void SourceContext::setProject( KBabel::Project::Ptr project )
+{
+ _project = project;
+}
+
+#include "context.moc"
+
+// kate: space-indent on; indent-width 4; replace-tabs on;
diff --git a/kbabel/commonui/context.h b/kbabel/commonui/context.h
new file mode 100644
index 00000000..2ccceecd
--- /dev/null
+++ b/kbabel/commonui/context.h
@@ -0,0 +1,123 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002-2005 Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef CONTEXT_H
+#define CONTEXT_H
+
+#include <qvaluelist.h>
+#include <qwidget.h>
+
+#include <ktexteditor/document.h>
+#include <ktexteditor/view.h>
+
+#include <kbproject.h>
+
+class QComboBox;
+class QVBoxLayout;
+class QLineEdit;
+class KListEditor;
+class KConfig;
+class KURL;
+
+struct ContextInfo
+{
+ QString path;
+ uint line;
+};
+
+/**
+ * @short Class for displaying source code context
+ *
+ * Widget for displaying source code context of for the given GNU gettext comment.
+ * The searched paths can be configured using variables.
+ *
+ * The possible variables are:
+ * - \@POFILEDIR\@ absolute directory of the PO file (to create paths relatives to the PO file)
+ * - \@PACKAGE\@ name of the PO file
+ * - \@PACKAGEDIR\@ relative directory of the PO file (relative to \@CODEROOT\@)
+ * - \@CODEROOT\@ base directory (especially of the catalog manager)
+ * - \@COMMENTPATH\@ (relative) path given as source code reference in a comment of the PO file
+ *
+ * @note The difference between \@POFILEDIR\@ and a path constructed by
+ * \@CODEROOT\@\@PACKAGEDIR\@/ is that \@POFILEDIR\@ will also work if the file is external
+ * to the catalog manager's root
+ *
+ * @note It requires a KPart implementing KTextEditor interface with selections.
+ * @author Stanislav Visnovsky <visnovsky@kde.org>
+ */
+class KDE_EXPORT SourceContext : public QWidget
+{
+ Q_OBJECT
+public:
+ SourceContext(QWidget* parent, KBabel::Project::Ptr project);
+
+ void setProject(KBabel::Project::Ptr project);
+
+public slots:
+ /**
+ * Try to find the corresponding file and load it to this widget.
+ * @param packageDir path of the package, where to find the source file
+ * @param packageName name of the package, where to find the source file
+ * @param gettextComment comment string with context as generated by xgettext (can start with #:)
+ * @param urlPoFile URL of the PO file
+ * @todo even if @p urlPoFile is an URL SourceContext::resolvePath is not remote-aware yet
+ */
+ void setContext( const QString& packageDir, const QString& packageName, const QString& gettextComment, const KURL& urlPoFile );
+
+private:
+ /**
+ * Get a list of paths from the source references in the comment @p gettextComment
+ * @param packageDir path of the package, where to find the source file
+ * @param packageName name of the package, where to find the source file
+ * @param gettextComment comment string with context as generated by xgettext (can start with #:)
+ * @param urlPoFile URL of the PO file
+ * @todo even if @p urlPoFile is an URL SourceContext::resolvePath is not remote-aware yet
+ * @private
+ */
+ QValueList<ContextInfo> resolvePath( const QString& packageDir, const QString& packageName, const QString& gettextComment, const KURL& urlPoFile );
+ bool loadPart();
+
+ /// Parent widget (for KIO::NetAccess member functions)
+ QWidget* m_parent;
+ KTextEditor::Document* _part;
+ KTextEditor::View* _view;
+ QComboBox *_referenceCombo;
+ QVBoxLayout *_layout;
+
+ QValueList<ContextInfo> _referenceList;
+
+ KBabel::Project::Ptr _project;
+private slots:
+ void updateToSelected(int index);
+};
+
+#endif // CONTEXT_H
diff --git a/kbabel/commonui/diffpreferences.ui b/kbabel/commonui/diffpreferences.ui
new file mode 100644
index 00000000..a3ea5a4e
--- /dev/null
+++ b/kbabel/commonui/diffpreferences.ui
@@ -0,0 +1,141 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>DiffPreferences</class>
+<author>Stanislav Visnovsky</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>DiffPreferences</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>538</width>
+ <height>462</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>kcfg_UseDBForDiff</cstring>
+ </property>
+ <property name="title">
+ <string>Diff Source</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;&lt;p&gt;&lt;b&gt;Source for difference lookup&lt;/b&gt;&lt;/p&gt;
+&lt;p&gt;Here you can select a source, which should be used
+for finding a difference.&lt;/p&gt;
+&lt;p&gt;You can select file, translation database or
+corresponding msgstr.&lt;/p&gt;
+&lt;p&gt;If you choose the translation database, the messages to diff with are
+taken from the Translation Database; to be useful, you have
+to enable &lt;i&gt;Auto add entry to database&lt;/i&gt; in its
+preferences dialog.&lt;/p&gt;
+&lt;p&gt;The last option is useful for those using PO-files
+for proofreading.&lt;/p&gt;
+&lt;p&gt;You can temporarily diff with messages from a file
+by choosing &lt;i&gt;Tools-&gt;Diff-&gt;Open file for diff&lt;/i&gt;
+in KBabel's main window.&lt;/p&gt;&lt;/qt&gt;</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>radioButton1</cstring>
+ </property>
+ <property name="text">
+ <string>Use &amp;file</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>radioButton2</cstring>
+ </property>
+ <property name="text">
+ <string>Use messages from &amp;translation database</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>radioButton3</cstring>
+ </property>
+ <property name="text">
+ <string>Use &amp;msgstr from the same file</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Base folder for diff files:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_DiffBaseDir</cstring>
+ </property>
+ </widget>
+ <widget class="KURLRequester">
+ <property name="name">
+ <cstring>kcfg_DiffBaseDir</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;&lt;q&gt;&lt;b&gt;Base folder for diff files&lt;/b&gt;&lt;/q&gt;
+&lt;p&gt;Here you can define a folder in which the files to
+diff with are stored. If the files are stored at the same
+place beneath this folder as the original files beneath
+their base folder, KBabel can automatically open the correct
+file to diff with.&lt;/p&gt;
+&lt;p&gt;Note that this option has no effect if messages from
+the database are used for diffing.&lt;/p&gt;&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <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>31</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<includes>
+ <include location="local" impldecl="in implementation">diffpreferences.ui.h</include>
+</includes>
+<functions>
+ <function>init()</function>
+</functions>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kbabel/commonui/diffpreferences.ui.h b/kbabel/commonui/diffpreferences.ui.h
new file mode 100644
index 00000000..5b02d278
--- /dev/null
+++ b/kbabel/commonui/diffpreferences.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 functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+void DiffPreferences::init()
+{
+ kcfg_DiffBaseDir->setMode(KFile::Directory);
+}
diff --git a/kbabel/commonui/finddialog.cpp b/kbabel/commonui/finddialog.cpp
new file mode 100644
index 00000000..7335f30a
--- /dev/null
+++ b/kbabel/commonui/finddialog.cpp
@@ -0,0 +1,553 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2002 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include "finddialog.h"
+
+#include <qbuttongroup.h>
+#include <qcheckbox.h>
+#include <qgroupbox.h>
+#include <qpushbutton.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qhbox.h>
+#include <qwhatsthis.h>
+
+#include <kcombobox.h>
+#include <kconfig.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kparts/componentfactory.h>
+#include <kregexpeditorinterface.h>
+
+using namespace KBabel;
+
+FindDialog::FindDialog(bool forReplace, QWidget* parent)
+ :KDialogBase(parent, "finddialog",true, "", Ok|Cancel, Ok)
+ , _regExpEditDialog(0), _replaceDlg(forReplace)
+{
+ QWidget* page = new QWidget(this);
+ QVBoxLayout *layout = new QVBoxLayout(page, 0, spacingHint());
+
+ QLabel *label = new QLabel(i18n("&Find:"),page);
+ layout->addWidget(label);
+
+ _findCombo = new KComboBox(true, page, "findCombo");
+ _findCombo->setMaxCount(10);
+ _findCombo->setInsertionPolicy(KComboBox::AtTop);
+ layout->addWidget(_findCombo);
+ label->setBuddy(_findCombo);
+
+ QString msg=i18n("<qt><p><b>Find text</b></p>"
+ "<p>Here you can enter the text you want to search for. "
+ "If you want to search for a regular expression, "
+ "enable <b>Use regular expression</b> below.</p></qt>");
+
+
+ QWhatsThis::add(label,msg);
+ QWhatsThis::add(_findCombo,msg);
+
+ if(forReplace) {
+ setCaption(i18n("Replace"));
+ setButtonOK(i18n("&Replace"));
+
+ _replaceLabel = new QLabel(i18n("&Replace with:"),page);
+ layout->addWidget(_replaceLabel);
+ _replaceCombo = new KComboBox(true, page, "replaceCombo");
+ _replaceCombo->setMaxCount(10);
+ _replaceCombo->setInsertionPolicy(KComboBox::AtTop);
+ layout->addWidget(_replaceCombo);
+ _replaceLabel->setBuddy(_replaceCombo);
+
+ msg=i18n("<qt><p><b>Replace text</b></p>"
+ "<p>Here you can enter the text you want the found text to get "
+ "replaced with. The text is used as is. It is not possible to make a back "
+ "reference, if you have searched for a regular expression.</p></qt>");
+
+ QWhatsThis::add(_replaceLabel,msg);
+ QWhatsThis::add(_replaceCombo,msg);
+ }
+ else {
+ setCaption(i18n("Find"));
+ setButtonOK(KGuiItem(i18n("&Find"),"find"));
+
+ _replaceLabel=0;
+ _replaceCombo=0;
+ }
+
+ _buttonGrp = new QButtonGroup(3, Qt::Horizontal, i18n("Where to Search"), page);
+ connect(_buttonGrp,SIGNAL(clicked(int)), this, SLOT(inButtonsClicked(int)));
+ layout->addWidget(_buttonGrp);
+
+ _inMsgid = new QCheckBox(i18n("&Msgid"),_buttonGrp);
+ _inMsgstr = new QCheckBox(i18n("M&sgstr"),_buttonGrp);
+ _inComment = new QCheckBox(i18n("Comm&ent"),_buttonGrp);
+
+ QWhatsThis::add(_buttonGrp,i18n("<qt><p><b>Where to search</b></p>"
+ "<p>Select here in which parts of a catalog entry you want "
+ "to search.</p></qt>"));
+
+
+ QGroupBox* box = new QGroupBox(2, Qt::Horizontal, i18n("Options"), page);
+ layout->addWidget(box);
+
+ _caseSensitive = new QCheckBox(i18n("C&ase sensitive"),box);
+ _wholeWords = new QCheckBox(i18n("O&nly whole words"),box);
+ _ignoreAccelMarker = new QCheckBox(i18n("I&gnore marker for keyboard accelerator"),box);
+ _ignoreContextInfo = new QCheckBox(i18n("Ignore con&text information"),box);
+ _fromCursor = new QCheckBox(i18n("From c&ursor position"),box);
+ _backwards = new QCheckBox(i18n("F&ind backwards"),box);
+
+ QHBox *regexp = new QHBox(box);
+
+ _isRegExp = new QCheckBox(i18n("Use regu&lar expression"),regexp);
+ _regExpButton = 0;
+
+ if( !KTrader::self()->query("KRegExpEditor/KRegExpEditor").isEmpty() )
+ {
+ _regExpButton = new QPushButton( i18n("&Edit..."), regexp );
+ connect( _regExpButton, SIGNAL( clicked() ), this, SLOT( regExpButtonClicked()));
+ connect( _isRegExp, SIGNAL( toggled(bool) ), _regExpButton, SLOT(setEnabled(bool)));
+ }
+
+ if(forReplace)
+ {
+ _inMsgid->setEnabled(false);
+ _askForReplace = new QCheckBox(i18n("As&k before replacing"),box);
+ _ignoreContextInfo->setEnabled(false);
+
+ QWhatsThis::add(box,i18n("<qt><p><b>Options</b></p>"
+ "<p>Here you can finetune replacing:"
+ "<ul><li><b>Case sensitive</b>: does case of entered text have to be respected?</li>"
+ "<li><b>Only whole words</b>: text found must not be part of a longer word</li>"
+ "<li><b>From cursor position</b>: start replacing at the part of the document where "
+ "the cursor is. Otherwise replacing is started at the beginning or the end.</li>"
+ "<li><b>Find backwards</b>: Should be self-explanatory.</li>"
+ "<li><b>Use regular expression</b>: use text entered in field <b>Find</b> "
+ "as a regular expression. This option has no effect with the replace text, especially "
+ "no back references are possible.</li>"
+ "<li><b>Ask before replacing</b>: Enable, if you want to have control about "
+ "what is replaced. Otherwise all found text is replaced without asking.</li>"
+ "</ul></p></qt>"));
+ }
+ else {
+ _askForReplace=0;
+
+ QWhatsThis::add(box,i18n("<qt><p><b>Options</b></p>"
+ "<p>Here you can finetune the search:"
+ "<ul><li><b>Case sensitive</b>: does case of entered text have to be respected?</li>"
+ "<li><b>Only whole words</b>: text found must not be part of a longer word</li>"
+ "<li><b>From cursor position</b>: start search at the part of the document, where "
+ "the cursor is. Otherwise search is started at the beginning or the end.</li>"
+ "<li><b>Find backwards</b>: Should be self-explanatory.</li>"
+ "<li><b>Use regular expression</b>: use entered text as a regular expression.</li>"
+ "</ul></p></qt>"));
+ }
+
+
+ readSettings();
+
+
+ setMainWidget(page);
+}
+
+FindDialog::~FindDialog()
+{
+ saveSettings();
+}
+
+int FindDialog::show(QString initialStr)
+{
+ if( !initialStr.isEmpty() ) {
+ _findCombo->setEditText( initialStr );
+ }
+ _findCombo->lineEdit()->selectAll();
+ _findCombo->setFocus();
+
+
+ KDialogBase::show();
+
+ int r = result();
+
+ if( r == QDialog::Accepted ) {
+ if(_replaceDlg) {
+ _replaceList.remove(_replaceCombo->currentText());
+ _replaceList.prepend(_replaceCombo->currentText());
+ if(_replaceList.count() > 10 )
+ _replaceList.remove(_replaceList.fromLast());
+
+ _replaceCombo->clear();
+ _replaceCombo->insertStringList(_replaceList);
+
+ _replaceFindList.remove(_findCombo->currentText());
+ _replaceFindList.prepend(_findCombo->currentText());
+ if(_replaceFindList.count() > 10 )
+ _replaceFindList.remove(_replaceFindList.fromLast());
+
+ _findCombo->clear();
+ _findCombo->insertStringList(_replaceFindList);
+
+ _replaceOptions.findStr = _findCombo->currentText();
+ _replaceOptions.replaceStr = _replaceCombo->currentText();
+
+ _replaceOptions.inMsgstr = _inMsgstr->isChecked();
+ _replaceOptions.inComment = _inComment->isChecked();
+ _replaceOptions.inMsgid = false;
+
+ _replaceOptions.caseSensitive = _caseSensitive->isChecked();
+ _replaceOptions.wholeWords = _wholeWords->isChecked();
+ _replaceOptions.ignoreAccelMarker = _ignoreAccelMarker->isChecked();
+ _replaceOptions.ignoreContextInfo = false;
+ _replaceOptions.backwards = _backwards->isChecked();
+ _replaceOptions.fromCursor = _fromCursor->isChecked();
+ _replaceOptions.isRegExp = _isRegExp->isChecked();
+ _replaceOptions.ask = _askForReplace->isChecked();
+ }
+ else {
+ _findList.remove(_findCombo->currentText());
+ _findList.prepend(_findCombo->currentText());
+ if(_findList.count() > 10 )
+ _findList.remove(_findList.fromLast());
+
+ _findCombo->clear();
+ _findCombo->insertStringList(_findList);
+
+ _findOptions.findStr = _findCombo->currentText();
+ _findOptions.inMsgid = _inMsgid->isChecked();
+ _findOptions.inMsgstr = _inMsgstr->isChecked();
+ _findOptions.inComment = _inComment->isChecked();
+
+ _findOptions.caseSensitive = _caseSensitive->isChecked();
+ _findOptions.wholeWords = _wholeWords->isChecked();
+ _findOptions.ignoreAccelMarker = _ignoreAccelMarker->isChecked();
+ _findOptions.ignoreContextInfo = _ignoreContextInfo->isChecked();
+ _findOptions.backwards = _backwards->isChecked();
+ _findOptions.fromCursor = _fromCursor->isChecked();
+ _findOptions.isRegExp = _isRegExp->isChecked();
+ }
+ }
+
+ return r;
+}
+
+int FindDialog::exec(QString initialStr)
+{
+ if( !initialStr.isEmpty() ) {
+ _findCombo->setEditText( initialStr );
+ }
+ _findCombo->lineEdit()->selectAll();
+ _findCombo->setFocus();
+
+
+ KDialogBase::exec();
+
+ int r = result();
+
+ if( r == QDialog::Accepted ) {
+ if(_replaceDlg) {
+ _replaceList.remove(_replaceCombo->currentText());
+ _replaceList.prepend(_replaceCombo->currentText());
+ if(_replaceList.count() > 10 )
+ _replaceList.remove(_replaceList.fromLast());
+
+ _replaceCombo->clear();
+ _replaceCombo->insertStringList(_replaceList);
+
+ _replaceFindList.remove(_findCombo->currentText());
+ _replaceFindList.prepend(_findCombo->currentText());
+ if(_replaceFindList.count() > 10 )
+ _replaceFindList.remove(_replaceFindList.fromLast());
+
+ _findCombo->clear();
+ _findCombo->insertStringList(_replaceFindList);
+
+ _replaceOptions.findStr = _findCombo->currentText();
+ _replaceOptions.replaceStr = _replaceCombo->currentText();
+
+ _replaceOptions.inMsgstr = _inMsgstr->isChecked();
+ _replaceOptions.inComment = _inComment->isChecked();
+ _replaceOptions.inMsgid = false;
+
+ _replaceOptions.caseSensitive = _caseSensitive->isChecked();
+ _replaceOptions.wholeWords = _wholeWords->isChecked();
+ _replaceOptions.ignoreAccelMarker = _ignoreAccelMarker->isChecked();
+ _replaceOptions.ignoreContextInfo = false;
+ _replaceOptions.backwards = _backwards->isChecked();
+ _replaceOptions.fromCursor = _fromCursor->isChecked();
+ _replaceOptions.isRegExp = _isRegExp->isChecked();
+ _replaceOptions.ask = _askForReplace->isChecked();
+ }
+ else {
+ _findList.remove(_findCombo->currentText());
+ _findList.prepend(_findCombo->currentText());
+ if(_findList.count() > 10 )
+ _findList.remove(_findList.fromLast());
+
+ _findCombo->clear();
+ _findCombo->insertStringList(_findList);
+
+ _findOptions.findStr = _findCombo->currentText();
+ _findOptions.inMsgid = _inMsgid->isChecked();
+ _findOptions.inMsgstr = _inMsgstr->isChecked();
+ _findOptions.inComment = _inComment->isChecked();
+
+ _findOptions.caseSensitive = _caseSensitive->isChecked();
+ _findOptions.wholeWords = _wholeWords->isChecked();
+ _findOptions.ignoreAccelMarker = _ignoreAccelMarker->isChecked();
+ _findOptions.ignoreContextInfo = _ignoreContextInfo->isChecked();
+ _findOptions.backwards = _backwards->isChecked();
+ _findOptions.fromCursor = _fromCursor->isChecked();
+ _findOptions.isRegExp = _isRegExp->isChecked();
+ }
+ }
+
+ return r;
+}
+
+FindOptions FindDialog::findOpts()
+{
+ return _findOptions;
+}
+
+void FindDialog::setFindOpts(FindOptions options)
+{
+ _findOptions = options;
+ _inMsgid->setChecked(_findOptions.inMsgid);
+ _inMsgstr->setChecked(_findOptions.inMsgstr);
+ _inComment->setChecked(_findOptions.inComment);
+
+ _caseSensitive->setChecked(_findOptions.caseSensitive);
+ _wholeWords->setChecked(_findOptions.wholeWords);
+ _ignoreAccelMarker->setChecked(_findOptions.ignoreAccelMarker);
+ _ignoreContextInfo->setChecked(_findOptions.ignoreContextInfo);
+ _backwards->setChecked(_findOptions.backwards);
+ _fromCursor->setChecked(_findOptions.fromCursor);
+ _isRegExp->setChecked(_findOptions.isRegExp);
+ if( _regExpButton ) _regExpButton->setEnabled( _findOptions.isRegExp );
+
+ _findCombo->setEditText(_findOptions.findStr);
+}
+
+ReplaceOptions FindDialog::replaceOpts()
+{
+ return _replaceOptions;
+}
+
+void FindDialog::setReplaceOpts(ReplaceOptions options)
+{
+ _replaceOptions = options;
+ _inMsgid->setChecked(_replaceOptions.inMsgid);
+ _inMsgstr->setChecked(_replaceOptions.inMsgstr);
+ _inComment->setChecked(_replaceOptions.inComment);
+
+ _caseSensitive->setChecked(_replaceOptions.caseSensitive);
+ _wholeWords->setChecked(_replaceOptions.wholeWords);
+ _ignoreAccelMarker->setChecked(_replaceOptions.ignoreAccelMarker);
+ _ignoreContextInfo->setChecked(_replaceOptions.ignoreContextInfo);
+ _backwards->setChecked(_replaceOptions.backwards);
+ _fromCursor->setChecked(_replaceOptions.fromCursor);
+ _isRegExp->setChecked(_replaceOptions.isRegExp);
+ _askForReplace->setChecked(_replaceOptions.ask);
+ if( _regExpButton ) _regExpButton->setEnabled( _replaceOptions.isRegExp );
+
+ _findCombo->setEditText(_replaceOptions.findStr);
+ _replaceCombo->setEditText(_replaceOptions.replaceStr);
+}
+
+void FindDialog::readSettings()
+{
+ KConfig* config = KGlobal::config();
+
+ if(_replaceDlg) {
+ KConfigGroupSaver cgs(config,"ReplaceDialog");
+ _replaceOptions.inMsgstr = config->readBoolEntry("InMsgstr",true);
+ _replaceOptions.inComment = config->readBoolEntry("InComment",false);
+
+ _replaceOptions.caseSensitive =
+ config->readBoolEntry("CaseSensitive",true);
+ _replaceOptions.wholeWords = config->readBoolEntry("WholeWords",false);
+ _replaceOptions.ignoreAccelMarker =
+ config->readBoolEntry("IgnoreAccelMarker",true);
+ _replaceOptions.backwards = config->readBoolEntry("Backwards",false);
+ _replaceOptions.fromCursor = config->readBoolEntry("FromCursor",true);
+ _replaceOptions.isRegExp = config->readBoolEntry("RegExp",false);
+ _replaceOptions.ask = config->readBoolEntry("AskForReplace",true);
+ _replaceFindList = config->readListEntry("FindList");
+ _replaceList = config->readListEntry("ReplaceList");
+
+ _inMsgstr->setChecked(_replaceOptions.inMsgstr);
+ _inComment->setChecked(_replaceOptions.inComment);
+
+ _caseSensitive->setChecked(_replaceOptions.caseSensitive);
+ _wholeWords->setChecked(_replaceOptions.wholeWords);
+ _ignoreAccelMarker->setChecked(_findOptions.ignoreAccelMarker);
+ _backwards->setChecked(_replaceOptions.backwards);
+ _fromCursor->setChecked(_replaceOptions.fromCursor);
+ _isRegExp->setChecked(_replaceOptions.isRegExp);
+ _askForReplace->setChecked(_replaceOptions.ask);
+ if( _regExpButton ) _regExpButton->setEnabled( _findOptions.isRegExp );
+
+ _replaceCombo->insertStringList(_replaceList);
+ _findCombo->insertStringList(_replaceFindList);
+ }
+ else {
+ KConfigGroupSaver cgs(config,"FindDialog");
+
+ _findOptions.inMsgid = config->readBoolEntry("InMsgid",true);
+ _findOptions.inMsgstr = config->readBoolEntry("InMsgstr",true);
+ _findOptions.inComment = config->readBoolEntry("InComment",false);
+
+ _findOptions.caseSensitive = config->readBoolEntry("CaseSensitive"
+ ,false);
+ _findOptions.wholeWords = config->readBoolEntry("WholeWords",false);
+ _findOptions.ignoreAccelMarker =
+ config->readBoolEntry("IgnoreAccelMarker",true);
+ _findOptions.ignoreContextInfo =
+ config->readBoolEntry("IgnoreContextInfo",true);
+ _findOptions.backwards = config->readBoolEntry("Backwards",false);
+ _findOptions.fromCursor = config->readBoolEntry("FromCursor",false);
+ _findOptions.isRegExp = config->readBoolEntry("RegExp",false);
+ _findList = config->readListEntry("List");
+ if( _regExpButton ) _regExpButton->setEnabled( _findOptions.isRegExp );
+
+ _inMsgid->setChecked(_findOptions.inMsgid);
+ _inMsgstr->setChecked(_findOptions.inMsgstr);
+ _inComment->setChecked(_findOptions.inComment);
+
+ _caseSensitive->setChecked(_findOptions.caseSensitive);
+ _wholeWords->setChecked(_findOptions.wholeWords);
+ _ignoreAccelMarker->setChecked(_findOptions.ignoreAccelMarker);
+ _ignoreContextInfo->setChecked(_findOptions.ignoreContextInfo);
+ _backwards->setChecked(_findOptions.backwards);
+ _fromCursor->setChecked(_findOptions.fromCursor);
+ _isRegExp->setChecked(_findOptions.isRegExp);
+
+ _findCombo->insertStringList(_findList);
+ }
+
+}
+
+void FindDialog::saveSettings()
+{
+ KConfig* config = KGlobal::config();
+
+ if(_replaceDlg) {
+ KConfigGroupSaver cgs(config,"ReplaceDialog");
+ config->writeEntry("InMsgstr",_replaceOptions.inMsgstr);
+ config->writeEntry("InComment",_replaceOptions.inComment);
+
+ config->writeEntry("CaseSensitive",_replaceOptions.caseSensitive);
+ config->writeEntry("WholeWords",_replaceOptions.wholeWords);
+ config->writeEntry("IgnoreAccelMarker"
+ ,_replaceOptions.ignoreAccelMarker);
+ config->writeEntry("Backwards",_replaceOptions.backwards);
+ config->writeEntry("FromCursor",_replaceOptions.fromCursor);
+ config->writeEntry("RegExp",_replaceOptions.isRegExp);
+ config->writeEntry("AskForReplace",_replaceOptions.ask);
+ config->writeEntry("FindList",_replaceFindList);
+ config->writeEntry("ReplaceList",_replaceList);
+ }
+ else {
+ KConfigGroupSaver cgs(config,"FindDialog");
+
+ config->writeEntry("InMsgid",_findOptions.inMsgid);
+ config->writeEntry("InMsgstr",_findOptions.inMsgstr);
+ config->writeEntry("InComment",_findOptions.inComment);
+
+ config->writeEntry("CaseSensitive",_findOptions.caseSensitive);
+ config->writeEntry("WholeWords",_findOptions.wholeWords);
+ config->writeEntry("IgnoreAccelMarker"
+ ,_findOptions.ignoreAccelMarker);
+ config->writeEntry("IgnoreContextInfo"
+ ,_findOptions.ignoreContextInfo);
+ config->writeEntry("Backwards",_findOptions.backwards);
+ config->writeEntry("FromCursor",_findOptions.fromCursor);
+ config->writeEntry("RegExp",_findOptions.isRegExp);
+ config->writeEntry("List",_findList);
+ }
+}
+
+
+
+void FindDialog::inButtonsClicked(int id)
+{
+ // check if at least one button is checked
+ if(! _buttonGrp->find(id)->isOn() ) {
+ if(!_inMsgstr->isOn() && !_inComment->isOn() ) {
+ if(_inMsgid->isEnabled()) {
+ if( !_inMsgid->isOn() ) {
+ _buttonGrp->setButton(id);
+ }
+ }
+ else {
+ _buttonGrp->setButton(id);
+ }
+
+ }
+ }
+}
+
+void FindDialog::regExpButtonClicked()
+{
+ if ( _regExpEditDialog == 0 )
+ _regExpEditDialog = KParts::ComponentFactory::createInstanceFromQuery<QDialog>( "KRegExpEditor/KRegExpEditor", QString::null, this );
+
+ KRegExpEditorInterface *iface = dynamic_cast<KRegExpEditorInterface *>( _regExpEditDialog );
+ if( iface )
+ {
+ iface->setRegExp( _findCombo->currentText() );
+ if( _regExpEditDialog->exec() == QDialog::Accepted )
+ _findCombo->setCurrentText( iface->regExp() );
+ }
+}
+
+ReplaceDialog::ReplaceDialog(QWidget* parent)
+ :KDialogBase(Plain, "", Close|User1|User2|User3, User1, parent,"finddialog"
+ , true,false,i18n("&Replace"),i18n("&Goto Next"),i18n("R&eplace All"))
+{
+ QWidget* page = plainPage();
+ QVBoxLayout *layout = new QVBoxLayout(page, 0, spacingHint());
+
+ QLabel *label = new QLabel(i18n("Replace this string?"),page);
+ layout->addWidget(label);
+
+ connect(this,SIGNAL(user1Clicked()),this,SIGNAL(replace()));
+ connect(this,SIGNAL(user2Clicked()),this,SIGNAL(next()));
+ connect(this,SIGNAL(user3Clicked()),this,SIGNAL(replaceAll()));
+}
+
+ReplaceDialog::~ReplaceDialog()
+{
+}
+
+#include "finddialog.moc"
diff --git a/kbabel/commonui/finddialog.h b/kbabel/commonui/finddialog.h
new file mode 100644
index 00000000..7baa0675
--- /dev/null
+++ b/kbabel/commonui/finddialog.h
@@ -0,0 +1,136 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef FINDDIALOG_H
+#define FINDDIALOG_H
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <kdialogbase.h>
+
+class QButtonGroup;
+class QCheckBox;
+class QLabel;
+class KComboBox;
+
+#include "findoptions.h"
+
+class KDE_EXPORT FindDialog : public KDialogBase
+{
+ Q_OBJECT
+public:
+ /**
+ * Constructor
+ * @param replaceDlg flag, if this is a replace dialog
+ */
+ FindDialog(bool replaceDlg, QWidget* parent);
+ ~FindDialog();
+
+ /**
+ * shows the dialog
+ * @param initialStr string to display in find field.
+ * If empty, the last used string is used.
+ *
+ * @return the result code of the dialog
+ */
+ int show(QString initialStr);
+
+ /**
+ * executes the dialog as modal
+ * @param initialStr string to display in find field.
+ * If empty, the last used string is used.
+ *
+ * @return the result code of the dialog
+ */
+ int exec(QString initialStr);
+ KBabel::FindOptions findOpts();
+ void setFindOpts(KBabel::FindOptions options);
+ KBabel::ReplaceOptions replaceOpts();
+ void setReplaceOpts(KBabel::ReplaceOptions options);
+
+protected:
+ void readSettings();
+ void saveSettings();
+
+ bool isReplaceDialog() { return _replaceDlg; }
+
+private slots:
+ void inButtonsClicked(int id);
+ void regExpButtonClicked();
+
+private:
+ KComboBox *_findCombo;
+ KComboBox *_replaceCombo;
+ QLabel *_replaceLabel;
+
+ QButtonGroup *_buttonGrp;
+ QCheckBox *_inMsgid;
+ QCheckBox *_inMsgstr;
+ QCheckBox *_inComment;
+
+ QCheckBox *_caseSensitive;
+ QCheckBox *_wholeWords;
+ QCheckBox *_ignoreAccelMarker;
+ QCheckBox *_ignoreContextInfo;
+ QCheckBox *_backwards;
+ QCheckBox *_fromCursor;
+ QCheckBox *_isRegExp;
+ QCheckBox *_askForReplace;
+
+ QPushButton *_regExpButton;
+ QDialog *_regExpEditDialog;
+
+ KBabel::FindOptions _findOptions;
+ KBabel::ReplaceOptions _replaceOptions;
+
+ QStringList _findList;
+ QStringList _replaceFindList;
+ QStringList _replaceList;
+
+ bool _replaceDlg;
+};
+
+class KDE_EXPORT ReplaceDialog : public KDialogBase
+{
+ Q_OBJECT
+public:
+ ReplaceDialog(QWidget* parent);
+ ~ReplaceDialog();
+
+signals:
+ void replace();
+ void replaceAll();
+ void next();
+
+};
+
+#endif // FINDDIALOG_H
diff --git a/kbabel/commonui/kactionselector.cpp b/kbabel/commonui/kactionselector.cpp
new file mode 100644
index 00000000..b214a49f
--- /dev/null
+++ b/kbabel/commonui/kactionselector.cpp
@@ -0,0 +1,562 @@
+/***************************************************************************
+ KActionSelector.cpp
+ A widget for selecting and arranging actions/objects
+ -------------------
+ begin : Mon June 3 2002
+ copyright : (C) 2002 by Anders Lund
+ email : anders@alweb.dk
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ * *
+ * In addition, as a special exception, the copyright holders give *
+ * permission to link the code of this program with any edition of *
+ * the Qt library by Trolltech AS, Norway (or with modified versions *
+ * of Qt that use the same license as Qt), and distribute linked *
+ * combinations including the two. You must obey the GNU General *
+ * Public License in all respects for all of the code used other than *
+ * Qt. If you modify this file, you may extend this exception to *
+ * your version of the file, but you are not obligated to do so. If *
+ * you do not wish to do so, delete this exception statement from *
+ * your version. *
+ ***************************************************************************/
+
+#include "kactionselector.h"
+#include <resources.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kdialog.h> // for spacingHint()
+#include <kdebug.h>
+
+#include <qlistbox.h>
+#include <qtoolbutton.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qevent.h>
+#include <qwhatsthis.h>
+#include <qapplication.h>
+
+class KActionSelectorPrivate {
+ public:
+ QListBox *availableListBox, *selectedListBox;
+ QToolButton *btnAdd, *btnRemove, *btnUp, *btnDown;
+ QLabel *lAvailable, *lSelected;
+ bool moveOnDoubleClick, keyboardEnabled;
+ KActionSelector::ButtonIconSize iconSize;
+ QString addIcon, removeIcon, upIcon, downIcon;
+ KActionSelector::InsertionPolicy availableInsertionPolicy, selectedInsertionPolicy;
+ bool showUpDownButtons;
+};
+
+//BEGIN Constructor/destructor
+
+KActionSelector::KActionSelector( QWidget *parent, const char *name )
+ : QWidget( parent, name )
+{
+ d = new KActionSelectorPrivate();
+ d->moveOnDoubleClick = true;
+ d->keyboardEnabled = true;
+ d->iconSize = SmallIcon;
+ d->addIcon = QApplication::reverseLayout() ? "back" : "forward";
+ d->removeIcon = QApplication::reverseLayout() ? "forward" : "back";
+ d->upIcon = "up";
+ d->downIcon = "down";
+ d->availableInsertionPolicy = Sorted;
+ d->selectedInsertionPolicy = BelowCurrent;
+ d->showUpDownButtons = true;
+
+ //int isz = IconSize( KIcon::Small );
+
+ QHBoxLayout *lo = new QHBoxLayout( this );
+ lo->setSpacing( KDialog::spacingHint() );
+
+ QVBoxLayout *loAv = new QVBoxLayout( lo );
+ d->lAvailable = new QLabel( i18n("&Available:"), this );
+ loAv->addWidget( d->lAvailable );
+ d->availableListBox = new QListBox( this );
+ loAv->addWidget( d->availableListBox );
+ d->lAvailable->setBuddy( d->availableListBox );
+
+ QVBoxLayout *loHBtns = new QVBoxLayout( lo );
+ loHBtns->addStretch( 1 );
+ d->btnAdd = new QToolButton( this );
+ loHBtns->addWidget( d->btnAdd );
+ d->btnRemove = new QToolButton( this );
+ loHBtns->addWidget( d->btnRemove );
+ loHBtns->addStretch( 1 );
+
+ QVBoxLayout *loS = new QVBoxLayout( lo );
+ d->lSelected = new QLabel( i18n("&Selected:"), this );
+ loS->addWidget( d->lSelected );
+ d->selectedListBox = new QListBox( this );
+ loS->addWidget( d->selectedListBox );
+ d->lSelected->setBuddy( d->selectedListBox );
+
+ QVBoxLayout *loVBtns = new QVBoxLayout( lo );
+ loVBtns->addStretch( 1 );
+ d->btnUp = new QToolButton( this );
+ loVBtns->addWidget( d->btnUp );
+ d->btnDown = new QToolButton( this );
+ loVBtns->addWidget( d->btnDown );
+ loVBtns->addStretch( 1 );
+
+ loadIcons();
+
+ connect( d->btnAdd, SIGNAL(clicked()), this, SLOT(buttonAddClicked()) );
+ connect( d->btnRemove, SIGNAL(clicked()), this, SLOT(buttonRemoveClicked()) );
+ connect( d->btnUp, SIGNAL(clicked()), this, SLOT(buttonUpClicked()) );
+ connect( d->btnDown, SIGNAL(clicked()), this, SLOT(buttonDownClicked()) );
+ connect( d->availableListBox, SIGNAL(doubleClicked(QListBoxItem*)),
+ this, SLOT(itemDoubleClicked(QListBoxItem*)) );
+ connect( d->selectedListBox, SIGNAL(doubleClicked(QListBoxItem*)),
+ this, SLOT(itemDoubleClicked(QListBoxItem*)) );
+ connect( d->availableListBox, SIGNAL(currentChanged(QListBoxItem*)),
+ this, SLOT(slotCurrentChanged(QListBoxItem *)) );
+ connect( d->selectedListBox, SIGNAL(currentChanged(QListBoxItem*)),
+ this, SLOT(slotCurrentChanged(QListBoxItem *)) );
+
+ d->availableListBox->installEventFilter( this );
+ d->selectedListBox->installEventFilter( this );
+}
+
+KActionSelector::~KActionSelector()
+{
+ delete d;
+}
+
+//END Constructor/destroctor
+
+//BEGIN Public Methods
+
+QListBox *KActionSelector::availableListBox()
+{
+ return d->availableListBox;
+}
+
+QListBox *KActionSelector::selectedListBox()
+{
+ return d->selectedListBox;
+}
+
+void KActionSelector::setButtonIcon( const QString &icon, MoveButton button )
+{
+ int isz;
+ if ( d->iconSize == SmallIcon ) isz = IconSize( KIcon::Small );
+ else if ( d->iconSize == Small ) isz = 16;
+ else if ( d->iconSize == Medium ) isz = 22;
+ else if ( d->iconSize == Large ) isz = 32;
+ else if ( d->iconSize == XLarge ) isz = 48;
+
+ switch ( button )
+ {
+ case ButtonAdd:
+ d->addIcon = icon;
+ d->btnAdd->setIconSet( SmallIconSet( icon, isz ) );
+ break;
+ case ButtonRemove:
+ d->removeIcon = icon;
+ d->btnRemove->setIconSet( SmallIconSet( icon, isz ) );
+ break;
+ case ButtonUp:
+ d->upIcon = icon;
+ d->btnUp->setIconSet( SmallIconSet( icon, isz ) );
+ break;
+ case ButtonDown:
+ d->downIcon = icon;
+ d->btnDown->setIconSet( SmallIconSet( icon, isz ) );
+ break;
+ default:
+ kdDebug(KBABEL)<<"KActionSelector::setButtonIcon: DAINBREAD!"<<endl;
+ }
+}
+
+void KActionSelector::setButtonIconSet( const QIconSet &iconset, MoveButton button )
+{
+ switch ( button )
+ {
+ case ButtonAdd:
+ d->btnAdd->setIconSet( iconset );
+ break;
+ case ButtonRemove:
+ d->btnRemove->setIconSet( iconset );
+ break;
+ case ButtonUp:
+ d->btnUp->setIconSet( iconset );
+ break;
+ case ButtonDown:
+ d->btnDown->setIconSet( iconset );
+ break;
+ default:
+ kdDebug(KBABEL)<<"KActionSelector::setButtonIconSet: DAINBREAD!"<<endl;
+ }
+}
+
+void KActionSelector::setButtonTooltip( const QString &tip, MoveButton button )
+{
+ switch ( button )
+ {
+ case ButtonAdd:
+ d->btnAdd->setTextLabel( tip );
+ break;
+ case ButtonRemove:
+ d->btnRemove->setTextLabel( tip );
+ break;
+ case ButtonUp:
+ d->btnUp->setTextLabel( tip );
+ break;
+ case ButtonDown:
+ d->btnDown->setTextLabel( tip );
+ break;
+ default:
+ kdDebug(KBABEL)<<"KActionSelector::setButtonToolTip: DAINBREAD!"<<endl;
+ }
+}
+
+void KActionSelector::setButtonWhatsThis( const QString &text, MoveButton button )
+{
+ switch ( button )
+ {
+ case ButtonAdd:
+ QWhatsThis::add( d->btnAdd, text );
+ break;
+ case ButtonRemove:
+ QWhatsThis::add( d->btnRemove, text );
+ break;
+ case ButtonUp:
+ QWhatsThis::add( d->btnUp, text );
+ break;
+ case ButtonDown:
+ QWhatsThis::add( d->btnDown, text );
+ break;
+ default:
+ kdDebug(KBABEL)<<"KActionSelector::setButtonWhatsThis: DAINBREAD!"<<endl;
+ }
+}
+
+void KActionSelector::setButtonsEnabled()
+{
+ d->btnAdd->setEnabled( d->availableListBox->currentItem() > -1 );
+ d->btnRemove->setEnabled( d->selectedListBox->currentItem() > -1 );
+ d->btnUp->setEnabled( d->selectedListBox->currentItem() > 0 );
+ d->btnDown->setEnabled( d->selectedListBox->currentItem() > -1 &&
+ d->selectedListBox->currentItem() < (int)d->selectedListBox->count() - 1 );
+}
+
+//END Public Methods
+
+//BEGIN Properties
+
+bool KActionSelector::moveOnDoubleClick() const
+{
+ return d->moveOnDoubleClick;
+}
+
+void KActionSelector::setMoveOnDoubleClick( bool b )
+{
+ d->moveOnDoubleClick = b;
+}
+
+bool KActionSelector::keyboardEnabled() const
+{
+ return d->keyboardEnabled;
+}
+
+void KActionSelector::setKeyboardEnabled( bool b )
+{
+ d->keyboardEnabled = b;
+}
+
+QString KActionSelector::availableLabel() const
+{
+ return d->lAvailable->text();
+}
+
+void KActionSelector::setAvailableLabel( const QString &text )
+{
+ d->lAvailable->setText( text );
+}
+
+QString KActionSelector::selectedLabel() const
+{
+ return d->lSelected->text();
+}
+
+void KActionSelector::setSelectedLabel( const QString &text )
+{
+ d->lSelected->setText( text );
+}
+
+KActionSelector::ButtonIconSize KActionSelector::buttonIconSize() const
+{
+ return d->iconSize;
+}
+
+void KActionSelector::setButtonIconSize( ButtonIconSize size )
+{
+ d->iconSize = size;
+ // reload icons
+ loadIcons();
+}
+
+KActionSelector::InsertionPolicy KActionSelector::availableInsertionPolicy()
+{
+ return d->availableInsertionPolicy;
+}
+
+void KActionSelector::setAvailableInsertionPolicy( InsertionPolicy p )
+{
+ d->availableInsertionPolicy = p;
+}
+
+KActionSelector::InsertionPolicy KActionSelector::selectedInsertionPolicy()
+{
+ return d->selectedInsertionPolicy;
+}
+
+void KActionSelector::setSelectedInsertionPolicy( InsertionPolicy p )
+{
+ d->selectedInsertionPolicy = p;
+}
+
+bool KActionSelector::showUpDownButtons()
+{
+ return d->showUpDownButtons;
+}
+
+void KActionSelector::setShowUpDownButtons( bool show )
+{
+ d->showUpDownButtons = show;
+ if ( show )
+ {
+ d->btnUp->show();
+ d->btnDown->show();
+ }
+ else
+ {
+ d->btnUp->hide();
+ d->btnDown->hide();
+ }
+}
+
+//END Properties
+
+//BEGIN Public Slots
+
+void KActionSelector::polish()
+{
+ setButtonsEnabled();
+}
+
+//END Public Slots
+
+//BEGIN Protected
+void KActionSelector::keyPressEvent( QKeyEvent *e )
+{
+ if ( ! d->keyboardEnabled ) return;
+ if ( (e->state() & Qt::ControlButton) )
+ {
+ switch ( e->key() )
+ {
+ case Key_Right:
+ buttonAddClicked();
+ break;
+ case Key_Left:
+ buttonRemoveClicked();
+ break;
+ case Key_Up:
+ buttonUpClicked();
+ break;
+ case Key_Down:
+ buttonDownClicked();
+ break;
+ default:
+ e->ignore();
+ return;
+ }
+ }
+}
+
+bool KActionSelector::eventFilter( QObject *o, QEvent *e )
+{
+ if ( d->keyboardEnabled && e->type() == QEvent::KeyPress )
+ {
+ if ( (((QKeyEvent*)e)->state() & Qt::ControlButton) )
+ {
+ switch ( ((QKeyEvent*)e)->key() )
+ {
+ case Key_Right:
+ buttonAddClicked();
+ break;
+ case Key_Left:
+ buttonRemoveClicked();
+ break;
+ case Key_Up:
+ buttonUpClicked();
+ break;
+ case Key_Down:
+ buttonDownClicked();
+ break;
+ default:
+ return QWidget::eventFilter( o, e );
+ break;
+ }
+ return true;
+ }
+ else if ( o->inherits( "QListBox" ) )
+ {
+ switch ( ((QKeyEvent*)e)->key() )
+ {
+ case Key_Return:
+ case Key_Enter:
+ QListBox *lb = (QListBox*)o;
+ int index = lb->currentItem();
+ if ( index < 0 ) break;
+ moveItem( lb->item( index ) );
+ return true;
+ }
+ }
+ }
+ return QWidget::eventFilter( o, e );
+}
+
+//END Protected
+
+//BEGIN Private Slots
+
+void KActionSelector::buttonAddClicked()
+{
+ // move all selected items from available to selected listbox
+ QListBoxItem *item = d->availableListBox->firstItem();
+ while ( item ) {
+ if ( item->isSelected() ) {
+ d->availableListBox->takeItem( item );
+ d->selectedListBox->insertItem( item, insertionIndex( d->selectedListBox, d->selectedInsertionPolicy ) );
+ d->selectedListBox->setCurrentItem( item );
+ emit added( item );
+ }
+ item = item->next();
+ }
+ if ( d->selectedInsertionPolicy == Sorted )
+ d->selectedListBox->sort();
+ d->selectedListBox->setFocus();
+}
+
+void KActionSelector::buttonRemoveClicked()
+{
+ // move all selected items from selected to available listbox
+ QListBoxItem *item = d->selectedListBox->firstItem();
+ while ( item ) {
+ if ( item->isSelected() ) {
+ d->selectedListBox->takeItem( item );
+ d->availableListBox->insertItem( item, insertionIndex( d->availableListBox, d->availableInsertionPolicy ) );
+ d->availableListBox->setCurrentItem( item );
+ emit removed( item );
+ }
+ item = item->next();
+ }
+ if ( d->availableInsertionPolicy == Sorted )
+ d->availableListBox->sort();
+ d->availableListBox->setFocus();
+}
+
+void KActionSelector::buttonUpClicked()
+{
+ int c = d->selectedListBox->currentItem();
+ if ( c < 0 ) return;
+ QListBoxItem *item = d->selectedListBox->item( c );
+ d->selectedListBox->takeItem( item );
+ d->selectedListBox->insertItem( item, c-1 );
+ d->selectedListBox->setCurrentItem( item );
+ emit movedUp( item );
+}
+
+void KActionSelector::buttonDownClicked()
+{
+ int c = d->selectedListBox->currentItem();
+ if ( c < 0 ) return;
+ QListBoxItem *item = d->selectedListBox->item( c );
+ d->selectedListBox->takeItem( item );
+ d->selectedListBox->insertItem( item, c+1 );
+ d->selectedListBox->setCurrentItem( item );
+ emit movedDown( item );
+}
+
+void KActionSelector::itemDoubleClicked( QListBoxItem *item )
+{
+ if ( d->moveOnDoubleClick )
+ moveItem( item );
+}
+
+//END Private Slots
+
+//BEGIN Private Methods
+
+void KActionSelector::loadIcons()
+{
+ int isz;
+ if ( d->iconSize == SmallIcon ) isz = IconSize( KIcon::Small );
+ else if ( d->iconSize == Small ) isz = 16;
+ else if ( d->iconSize == Medium ) isz = 22;
+ else if ( d->iconSize == Large ) isz = 32;
+ else if ( d->iconSize == XLarge ) isz = 48;
+
+ d->btnAdd->setIconSet( SmallIconSet( d->addIcon, isz ) );
+ d->btnRemove->setIconSet( SmallIconSet( d->removeIcon, isz ) );
+ d->btnUp->setIconSet( SmallIconSet( d->upIcon, isz ) );
+ d->btnDown->setIconSet( SmallIconSet( d->downIcon, isz ) );
+}
+
+void KActionSelector::moveItem( QListBoxItem *item )
+{
+ QListBox *lbFrom = item->listBox();
+ QListBox *lbTo;
+ if ( lbFrom == d->availableListBox )
+ lbTo = d->selectedListBox;
+ else if ( lbFrom == d->selectedListBox )
+ lbTo = d->availableListBox;
+ else //?! somewhat unlikely...
+ return;
+
+ InsertionPolicy p = ( lbTo == d->availableListBox ) ?
+ d->availableInsertionPolicy : d->selectedInsertionPolicy;
+
+ lbFrom->takeItem( item );
+ lbTo->insertItem( item, insertionIndex( lbTo, p ) );
+ lbTo->setFocus();
+ lbTo->setCurrentItem( item );
+
+ if ( p == Sorted )
+ lbTo->sort();
+ if ( lbTo == d->selectedListBox )
+ emit added( item );
+ else
+ emit removed( item );
+}
+
+int KActionSelector::insertionIndex( QListBox *lb, InsertionPolicy policy )
+{
+ int index;
+ switch ( policy )
+ {
+ case BelowCurrent:
+ index = lb->currentItem();
+ if ( index > -1 ) index += 1;
+ break;
+ case AtTop:
+ index = 0;
+ break;
+ default:
+ index = -1;
+ }
+ return index;
+}
+
+//END Private Methods
+#include "kactionselector.moc"
diff --git a/kbabel/commonui/kactionselector.h b/kbabel/commonui/kactionselector.h
new file mode 100644
index 00000000..324ed54f
--- /dev/null
+++ b/kbabel/commonui/kactionselector.h
@@ -0,0 +1,410 @@
+/***************************************************************************
+ KActionSelector.h
+ A widget for selecting and arranging actions/objects
+ -------------------
+ begin : Mon June 3 2002
+ copyright : (C) 2002 by Anders Lund
+ email : anders@alweb.dk
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ * *
+ * In addition, as a special exception, the copyright holders give *
+ * permission to link the code of this program with any edition of *
+ * the Qt library by Trolltech AS, Norway (or with modified versions *
+ * of Qt that use the same license as Qt), and distribute linked *
+ * combinations including the two. You must obey the GNU General *
+ * Public License in all respects for all of the code used other than *
+ * Qt. If you modify this file, you may extend this exception to *
+ * your version of the file, but you are not obligated to do so. If *
+ * you do not wish to do so, delete this exception statement from *
+ * your version. *
+ ***************************************************************************/
+
+#ifndef _KACTION_SELECTOR_H_
+#define _KACTION_SELECTOR_H_
+
+#include <qwidget.h>
+
+class QListBox;
+class QListBoxItem;
+class QKeyEvent;
+class QEvent;
+class QIconSet;
+
+class KActionSelectorPrivate;
+
+/**
+ @short A widget for selecting and arranging actions/objects
+ This widget allows the user to select from a set of objects and arrange
+ the order of the selected ones using two list boxes labeled "Available"
+ and "Used" with horizontal arrows in between to move selected objects between
+ the two, and vertical arrows on the right to arrange the order of the selected
+ objects.
+
+ The widget moves objects to the other listbox when doubleclicked if
+ the property moveOnDoubleClick is set to true (default). See moveOnDoubleClick()
+ and setMoveOnDoubleClick().
+
+ The user control the widget using the keyboard if enabled (default),
+ see keyboardEnabled.
+
+ Note that this may conflist with keyboard selection in the selected list box,
+ if you set that to anything else than QListBox::Single (which is the default).
+
+ To use it, simply construct an instance and then add items to the two listboxes,
+ available through lbAvailable() and lbSelected(). Whenever you want, you can retrieve
+ the selected options using QListBox methods on lbSelected().
+
+ This way, you can use your own QListBoxItem class, allowing you to easily
+ store object data in those.
+
+ When an item is moved to a listbox, it is placed below the current item
+ of that listbox.
+
+ Standard arrow icons are used, but you can use icons of your own choice if desired,
+ see setButtonIcon(). It is also possible to set tooltips and whatsthis help
+ for the buttons. See setButtonTooltip() and setButtonWhatsThis().
+
+ To set whatsthis or tooltips for the listboxes, access them through
+ availableListbox() and selectedListBox().
+
+ All the moving buttons are automatically set enabled as expected.
+
+ Signals are sent each time an item is moved, allowing you to follow the
+ users actions if you need to. See addedToSelection(), removedFromSelection(),
+ movedUp() and movedDown()
+
+ @author Anders Lund <anders@alweb.dk>
+*/
+
+class KActionSelector : public QWidget {
+ Q_OBJECT
+ Q_ENUMS( ButtonIconSize InsertionPolicy )
+ Q_PROPERTY( bool moveOnDoubleClick READ moveOnDoubleClick WRITE setMoveOnDoubleClick )
+ Q_PROPERTY( bool keyboardEnabled READ keyboardEnabled WRITE setKeyboardEnabled )
+ Q_PROPERTY( QString availableLabel READ availableLabel WRITE setAvailableLabel )
+ Q_PROPERTY( QString selectedLabel READ selectedLabel WRITE setSelectedLabel )
+ Q_PROPERTY( ButtonIconSize buttonIconSize READ buttonIconSize WRITE setButtonIconSize )
+ Q_PROPERTY( InsertionPolicy availableInsertionPolicy READ availableInsertionPolicy WRITE setAvailableInsertionPolicy )
+ Q_PROPERTY( InsertionPolicy selectedInsertionPolicy READ selectedInsertionPolicy WRITE setSelectedInsertionPolicy )
+ Q_PROPERTY( bool showUpDownButtons READ showUpDownButtons WRITE setShowUpDownButtons )
+
+public:
+ KActionSelector( QWidget *parent=0, const char *name=0 );
+ ~KActionSelector();
+
+ /**
+ @return The QListBox holding the available actions
+ */
+ QListBox *availableListBox();
+
+ /**
+ @return The QListBox holding the selected actions
+ */
+ QListBox *selectedListBox();
+
+ /**
+ This enum indentifies the moving buttons
+ */
+ enum MoveButton {
+ ButtonAdd,
+ ButtonRemove,
+ ButtonUp,
+ ButtonDown
+ };
+
+ /**
+ This enum identifies the icon sizes, used for the move buttons.
+ The values correspond to the following pixel sizes:
+ @li SmallIcon - the return value of IconSize( KIcon::Small ), the user defined size
+ of a small icon in KDE. This is the default setting.
+ @li Small - 16px
+ @li Medium - 22px
+ @li Large - 32px
+ @li XLarge - 48px
+ */
+ enum ButtonIconSize {
+ SmallIcon,
+ Small,
+ Medium,
+ Large,
+ XLarge
+ };
+
+ /**
+ This enum defines policies for where to insert moved items in a listbox.
+ The following policies are currently defined:
+ @li BelowCurrent - The item is inserted below the listbox'
+ currentItem() or at the end if there is no curent item.
+ @li Sorted - The listbox is sort()ed after one or more items are inserted.
+ @li AtTop - The item is inserted at index 0 in the listbox.
+ @li AtBottom - The item is inserted at the end of the listbox.
+
+ @sa availableInsertionPolicy(), setAvailableInsertionPolicy(),
+ selectedInsertionPolicy(), setSelectedInsertionPolicy().
+ */
+ enum InsertionPolicy {
+ BelowCurrent,
+ Sorted,
+ AtTop,
+ AtBottom
+ };
+
+ /**
+ @return Wheather moveOnDoubleClcik is enabled.
+
+ If enabled, an item in any listbox will be moved to the other one whenever
+ doubleclicked.
+ @sa setMoveOnDoubleClick()
+ */
+ bool moveOnDoubleClick() const;
+
+ /**
+ Sets moveOnDoubleClick to @p enable
+ @sa moveOnDoubleClick()
+ */
+ void setMoveOnDoubleClick( bool enable );
+
+ /**
+ @return Weather keyboard control is enabled.
+
+ When Keyboard control is enabled, the widget will react to
+ the following keyboard actions:
+ @li CTRL + Right - simulate clicking the add button
+ @li CTRL + Left - simulate clicking the remove button
+ @li CTRL + Up - simulate clicking the up button
+ @li CTRL + Down - simulate clicking the down button
+
+ Additionally, pressing RETURN or ENTER on one of the list boxes
+ will cause the current item of that listbox to be moved to the other
+ listbox.
+
+ The keyboard actions are enabled by default.
+
+ @sa setKeyboardEnabled()
+ */
+ bool keyboardEnabled() const;
+
+ /**
+ Sets the keyboard enabled depending on @p enable.
+ @sa keyboardEnabled()
+ */
+ void setKeyboardEnabled( bool enable );
+
+ /**
+ @return The text of the label for the available items listbox.
+ */
+ QString availableLabel() const;
+
+ /**
+ Sets the label for the available items listbox to @p text.
+ Note that this label has the listbox as its @e buddy, so that
+ if you have a single ampersand in the text, the following character
+ will become the accellerator to focus te listbox.
+ */
+ void setAvailableLabel( const QString & text );
+
+ /**
+ @return the label of the selected items listbox.
+ */
+ QString selectedLabel() const;
+
+ /**
+ Sets the label for the selected items listbox to @p text.
+ Note that this label has the listbox as its @e buddy, so that
+ if you have a single ampersand in the text, the following character
+ will become the accellerator to focus te listbox.
+ */
+ void setSelectedLabel( const QString & text );
+
+ /**
+ @return the current ButtonIconSize.
+ */
+ ButtonIconSize buttonIconSize() const;
+
+ /**
+ Sets the button icon size.
+ See ButtonIconSize for the possible values and their pixel meaning.
+ */
+ void setButtonIconSize( ButtonIconSize size );
+
+ /**
+ @return The current insertion policy for the available listbox.
+ The default policy for the available listbox is Sorted.
+ See also InsertionPolicy, setAvailableInsertionPolicy().
+ */
+ InsertionPolicy availableInsertionPolicy();
+
+ /**
+ Sets the insertion policy for the available listbox.
+ See also InsertionPolicy, availableInsertionPolicy().
+ */
+ void setAvailableInsertionPolicy( InsertionPolicy policy );
+
+ /**
+ @return The current insertion policy for the selected listbox.
+ The default policy for the selected listbox is BelowCurrent.
+ See also InsertionPolicy, setSelectedInsertionPolicy().
+ */
+ InsertionPolicy selectedInsertionPolicy();
+
+ /**
+ Sets the insertion policy for the selected listbox.
+ See also InsertionPolicy, selectedInsertionPolicy().
+ */
+ void setSelectedInsertionPolicy( InsertionPolicy policy );
+
+ /**
+ @return wheather the Up and Down buttons should be displayed.
+ */
+ bool showUpDownButtons();
+
+ /**
+ Sets wheather the Up and Down buttons should be displayed
+ according to @p show
+ */
+ void setShowUpDownButtons( bool show );
+
+ /**
+ Sets the pixmap of the button @p button to @p icon.
+ It calls @ref SmallIconSet(pm) to generate the icon set.
+ */
+ void setButtonIcon( const QString &icon, MoveButton button );
+
+ /**
+ Sets the iconset for button @p button to @p iconset.
+ You can use this method to et a costum icon set. Either
+ created by @ref QIconSet, or use the application instance of
+ @ref KIconLoader (recommended).
+ */
+ void setButtonIconSet( const QIconSet &iconset, MoveButton button );
+
+ /**
+ Sets the tooltip for the button @p button to @p tip.
+ */
+ void setButtonTooltip( const QString &tip, MoveButton button );
+
+ /**
+ Sets the whatsthis help for button @p button to @p text.
+ */
+ void setButtonWhatsThis( const QString &text, MoveButton button );
+
+ /**
+ Sets the enabled state of all moving buttons to reflect the current
+ options.
+
+ Be sure to call this if you add or removes items to either listbox after the
+ widget is show()n
+ */
+ void setButtonsEnabled();
+
+signals:
+ /**
+ Emitted when an item is moved to the "selected" listbox.
+ */
+ void added( QListBoxItem *item );
+
+ /**
+ Emitted when an item is moved out of the "selected" listbox.
+ */
+ void removed( QListBoxItem *item );
+
+ /**
+ Emitted when an item is moved upwards in the "selected" listbox.
+ */
+ void movedUp( QListBoxItem *item );
+
+ /**
+ Emitted when an item is moved downwards in the "selected" listbox.
+ */
+ void movedDown( QListBoxItem *item );
+
+ /**
+ Emitted when an item is moved to the "selected" listbox.
+ */
+// void addedToSelection( QListBoxItem *item );
+
+public slots:
+ /**
+ Reimplemented for internal reasons.
+ (calls setButtonsEnabled())
+ */
+ void polish();
+
+protected:
+ /**
+ Reimplamented for internal reasons.
+ */
+ void keyPressEvent( QKeyEvent * );
+
+ /**
+ Reimplemented for internal reasons.
+ */
+ bool eventFilter( QObject *, QEvent * );
+
+private slots:
+ /**
+ Move selected item from available box to the selected box
+ */
+ void buttonAddClicked();
+
+ /**
+ Move selected item from selected box to available box
+ */
+ void buttonRemoveClicked();
+
+ /**
+ Move selected item in selected box upwards
+ */
+ void buttonUpClicked();
+
+ /**
+ Move seleted item in selected box downwards
+ */
+ void buttonDownClicked();
+
+ /**
+ Moves the item @p item to the other listbox if moveOnDoubleClick is enabled.
+ */
+ void itemDoubleClicked( QListBoxItem *item );
+
+ /**
+ connected to both list boxes to set the buttons enabled
+ */
+ void slotCurrentChanged( QListBoxItem * ) { setButtonsEnabled(); };
+
+private:
+
+ /**
+ Move item @p item to the other listbox
+ */
+ void moveItem( QListBoxItem *item );
+
+ /**
+ loads the icons for the move buttons.
+ */
+ void loadIcons();
+
+ /**
+ @return the index to insert an item into listbox @p lb,
+ given InsertionPolicy @p policy.
+
+ Note that if policy is Sorted, this will return -1.
+ Sort the listbox after inserting the item in that case.
+ */
+ int insertionIndex( QListBox *lb, InsertionPolicy policy );
+
+ /** @private
+ Private data storage
+ */
+ KActionSelectorPrivate *d;
+};
+
+#endif // _KACTION_SELECTOR_H_
diff --git a/kbabel/commonui/kbabel_tool.desktop b/kbabel/commonui/kbabel_tool.desktop
new file mode 100644
index 00000000..3ae5922d
--- /dev/null
+++ b/kbabel/commonui/kbabel_tool.desktop
@@ -0,0 +1,9 @@
+[Desktop Entry]
+Type=ServiceType
+X-KDE-ServiceType=KBabelTool
+
+[PropertyDef::Shortcuts]
+Type=QStringList
+
+[PropertyDef::ValidationString]
+Type=QString
diff --git a/kbabel/commonui/kbabel_validator.desktop b/kbabel/commonui/kbabel_validator.desktop
new file mode 100644
index 00000000..fd8ad4ac
--- /dev/null
+++ b/kbabel/commonui/kbabel_validator.desktop
@@ -0,0 +1,56 @@
+[Desktop Entry]
+Type=ServiceType
+X-KDE-ServiceType=KBabelValidator
+Comment=KDE Data Tool for KBabel
+Comment[bg]=ИнÑтрумент за данни на KDE - KBabel
+Comment[br]=Ostilh roadoù KDE evit KBabel
+Comment[bs]=KDE podatkovni alat za KBabel
+Comment[ca]=Eina de dades KDE per a KBabel
+Comment[cs]=Datový nástroj pro KBabel
+Comment[cy]=Erfyn Data KDE i KBabel
+Comment[da]=KDE Data-værktøj for KBabel
+Comment[de]=KDE Datenbearbeitungswerkzeug für KBabel
+Comment[el]=ΕÏγαλείο δεδομένων για το KBabel του KDE
+Comment[es]=Herramienta de datos KDE para KBabel
+Comment[et]=KBabeli KDE andmete tööriist
+Comment[eu]=KBabel-erako KDE aatu tresna
+Comment[fa]=ابزار دادۀ KDE برای KBabel
+Comment[fi]=KBabelin KDE Data Tool
+Comment[fr]=Outil de données KDE pour KBabel
+Comment[gl]=Ferramenta de Datos de KDE para KBabel
+Comment[hi]=के-बेबल के लिठकेडीई डाटा औज़ार
+Comment[hu]=Adatkezelő a KBabelhez
+Comment[is]=KDE gagnatól fyrir KBabel
+Comment[it]=Strumento KDE per la gestione dati con KBabel
+Comment[ja]=KBabel ã®ãŸã‚ã® KDE データツール
+Comment[ka]=KBabel-ის KDE მáƒáƒœáƒáƒªáƒ”მთრხელსáƒáƒ¬áƒ§áƒ
+Comment[kk]=KDE-нің KBabel-дің деректер құралы
+Comment[lt]=KDE duomenų įrankis, skirtas KBabel
+Comment[ms]=Alatan Data KDE untuk KBabel
+Comment[nb]=KDE dataverktøy for KBabel
+Comment[nds]=KDE-Datenwarktüüch för KBabel
+Comment[ne]=केबà¥à¤¯à¤¾à¤¬à¤²à¤•à¤¾ लागि केडीई डाटा उपकरण
+Comment[nl]=KDE Dataprogramma voor KBabel
+Comment[nn]=KDE-dataverktøy for KBabel
+Comment[pa]=KBabel ਲਈ ਕੇਡੀਈ ਡਾਟਾ ਸੰਦ
+Comment[pl]=Narzędzie danych KDE dla KBabel
+Comment[pt]=Ferramenta de Dados do KDE para o KBabel
+Comment[pt_BR]=Ferramenta de Dados KDE para o KBabel
+Comment[ru]=Данные Ð´Ð»Ñ KBabel
+Comment[sk]=Dátový nástroj pre KBabel
+Comment[sl]=Podatkovno orodje KDE za KBabel
+Comment[sr]=KDE-ов алат за податке за KBabel
+Comment[sr@Latn]=KDE-ov alat za podatke za KBabel
+Comment[sv]=KDE dataverktyg för Kbabel
+Comment[ta]=KDE Kபாபேலின௠தரவà¯à®•à¯ கரà¯à®µà®¿
+Comment[tg]=Маълумоти аÑбоби KDE барои KBabel
+Comment[tr]=KBabel için KDE Veri Aracı
+Comment[uk]=ЗаÑіб роботи з даними KDE Ð´Ð»Ñ KBabel
+Comment[zh_CN]=KBabel çš„ KDE æ•°æ®å·¥å…·
+Comment[zh_TW]=KBabel 資料工具
+
+[PropertyDef::Shortcuts]
+Type=QStringList
+
+[PropertyDef::ValidationString]
+Type=QString
diff --git a/kbabel/commonui/klisteditor.ui b/kbabel/commonui/klisteditor.ui
new file mode 100644
index 00000000..63fbfceb
--- /dev/null
+++ b/kbabel/commonui/klisteditor.ui
@@ -0,0 +1,261 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>KListEditor</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>KListEditor</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>334</width>
+ <height>274</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>_frame</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string></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="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout3</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="QLineEdit">
+ <property name="name">
+ <cstring>_edit</cstring>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout2</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="QListBox">
+ <item>
+ <property name="text">
+ <string>New Item</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>_list</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>200</width>
+ <height>200</height>
+ </size>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout5_2</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="QPushButton">
+ <property name="name">
+ <cstring>_addButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Add</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>_removeButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Remove</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>_upButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Up</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>_downButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Down</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>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ </hbox>
+</widget>
+<connections>
+ <connection>
+ <sender>_addButton</sender>
+ <signal>pressed()</signal>
+ <receiver>KListEditor</receiver>
+ <slot>addToList()</slot>
+ </connection>
+ <connection>
+ <sender>_removeButton</sender>
+ <signal>pressed()</signal>
+ <receiver>KListEditor</receiver>
+ <slot>removeFromList()</slot>
+ </connection>
+ <connection>
+ <sender>_upButton</sender>
+ <signal>pressed()</signal>
+ <receiver>KListEditor</receiver>
+ <slot>upInList()</slot>
+ </connection>
+ <connection>
+ <sender>_downButton</sender>
+ <signal>pressed()</signal>
+ <receiver>KListEditor</receiver>
+ <slot>downInList()</slot>
+ </connection>
+ <connection>
+ <sender>_edit</sender>
+ <signal>returnPressed()</signal>
+ <receiver>KListEditor</receiver>
+ <slot>updateList()</slot>
+ </connection>
+ <connection>
+ <sender>_edit</sender>
+ <signal>textChanged(const QString&amp;)</signal>
+ <receiver>KListEditor</receiver>
+ <slot>editChanged(const QString&amp;)</slot>
+ </connection>
+ <connection>
+ <sender>_list</sender>
+ <signal>highlighted(int)</signal>
+ <receiver>KListEditor</receiver>
+ <slot>updateButtons(int)</slot>
+ </connection>
+ <connection>
+ <sender>_list</sender>
+ <signal>highlighted(const QString&amp;)</signal>
+ <receiver>_edit</receiver>
+ <slot>setText(const QString&amp;)</slot>
+ </connection>
+</connections>
+<includes>
+ <include location="local" impldecl="in implementation">klisteditor.ui.h</include>
+</includes>
+<signals>
+ <signal>itemsChanged()</signal>
+</signals>
+<slots>
+ <slot>addToList()</slot>
+ <slot>downInList()</slot>
+ <slot>removeFromList()</slot>
+ <slot>upInList()</slot>
+ <slot>updateButtons( int newIndex )</slot>
+ <slot>updateList()</slot>
+ <slot>setList( QStringList contents )</slot>
+ <slot access="protected">editChanged( const QString &amp; s )</slot>
+ <slot>setTitle( const QString &amp; s )</slot>
+ <slot returnType="QStringList">list()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kbabel/commonui/klisteditor.ui.h b/kbabel/commonui/klisteditor.ui.h
new file mode 100644
index 00000000..bc916e56
--- /dev/null
+++ b/kbabel/commonui/klisteditor.ui.h
@@ -0,0 +1,122 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002-2005 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+
+** 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 KListEditor::addToList()
+{
+ _list->insertItem(_edit->text());
+ _edit->clear();
+ _removeButton->setEnabled(true);
+ emit itemsChanged();
+}
+
+void KListEditor::downInList()
+{
+ int i=_list->currentItem();
+ if( i< (int)_list->count()-1 ) {
+ QString ci = _list->currentText();
+ _list->removeItem(i);
+ _list->insertItem(ci,i+1);
+ _list->setCurrentItem(i+1);
+ }
+ emit itemsChanged();
+}
+
+void KListEditor::removeFromList()
+{
+ _list->removeItem(_list->currentItem());
+ if( _list->count()==0 ) _edit->clear();
+ _removeButton->setEnabled(_list->count()>0);
+ emit itemsChanged();
+}
+
+void KListEditor::upInList()
+{
+ int i=_list->currentItem();
+ if( i>0 ) {
+ QString ci = _list->currentText();
+ _list->removeItem(i);
+ _list->insertItem(ci,i-1);
+ _list->setCurrentItem(i-1);
+ }
+ emit itemsChanged();
+}
+
+void KListEditor::updateButtons( int newIndex )
+{
+ _upButton->setEnabled(newIndex>0);
+ _downButton->setEnabled(newIndex+1 != (int)_list->count());
+ _removeButton->setEnabled(true);
+}
+
+void KListEditor::updateList()
+{
+ int i=_list->currentItem();
+ if( i==-1 ) addToList();
+ else _list->changeItem(_edit->text(), i );
+}
+
+void KListEditor::setList( QStringList contents )
+{
+ _list->clear();
+ _list->insertStringList(contents);
+ _list->setCurrentItem(0);
+ _removeButton->setEnabled(!contents.isEmpty());
+}
+
+
+void KListEditor::editChanged( const QString &s )
+{
+ _addButton->setEnabled(!s.isEmpty());
+}
+
+
+void KListEditor::setTitle( const QString &s )
+{
+ _frame->setTitle(s);
+}
+
+
+QStringList KListEditor::list()
+{
+ QStringList result;
+ for( uint i=0; i<_list->count() ; i++ )
+ result.append(_list->text(i));
+ return result;
+}
diff --git a/kbabel/commonui/projectpref.cpp b/kbabel/commonui/projectpref.cpp
new file mode 100644
index 00000000..1bffa2e6
--- /dev/null
+++ b/kbabel/commonui/projectpref.cpp
@@ -0,0 +1,278 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2004-2005 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include "projectpref.h"
+#include "projectprefwidgets.h"
+#include "diffpreferences.h"
+#include "kbprojectsettings.h"
+
+#include <qlayout.h>
+#include <qwhatsthis.h>
+#include <qvbox.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kapplication.h>
+
+
+#define PAGE_IDENTITY 0
+#define PAGE_SAVE 1
+#define PAGE_SPELL 2
+#define PAGE_SOURCE 3
+#define PAGE_MISC 4
+#define PAGE_CATMAN 5
+#define PAGE_DIRCOMMANDS 6
+#define PAGE_FILECOMMANDS 7
+#define PAGE_VIEW 8
+#define PAGE_DIFF 9
+
+using namespace KBabel;
+
+ProjectDialog::ProjectDialog(Project::Ptr project)
+ : KConfigDialog(0, "project dialog", project->settings(),
+ IconList, Help|Default|Ok|Apply|Cancel)
+ , _project( project )
+{
+
+ _identityPage = new IdentityPreferences(0, project->name());
+ addPage(_identityPage, i18n("title of page in preferences dialog","Identity")
+ , "pref_identity"
+ , i18n("Information About You and Translation Team")
+ );
+
+ _savePage = new SavePreferences(0);
+ addPage(_savePage, i18n("title of page in preferences dialog","Save")
+ , "filesave"
+ , i18n("Options for File Saving"));
+
+
+ _spellPage = new SpellPreferences(0);
+ addPage(_spellPage, i18n("title of page in preferences dialog","Spelling")
+ , "spellcheck"
+ , i18n("Options for Spell Checking"));
+ connect( _spellPage, SIGNAL( settingsChanged() )
+ , this, SLOT(updateButtons()) );
+
+ _sourcePage = new SourceContextPreferences(0);
+ addPage(_sourcePage, i18n("title of page in preferences dialog","Source")
+ , "source"
+ ,i18n("Options for Showing Source Context"));
+ connect(_sourcePage, SIGNAL (itemsChanged())
+ , this, SLOT (updateButtons()) );
+
+ _miscPage = new MiscPreferences(0);
+ addPage(_miscPage, i18n("title of page in preferences dialog","Miscellaneous")
+ , "misc"
+ ,i18n("Miscellaneous Settings"));
+
+ _catmanPage = new CatmanPreferences(0);
+ addPage(_catmanPage, i18n("title of page in preferences dialog","Folders")
+ , "catalogmanager"
+ , i18n("Paths to Message Catalogs & Catalog Templates"));
+
+ _dirCommandsPage = new DirCommandsPreferences(0);
+ addPage(_dirCommandsPage, i18n("title of page in preferences dialog","Folder Commands")
+ , "folder"
+ , i18n("User-Defined Commands for Folder Items"));
+ connect( _dirCommandsPage, SIGNAL( settingsChanged() ),
+ this, SLOT(updateButtons()) );
+
+ _fileCommandsPage = new FileCommandsPreferences(0);
+ addPage(_fileCommandsPage, i18n("title of page in preferences dialog","File Commands")
+ , "files"
+ , i18n("User-Defined Commands for File Items"));
+ connect( _fileCommandsPage, SIGNAL( settingsChanged() ),
+ this, SLOT(updateButtons()) );
+
+ _viewPage = new ViewPreferences(0);
+ addPage(_viewPage, i18n("title of page in preferences dialog","Catalog Manager")
+ , "view_tree"
+ , i18n("Catalog Manager View Settings"));
+
+ _diffPage = new DiffPreferences(0);
+ addPage(_diffPage, i18n("title of page in preferences dialog","Diff")
+ , "diff"
+ , i18n("Searching for Differences"));
+
+ setHelp( "preferences-project-settings", "kbabel" );
+
+ adjustSize();
+}
+
+void ProjectDialog::slotDefault()
+{
+ // redefine the KConfigDialog behavior to push default on the
+ // current page only
+
+ _project->settings()->useDefaults(true);
+
+ switch(activePageIndex())
+ {
+ case PAGE_IDENTITY:
+ _identityPage->defaults(_project->identitySettings());
+ break;
+ case PAGE_SAVE:
+ _savePage->defaults(_project->saveSettings());
+ break;
+ case PAGE_MISC:
+ _miscPage->defaults(_project->miscSettings());
+ break;
+ case PAGE_SPELL:
+ _spellPage->defaults(_project->spellcheckSettings());
+ break;
+ case PAGE_SOURCE:
+ _sourcePage->defaults(_project->sourceContextSettings());
+ break;
+ case PAGE_CATMAN:
+ _catmanPage->defaults(_project->catManSettings());
+ break;
+ case PAGE_DIRCOMMANDS:
+ _dirCommandsPage->defaults(_project->catManSettings());
+ break;
+ case PAGE_FILECOMMANDS:
+ _fileCommandsPage->defaults(_project->catManSettings());
+ break;
+ case PAGE_VIEW:
+ _viewPage->defaults(_project->catManSettings());
+ break;
+ }
+
+ _project->settings()->useDefaults(false);
+}
+
+void ProjectDialog::updateSettings()
+{
+ KBabel::CatManSettings _CatManSettings;
+ SourceContextSettings contextSettings;
+
+ _spellPage->mergeSettings(_spellcheckSettings);
+ _dirCommandsPage->mergeSettings(_CatManSettings);
+ _fileCommandsPage->mergeSettings(_CatManSettings);
+ _sourcePage->mergeSettings(contextSettings);
+
+ _project->settings()->setDirCommands( _CatManSettings.dirCommands );
+ _project->settings()->setDirCommandNames( _CatManSettings.dirCommandNames );
+ _project->settings()->setFileCommands( _CatManSettings.fileCommands );
+ _project->settings()->setFileCommandNames( _CatManSettings.fileCommandNames );
+
+ _project->setSettings(_spellcheckSettings);
+
+ _project->settings()->setPaths( contextSettings.sourcePaths );
+}
+
+void ProjectDialog::updateWidgets()
+{
+ _spellPage->updateWidgets(_project->spellcheckSettings());
+ _dirCommandsPage->updateWidgets(_project->catManSettings());
+ _fileCommandsPage->updateWidgets(_project->catManSettings());
+ _sourcePage->updateWidgets(_project->sourceContextSettings());
+}
+
+void ProjectDialog::updateWidgetsDefault()
+{
+ _project->settings()->useDefaults( true );
+ updateWidgets();
+ _project->settings()->useDefaults( false );
+}
+
+bool ProjectDialog::isDefault()
+{
+ SourceContextSettings contextSettings, defaultContextSettings;
+
+ // get the current values
+ _spellPage->mergeSettings(_spellcheckSettings);
+ _dirCommandsPage->mergeSettings(_CatManSettings);
+ _fileCommandsPage->mergeSettings(_CatManSettings);
+ _sourcePage->mergeSettings(defaultContextSettings);
+
+ // get default values
+ _project->settings()->useDefaults(true);
+ SpellcheckSettings defaultSpell = _project->spellcheckSettings();
+ CatManSettings defaultCatMan = _project->catManSettings();
+ defaultContextSettings = _project->sourceContextSettings();
+ _project->settings()->useDefaults(false);
+
+ bool result = true;
+
+ result &= _spellcheckSettings.noRootAffix == defaultSpell.noRootAffix;
+ result &= _spellcheckSettings.runTogether == defaultSpell.runTogether;
+ result &= _spellcheckSettings.spellClient == defaultSpell.spellClient;
+ result &= _spellcheckSettings.spellDict == defaultSpell.spellDict;
+ result &= _spellcheckSettings.spellEncoding == defaultSpell.spellEncoding;
+
+ result &= _CatManSettings.dirCommandNames == defaultCatMan.dirCommandNames;
+ result &= _CatManSettings.dirCommands == defaultCatMan.dirCommands;
+ result &= _CatManSettings.fileCommandNames == defaultCatMan.fileCommandNames;
+ result &= _CatManSettings.fileCommands == defaultCatMan.fileCommands;
+
+ result &= contextSettings.sourcePaths != defaultContextSettings.sourcePaths;
+
+ return result;
+}
+
+bool ProjectDialog::hasChanged()
+{
+ SourceContextSettings contextSettings, defaultContextSettings;
+
+ // get the current values
+ _spellPage->mergeSettings(_spellcheckSettings);
+ _dirCommandsPage->mergeSettings(_CatManSettings);
+ _fileCommandsPage->mergeSettings(_CatManSettings);
+ _sourcePage->mergeSettings(contextSettings);
+
+ // get project values
+ SpellcheckSettings defaultSpell = _project->spellcheckSettings();
+ CatManSettings defaultCatMan = _project->catManSettings();
+ defaultContextSettings = _project->sourceContextSettings();
+
+ bool result = false;
+
+ result |= _spellcheckSettings.noRootAffix != defaultSpell.noRootAffix;
+ result |= _spellcheckSettings.runTogether != defaultSpell.runTogether;
+ result |= _spellcheckSettings.spellClient != defaultSpell.spellClient;
+ result |= _spellcheckSettings.spellDict != defaultSpell.spellDict;
+ result |= _spellcheckSettings.spellEncoding != defaultSpell.spellEncoding;
+
+ result |= _CatManSettings.dirCommandNames != defaultCatMan.dirCommandNames;
+ result |= _CatManSettings.dirCommands != defaultCatMan.dirCommands;
+ result |= _CatManSettings.fileCommandNames != defaultCatMan.fileCommandNames;
+ result |= _CatManSettings.fileCommands != defaultCatMan.fileCommands;
+
+ result |= contextSettings.sourcePaths != defaultContextSettings.sourcePaths;
+
+ return result;
+}
+
+#include "projectpref.moc"
diff --git a/kbabel/commonui/projectpref.h b/kbabel/commonui/projectpref.h
new file mode 100644
index 00000000..90561c5b
--- /dev/null
+++ b/kbabel/commonui/projectpref.h
@@ -0,0 +1,93 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2004-2005 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef PROJECTPREF_H
+#define PROJECTPREF_H
+
+#include <kconfigdialog.h>
+#include <qptrlist.h>
+
+class SavePreferences;
+class IdentityPreferences;
+class MiscPreferences;
+class SpellPreferences;
+class CatmanPreferences;
+class DirCommandsPreferences;
+class FileCommandsPreferences;
+class ViewPreferences;
+class SourceContextPreferences;
+class DiffPreferences;
+
+#include "kbproject.h"
+#include "projectsettings.h"
+#include "context.h"
+
+namespace KBabel {
+
+class KDE_EXPORT ProjectDialog : public KConfigDialog
+{
+ Q_OBJECT
+public:
+ ProjectDialog(Project::Ptr project);
+
+protected slots:
+ virtual void slotDefault();
+ virtual void updateSettings();
+ virtual void updateWidgets();
+ virtual void updateWidgetsDefault();
+
+private:
+ virtual bool hasChanged();
+ virtual bool isDefault();
+
+ SavePreferences *_savePage;
+ IdentityPreferences* _identityPage;
+ MiscPreferences* _miscPage;
+ SpellPreferences* _spellPage;
+ SourceContextPreferences* _sourcePage;
+ CatmanPreferences *_catmanPage;
+ DirCommandsPreferences *_dirCommandsPage;
+ FileCommandsPreferences *_fileCommandsPage;
+ ViewPreferences *_viewPage;
+ DiffPreferences *_diffPage;
+
+ KBabel::SpellcheckSettings _spellcheckSettings;
+ KBabel::CatManSettings _CatManSettings;
+
+ Project::Ptr _project;
+};
+
+}
+
+#endif // PROJECTPREF_H
diff --git a/kbabel/commonui/projectprefwidgets.cpp b/kbabel/commonui/projectprefwidgets.cpp
new file mode 100644
index 00000000..16bc2da4
--- /dev/null
+++ b/kbabel/commonui/projectprefwidgets.cpp
@@ -0,0 +1,1209 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2001-2005 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include "klisteditor.h"
+#include "toolselectionwidget.h"
+#include "projectprefwidgets.h"
+#include "resources.h"
+#include "kbabeldictbox.h"
+#include "toolaction.h"
+#include "cmdedit.h"
+#include "kbprojectsettings.h"
+
+#include <kcombobox.h>
+#include <kdatatool.h>
+#include <klocale.h>
+#include <kdialog.h>
+#include <kfiledialog.h>
+#include <knuminput.h>
+#include <kmessagebox.h>
+#include <klineedit.h>
+#include <kurlcompletion.h>
+#include <kfontdialog.h>
+#include <kcolorbutton.h>
+#include <kparts/componentfactory.h>
+#include <kregexpeditorinterface.h>
+#include <ksconfig.h>
+#include <kurldrag.h>
+#include <kurlrequester.h>
+
+#include <qlayout.h>
+#include <qobjectlist.h>
+#include <qlabel.h>
+#include <qvbox.h>
+#include <qlineedit.h>
+#include <qcheckbox.h>
+#include <qgroupbox.h>
+#include <qhbuttongroup.h>
+#include <qvbuttongroup.h>
+#include <qpushbutton.h>
+#include <qcombobox.h>
+#include <qradiobutton.h>
+#include <qspinbox.h>
+#include <qtextcodec.h>
+#include <qwhatsthis.h>
+
+using namespace KBabel;
+
+static QSize sizeHintForWidget(const QWidget* widget)
+{
+ //
+ // The size is computed by adding the sizeHint().height() of all
+ // widget children and taking the width of the widest child and adding
+ // layout()->margin() and layout()->spacing()
+ //
+
+ QSize size;
+
+ int numChild = 0;
+ QObjectList *l = (QObjectList*)(widget->children());
+
+ for( uint i=0; i < l->count(); i++ )
+ {
+ QObject *o = l->at(i);
+ if( o->isWidgetType() )
+ {
+ numChild += 1;
+ QWidget *w=((QWidget*)o);
+
+ QSize s = w->sizeHint();
+ if( s.isEmpty() == true )
+ {
+ s = QSize( 50, 100 ); // Default size
+ }
+ size.setHeight( size.height() + s.height() );
+ if( s.width() > size.width() ) { size.setWidth( s.width() ); }
+ }
+ }
+
+ if( numChild > 0 )
+ {
+ size.setHeight( size.height() + widget->layout()->spacing()*(numChild-1) );
+ size += QSize( widget->layout()->margin()*2, widget->layout()->margin()*2 + 1 );
+ }
+ else
+ {
+ size = QSize( 1, 1 );
+ }
+
+ return( size );
+}
+
+
+
+
+SavePreferences::SavePreferences(QWidget *parent)
+ : KTabCtl(parent)
+{
+ QWidget* page = new QWidget(this);
+ QVBoxLayout* layout=new QVBoxLayout(page);
+ layout->setSpacing(KDialog::spacingHint());
+ layout->setMargin(KDialog::marginHint());
+
+ QGroupBox* box=new QGroupBox(1,Qt::Horizontal,page);
+ layout->addWidget(box);
+
+ box->setMargin(KDialog::marginHint());
+ _updateButton = new QCheckBox(i18n("&Update header when saving"),box, "kcfg_AutoUpdate");
+ _descriptionButton = new QCheckBox(i18n("Update &description comment when saving"),box, "kcfg_UpdateDescription");
+ _autoCheckButton = new QCheckBox(i18n("Chec&k syntax of file when saving"),box, "kcfg_AutoSyntaxCheck");
+ _saveObsoleteButton = new QCheckBox(i18n("Save &obsolete entries"),box, "kcfg_SaveObsolete");
+
+ QGroupBox* descBox=new QGroupBox(1,Qt::Horizontal,i18n("De&scription"),page);
+ layout->addWidget(descBox);
+
+ descBox->setMargin(KDialog::marginHint());
+ _descriptionEdit = new QLineEdit(descBox, "kcfg_DescriptionString");
+
+ QGroupBox* encodingBox = new QGroupBox(1,Qt::Horizontal,i18n("Encoding")
+ ,page);
+ encodingBox->setMargin(KDialog::marginHint());
+ layout->addWidget(encodingBox);
+ QHBox *b = new QHBox(encodingBox);
+
+ QLabel* tempLabel=new QLabel(i18n("Default:"),b);
+ _encodingBox = new QComboBox(b, "kcfg_Encoding");
+ b->setStretchFactor(_encodingBox,2);
+ b->setSpacing(KDialog::spacingHint());
+
+ QString defaultName=charsetString(ProjectSettingsBase::Locale);
+ defaultName+=" "+i18n("(default)");
+ QString utf8Name=charsetString(ProjectSettingsBase::UTF8);
+ QString utf16Name=charsetString(ProjectSettingsBase::UTF16);
+
+ _encodingBox->insertItem(defaultName,(int)ProjectSettingsBase::Locale);
+ _encodingBox->insertItem(utf8Name,(int)ProjectSettingsBase::UTF8);
+
+ // KBabel seems to crash somehow, when saving in utf16, so
+ // it's better to disable this, since it is useless anyway
+ // at the moment
+ //_encodingBox->insertItem(utf16Name,(int)UTF16);
+
+ tempLabel->setBuddy(_encodingBox);
+
+ _oldEncodingButton = new QCheckBox(i18n("Kee&p the encoding of the file")
+ ,encodingBox, "kcfg_UseOldEncoding");
+
+ _autoSaveBox = new QGroupBox( 1, Qt::Horizontal, i18n( "Automatic Saving" ), page );
+ _autoSaveBox->setMargin( KDialog::marginHint( ) );
+ layout->addWidget( _autoSaveBox );
+ _autoSaveDelay = new KIntNumInput( _autoSaveBox, "kcfg_AutoSaveDelay" );
+ _autoSaveDelay->setRange( 0, 60 );
+ _autoSaveDelay->setSuffix( i18n( "Short for minutes", " min" ) );
+ _autoSaveDelay->setSpecialValueText( i18n( "No autosave" ) );
+
+ layout->addStretch(1);
+ page->setMinimumSize(sizeHintForWidget(page));
+ addTab(page, i18n("&General"));
+
+ page = new QWidget(this);
+ layout=new QVBoxLayout(page);
+ layout->setSpacing(KDialog::spacingHint());
+ layout->setMargin(KDialog::marginHint());
+
+ QGroupBox* gridBox = new QGroupBox(2,Qt::Horizontal,i18n("Fields to Update"),page);
+ layout->addWidget(gridBox);
+ gridBox->setMargin(KDialog::marginHint());
+
+ _revisionButton = new QCheckBox(i18n("Re&vision-Date"),gridBox, "kcfg_UpdateRevisionDate");
+ _lastButton = new QCheckBox(i18n("Last-&Translator"),gridBox, "kcfg_UpdateLastTranslator");
+ _languageButton = new QCheckBox(i18n("&Language"),gridBox, "kcfg_UpdateLanguageTeam");
+ _charsetButton = new QCheckBox(i18n("Char&set"),gridBox, "kcfg_UpdateCharset");
+ _encodingButton = new QCheckBox(i18n("&Encoding"),gridBox, "kcfg_UpdateEncoding");
+ _projectButton = new QCheckBox(i18n("Pro&ject"),gridBox, "kcfg_UpdateProject");
+
+ QButtonGroup* dateBox = new QButtonGroup(2,Qt::Horizontal,i18n("Format of Revision-Date"),page, "kcfg_DateFormat");
+ layout->addWidget(dateBox);
+ box->setMargin(KDialog::marginHint());
+
+ // we remove/insert default date button to correctly map Qt::DateFormat to our Ids
+ _defaultDateButton = new QRadioButton( i18n("De&fault date format"),dateBox );
+ dateBox->remove (_defaultDateButton);
+ _localDateButton = new QRadioButton( i18n("Local date fo&rmat"),dateBox );
+ dateBox->remove (_localDateButton);
+ _customDateButton = new QRadioButton( i18n("Custo&m date format:"),dateBox );
+
+ dateBox->insert (_defaultDateButton);
+ dateBox->insert (_localDateButton);
+
+ _dateFormatEdit = new QLineEdit(dateBox, "kcfg_CustomDateFormat");
+ _dateFormatEdit->setEnabled(false);
+
+ connect( _customDateButton, SIGNAL(toggled(bool)), this, SLOT( customDateActivated(bool) ) );
+
+ QGroupBox* projectBox = new QGroupBox(1,Qt::Horizontal,i18n("Project String")
+ ,page);
+ projectBox->setMargin(KDialog::marginHint());
+ layout->addWidget(projectBox);
+ b = new QHBox(projectBox);
+
+ tempLabel=new QLabel(i18n("Project-Id:"),b);
+ _projectEdit = new QLineEdit(b, "kcfg_ProjectString");
+ b->setStretchFactor(_projectEdit,2);
+ b->setSpacing(KDialog::spacingHint());
+ tempLabel->setBuddy(_projectEdit);
+
+ layout->addStretch(1);
+ page->setMinimumSize(sizeHintForWidget(page));
+ addTab(page, i18n("&Header"));
+
+ page = new QWidget(this);
+ layout=new QVBoxLayout(page);
+ layout->setSpacing(KDialog::spacingHint());
+ layout->setMargin(KDialog::marginHint());
+
+ QGroupBox* translatorCopyrightBox = new QGroupBox(1,Qt::Horizontal, page);
+ translatorCopyrightBox->setMargin(KDialog::marginHint());
+ _translatorCopyrightButton =
+ new QCheckBox(i18n("Update &translator copyright")
+ ,translatorCopyrightBox, "kcfg_UpdateTranslatorCopyright");
+ layout->addWidget(translatorCopyrightBox);
+
+ QGroupBox* fsfBox=new QButtonGroup(1,Qt::Horizontal,i18n("Free Software Foundation Copyright"),page, "kcfg_FSFCopyright");
+ layout->addWidget(fsfBox);
+
+ fsfBox->setMargin(KDialog::marginHint());
+ _removeFSFButton = new QRadioButton(i18n("&Remove copyright if empty"),fsfBox);
+ _updateFSFButton = new QRadioButton(i18n("&Update copyright"),fsfBox);
+ _nochangeFSFButton = new QRadioButton(i18n("Do &not change"),fsfBox);
+
+ layout->addStretch(1);
+ page->setMinimumSize(sizeHintForWidget(page));
+ addTab(page, i18n("Cop&yright"));
+
+ QWhatsThis::add(_updateButton,
+ i18n("<qt><p><b>Update Header</b></p>\n"
+ "<p>Check this button to update the header "
+ "information of the file "
+ "every time it is saved.</p>\n"
+ "<p>The header normally keeps information about "
+ "the date and time the file was last\n"
+ "updated, the last translator etc.</p>\n"
+ "<p>You can choose which information you want to update from the checkboxes below.\n"
+ "Fields that do not exist are added to the header.\n"
+ "If you want to add additional fields to the header, you can edit the header manually by choosing\n"
+ "<b>Edit->Edit Header</b> in the editor window.</p></qt>"));
+
+ QWhatsThis::add(gridBox,i18n("<qt><p><b>Fields to update</b></p>\n"
+ "<p>Choose which fields in the header you want to have updated when saving.\n"
+ "If a field does not exist, it is appended to the header.</p>\n"
+ "<p>If you want to add other information to the header, you have to edit the header manually\n"
+ "by choosing <b>Edit->Edit Header</b> in the editor window.</p>\n"
+ "<p>Deactivate <b>Update Header</b> above if you do not want to have the header\n"
+ "updated when saving.</p></qt>"));
+
+ QWhatsThis::add(encodingBox,i18n("<qt><p><b>Encoding</b></p>"
+"<p>Choose how to encode characters when saving to a file. If you are unsure "
+"what encoding to use, please ask your translation coordinator.</p>"
+"<ul><li><b>%1</b>: this is the encoding that fits the character "
+"set of your system language.</li>"
+"<li><b>%2</b>: uses Unicode (UTF-8) encoding.</li>"
+"</ul></qt>").arg(defaultName).arg(utf8Name) );
+
+
+ QWhatsThis::add(_oldEncodingButton
+ ,i18n("<qt><p><b>Keep the encoding of the file</b></p>"
+ "<p>If this option is activated, files are always saved in the "
+ "same encoding as they were read in. Files without charset "
+ "information in the header (e.g. POT files) are saved in the "
+ "encoding set above.</p></qt>"));
+
+ QWhatsThis::add(_autoCheckButton,i18n("<qt><p><b>Check syntax of file when saving</b></p>\n"
+"<p>Check this to automatically check syntax of file with \"msgfmt --statistics\"\n"
+"when saving a file. You will only get a message, if an error occurred.</p></qt>"));
+
+ QWhatsThis::add(_saveObsoleteButton,i18n("<qt><p><b>Save obsolete entries</b></p>\n"
+"<p>If this option is activated, obsolete entries found when the file was open\n"
+"will be saved back to the file. Obsolete entries are marked by #~ and are\n"
+"created when the msgmerge does not need the translation anymore.\n"
+"If the text will appear again, the obsolete entries will be activated again.\n"
+"The main drawback is the size of the saved file.</p></qt>"));
+
+
+ QWhatsThis::add(dateBox, i18n("<qt><p><b>Format of Revision-Date</b></p>"
+"<p>Choose in which format the date and time of the header field\n"
+"<i>PO-Revision-Date</i> is saved: <ul>\n"
+"<li><b>Default</b> is the format normally used in PO files.</li>\n"
+"<li><b>Local</b> is the format specific to your country.\n"
+"It can be configured in KDE's Control Center.</li>\n"
+"<li><b>Custom</b> lets you define your own format.</li></ul></p> "
+"<p>It is recommended that you use the default format to avoid creating non-standard PO files.</p>"
+"<p>For more information, see section <b>The Preferences Dialog</b> "
+"in the online help.</p>"
+"</qt>") );
+
+ setMinimumSize(sizeHint());
+}
+
+
+void SavePreferences::defaults(const KBabel::SaveSettings& _settings)
+{
+ _updateButton->setChecked(_settings.autoUpdate);
+
+ _lastButton->setChecked(_settings.updateLastTranslator);
+ _revisionButton->setChecked(_settings.updateRevisionDate);
+ _languageButton->setChecked(_settings.updateLanguageTeam);
+ _charsetButton->setChecked(_settings.updateCharset);
+ _encodingButton->setChecked(_settings.updateEncoding);
+ _projectButton->setChecked(_settings.updateProject);
+
+ _encodingBox->setCurrentItem(_settings.encoding);
+ _oldEncodingButton->setChecked(_settings.useOldEncoding);
+
+ _projectEdit->setText(_settings.projectString);
+
+ _descriptionButton->setChecked(_settings.updateDescription);
+ _descriptionEdit->setText(_settings.descriptionString);
+ _translatorCopyrightButton->setChecked(_settings.updateTranslatorCopyright);
+
+ switch(_settings.FSFCopyright)
+ {
+ case ProjectSettingsBase::Update:
+ _updateFSFButton->setChecked(true);
+ break;
+ case ProjectSettingsBase::Remove:
+ _removeFSFButton->setChecked(true);
+ break;
+ case ProjectSettingsBase::NoChange:
+ _nochangeFSFButton->setChecked(true);
+ break;
+ case ProjectSettingsBase::RemoveLine:
+ break;
+ }
+
+ _autoCheckButton->setChecked(_settings.autoSyntaxCheck);
+ _saveObsoleteButton->setChecked(_settings.saveObsolete);
+
+ _dateFormatEdit->setText(_settings.customDateFormat);
+
+ switch(_settings.dateFormat)
+ {
+ case Qt::ISODate:
+ _defaultDateButton->setChecked(true);
+ break;
+ case Qt::LocalDate:
+ _localDateButton->setChecked(true);
+ break;
+ case Qt::TextDate:
+ _customDateButton->setChecked(true);
+ break;
+ }
+
+ _autoSaveDelay->setValue( _settings.autoSaveDelay );
+}
+
+
+void SavePreferences::customDateActivated(bool on)
+{
+ _dateFormatEdit->setEnabled(on);
+ _dateFormatEdit->setFocus();
+}
+
+void SavePreferences::setAutoSaveVisible( const bool on )
+{
+ if( on ) _autoSaveBox->show();
+ else _autoSaveBox->hide();
+}
+
+
+
+IdentityPreferences::IdentityPreferences(QWidget* parent, const QString& project)
+ : QWidget(parent)
+{
+ QWidget* page = this;
+ QVBoxLayout* layout=new QVBoxLayout(page);
+ layout->setSpacing(KDialog::spacingHint());
+ layout->setMargin(KDialog::marginHint());
+
+ if( !project.isEmpty() )
+ {
+ // show the project name in the widget at the top
+ layout->addWidget(new QLabel(i18n("<font size=\"+1\">Project: %1</font>").arg(project),page));
+ }
+
+ QGroupBox* group = new QGroupBox(2,Qt::Horizontal,page);
+ layout->addWidget(group);
+ group->setMargin(KDialog::marginHint());
+
+ QLabel* tempLabel=new QLabel(i18n("&Name:"),group);
+ _nameEdit = new QLineEdit(group, "kcfg_AuthorName");
+ tempLabel->setBuddy(_nameEdit);
+
+ tempLabel=new QLabel(i18n("Localized na&me:"),group);
+ _localNameEdit = new QLineEdit(group, "kcfg_LocalAuthorName");
+ tempLabel->setBuddy(_localNameEdit);
+
+ tempLabel=new QLabel(i18n("E&mail:"),group);
+ _mailEdit = new QLineEdit(group, "kcfg_AuthorEmail");
+ tempLabel->setBuddy(_mailEdit);
+
+
+ tempLabel=new QLabel(i18n("&Full language name:"),group);
+
+ QHBox *hbox = new QHBox(group);
+ hbox->setSpacing(KDialog::spacingHint());
+ _langEdit = new QLineEdit(hbox, "kcfg_Language");
+ tempLabel->setBuddy(_langEdit);
+ tempLabel=new QLabel(i18n("Lan&guage code:"),hbox);
+ _langCodeEdit = new QLineEdit(hbox, "kcfg_LanguageCode");
+ tempLabel->setBuddy(_langCodeEdit);
+ connect(_langCodeEdit,SIGNAL(textChanged(const QString&)), this
+ , SLOT(checkTestPluralButton()));
+
+ tempLabel=new QLabel(i18n("&Language mailing list:"),group);
+ _listEdit = new QLineEdit(group, "kcfg_Mailinglist");
+ _listEdit->setMinimumSize(100,_listEdit->sizeHint().height());
+ tempLabel->setBuddy(_listEdit);
+
+ tempLabel=new QLabel(i18n("&Timezone:"), group);
+ _timezoneEdit = new QLineEdit(group, "kcfg_Timezone");
+ _timezoneEdit->setMinimumSize(100,_timezoneEdit->sizeHint().height());
+ tempLabel->setBuddy(_timezoneEdit);
+
+
+ QString whatsThisMsg=i18n("<qt><p><b>Identity</b></p>\n"
+"<p>Fill in information about you and your translation team.\n"
+"This information is used when updating the header of a file.</p>\n"
+"<p>You can find the options if and what fields in the header should be updated\n"
+"on page <b>Save</b> in this dialog.</p></qt>");
+
+ QWhatsThis::add(group,whatsThisMsg);
+
+
+ group = new QGroupBox(1,Qt::Horizontal,page);
+ layout->addWidget(group);
+ group->setMargin(KDialog::marginHint());
+
+ hbox = new QHBox(group);
+ hbox->setSpacing(KDialog::spacingHint());
+
+ QLabel *label = new QLabel(i18n("&Number of singular/plural forms:"), hbox);
+ _pluralFormsBox = new QSpinBox(0,100,1,hbox, "kcfg_PluralForms");
+ _pluralFormsBox->setSpecialValueText(
+ i18n("automatic choose number of plural forms","Automatic"));
+ label->setBuddy(_pluralFormsBox);
+ connect(_pluralFormsBox,SIGNAL(valueChanged(int)), this
+ , SLOT(checkTestPluralButton()));
+
+ hbox->setStretchFactor(_pluralFormsBox,1);
+
+ _testPluralButton = new QPushButton(i18n("Te&st"),hbox);
+ _testPluralButton->setEnabled(false);
+ connect(_testPluralButton, SIGNAL(clicked()), this
+ , SLOT(testPluralForm()));
+
+ const QString msg=i18n("<qt><p><b>Number of singular/plural forms</b></p>"
+ "<p><b>Note</b>: This option is KDE specific. "
+ "If you are not translating a KDE application, you can safely "
+ "ignore this option.</p>"
+ "<p>Choose here how many singular and plural forms are used in "
+ "your language. "
+ "This number must correspond to the settings of your language "
+ "team.</p>"
+ "<p>Alternatively, you can set this option to "
+ "<i>Automatic</i> and KBabel will try to get this information "
+ "automatically from KDE. Use the <i>Test</i> button "
+ "to test if it can find it out.</p></qt>");
+ QWhatsThis::add(_pluralFormsBox,msg);
+ QWhatsThis::add(_testPluralButton,msg);
+
+ QVBox* vbox = new QVBox(group);
+ vbox->setSpacing(KDialog::spacingHint());
+
+ label = new QLabel(i18n("&GNU plural form header:"), vbox);
+
+ hbox = new QHBox(vbox);
+ hbox->setSpacing(KDialog::spacingHint());
+
+ _gnuPluralFormHeaderEdit = new QLineEdit(hbox, "kcfg_PluralFormsHeader");
+ label->setBuddy(_gnuPluralFormHeaderEdit);
+
+ hbox->setStretchFactor(_gnuPluralFormHeaderEdit,1);
+
+ _testGnuPluralFormButton = new QPushButton(i18n("&Lookup"),hbox);
+ connect(_testGnuPluralFormButton, SIGNAL(clicked()), this
+ , SLOT(lookupGnuPluralFormHeader()));
+
+ _checkPluralArgumentBox = new QCheckBox( i18n("Re&quire plural form arguments in translation")
+ , group, "kcfg_CheckPluralArgument" );
+ QWhatsThis::add(_checkPluralArgumentBox,
+ i18n("<qt><p><b>Require plural form arguments in translation</b></p>\n"
+ "<p><b>Note</b>: This option is KDE specific at the moment. "
+ "If you are not translating a KDE application, you can safely "
+ "ignore this option.</p>\n"
+ "<p>If is this option enabled, the validation check will "
+ "require the %n argument to be present in the message.</p></qt>"));
+
+ QWhatsThis::add(_gnuPluralFormHeaderEdit,
+ i18n("<qt><p><b>GNU plural form header</b></p>\n"
+ "<p>Here you can fill a header entry for GNU plural form handling; "
+ "if you leave the entry empty, the entry in the PO file will not be "
+ "changed or added.</p>\n"
+ "<p>KBabel can automatically try to determine value suggested by the "
+ "GNU gettext tools for currently set language; just press the <b>Lookup</b> "
+ "button.</p></qt>"));
+
+ layout->addStretch(1);
+
+ page->setMinimumSize(sizeHintForWidget(page));
+
+ setMinimumSize(sizeHint());
+
+ _mailEdit->installEventFilter(this);
+ _listEdit->installEventFilter(this);
+}
+
+void IdentityPreferences::defaults(const IdentitySettings& settings)
+{
+ _nameEdit->setText(settings.authorName);
+ _localNameEdit->setText(settings.authorLocalizedName);
+ _langEdit->setText(settings.languageName);
+ _langCodeEdit->setText(settings.languageCode);
+ _listEdit->setText(settings.mailingList);
+ _timezoneEdit->setText(settings.timeZone);
+ _pluralFormsBox->setValue(settings.numberOfPluralForms);
+ _gnuPluralFormHeaderEdit->setText(settings.gnuPluralFormHeader);
+ _checkPluralArgumentBox->setChecked(settings.checkPluralArgument);
+}
+
+bool IdentityPreferences::eventFilter(QObject *o, QEvent *e)
+{
+ if(e->type() == QEvent::Drop)
+ {
+ QDropEvent *de = static_cast<QDropEvent*>(e);
+ KURL::List urlList;
+ if(de && KURLDrag::decode(de,urlList))
+ {
+ KURL url(urlList.first());
+ if(url.protocol()== "mailto")
+ {
+ QString mail=url.path();
+
+ bool handled=false;
+ if(o == _mailEdit)
+ {
+ handled=true;
+ _mailEdit->setText(mail);
+ }
+ else if(o == _listEdit)
+ {
+ handled=true;
+ _listEdit->setText(mail);
+ }
+
+ if(handled)
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+void IdentityPreferences::checkTestPluralButton()
+{
+ int val = _pluralFormsBox->value();
+ QString lang=_langCodeEdit->text();
+
+ _testPluralButton->setEnabled(val==0 && !lang.isEmpty());
+}
+
+void IdentityPreferences::testPluralForm()
+{
+ QString lang=_langCodeEdit->text();
+
+ if(lang.isEmpty())
+ {
+ KMessageBox::sorry(this,i18n("Please insert a language code first."));
+ return;
+ }
+
+ int number=Catalog::getNumberOfPluralForms(lang);
+
+ QString msg;
+
+ if(number < 0)
+ {
+ msg = i18n("It is not possible to find out the number "
+ "of singular/plural forms automatically for the "
+ "language code \"%1\".\n"
+ "Do you have kdelibs.po installed for this language?\n"
+ "Please set the correct number manually.").arg(lang);
+ }
+ else
+ {
+ msg = i18n("The number of singular/plural forms found for "
+ "the language code \"%1\" is %2.").arg(lang).arg(number);
+ }
+
+ if(!msg.isEmpty())
+ {
+ KMessageBox::information(this,msg);
+ }
+}
+
+void IdentityPreferences::lookupGnuPluralFormHeader()
+{
+ QString lang=_langCodeEdit->text();
+
+ if(lang.isEmpty())
+ {
+ KMessageBox::sorry(this,i18n("Please insert a language code first."));
+ return;
+ }
+
+ QString header=GNUPluralForms(lang);
+
+ if( header.isEmpty() )
+ {
+ KMessageBox::information(this, i18n("It was not possible to determine "
+ "GNU header for plural forms. Maybe your GNU gettext tools are too "
+ "old or they do not contain a suggested value for your language.") );
+ }
+ else
+ {
+ _gnuPluralFormHeaderEdit->setText( header );
+ }
+}
+
+
+MiscPreferences::MiscPreferences(QWidget *parent)
+ : QWidget(parent), _regExpEditDialog(0)
+{
+ QWidget* page = this;
+
+ QVBoxLayout* layout=new QVBoxLayout(page);
+ layout->setSpacing(KDialog::spacingHint());
+ layout->setMargin(KDialog::marginHint());
+
+ QGroupBox* box=new QGroupBox(1,Qt::Horizontal,page);
+ box->setMargin(KDialog::marginHint());
+ layout->addWidget(box);
+
+ QHBox *hbox = new QHBox(box);
+ hbox->setSpacing(KDialog::spacingHint());
+
+ QLabel *label = new QLabel(i18n("&Marker for keyboard accelerator:"),hbox);
+ accelMarkerEdit = new KLineEdit(hbox, "kcfg_AccelMarker");
+ accelMarkerEdit->setMaxLength(1);
+ label->setBuddy(accelMarkerEdit);
+ hbox->setStretchFactor(accelMarkerEdit,1);
+ QString msg=i18n("<qt><p><b>Marker for keyboard accelerator</b></p>"
+ "<p>Define here, what character marks the following "
+ "character as keyboard accelerator. For example in Qt it is "
+ "'&amp;' and in Gtk it is '_'.</p></qt>");
+ QWhatsThis::add(label,msg);
+ QWhatsThis::add(accelMarkerEdit,msg);
+
+
+ hbox = new QHBox(box);
+ hbox->setSpacing(KDialog::spacingHint());
+
+ label = new QLabel(i18n("&Regular expression for context information:")
+ ,hbox);
+ contextInfoEdit = new KLineEdit(hbox, "kcfg_ContextInfo");
+ label->setBuddy(contextInfoEdit);
+ hbox->setStretchFactor(contextInfoEdit,1);
+
+ msg=i18n("<qt><p><b>Regular expression for context information</b></p>"
+ "<p>Enter a regular expression here which defines what is "
+ "context information in the message and must not get "
+ "translated.</p></qt>");
+ QWhatsThis::add(label,msg);
+ QWhatsThis::add(contextInfoEdit,msg);
+
+ if( !KTrader::self()->query("KRegExpEditor/KRegExpEditor").isEmpty() )
+ {
+ _regExpButton = new QPushButton( i18n("&Edit..."), hbox );
+ connect( _regExpButton, SIGNAL( clicked() ), this, SLOT( regExpButtonClicked()));
+ }
+
+
+ // preferences for mail attachments
+ QVButtonGroup* vbgroup = new QVButtonGroup(page);
+ vbgroup->setTitle(i18n("Compression Method for Mail Attachments"));
+ vbgroup->setRadioButtonExclusive(true);
+ vbgroup->setMargin(KDialog::marginHint());
+ layout->addWidget(vbgroup);
+
+ bzipButton = new QRadioButton(i18n("tar/&bzip2"), vbgroup, "kcfg_BZipCompression");
+ gzipButton = new QRadioButton(i18n("tar/&gzip"), vbgroup);
+
+ compressSingle = new QCheckBox(i18n("&Use compression when sending "
+ "a single file"), vbgroup, "kcfg_CompressSingleFile");
+
+ layout->addStretch(1);
+ page->setMinimumSize(sizeHintForWidget(page));
+}
+
+void MiscPreferences::defaults(const MiscSettings& settings)
+{
+ accelMarkerEdit->setText(settings.accelMarker);
+ contextInfoEdit->setText(settings.contextInfo.pattern());
+ if( settings.useBzip )
+ bzipButton->setChecked (true);
+ else
+ gzipButton->setChecked (true);
+
+ compressSingle->setChecked(settings.compressSingleFile);
+}
+
+QString MiscPreferences::contextInfo() const
+{
+ QString temp=contextInfoEdit->text();
+
+ bool quoted=false;
+ QString newStr;
+
+ for(uint i=0; i<temp.length(); i++)
+ {
+ if(temp[i]=='n')
+ {
+ quoted=!quoted;
+ newStr+=temp[i];
+ }
+ else if(temp[i]=='n' && quoted)
+ {
+ newStr[newStr.length()-1]='\n';
+ quoted=false;
+ }
+ else
+ {
+ quoted=false;
+ newStr+=temp[i];
+ }
+ }
+
+ return newStr;
+}
+
+void MiscPreferences::setContextInfo(QString reg)
+{
+ reg.replace("\n","\\n");
+ contextInfoEdit->setText(reg);
+}
+
+void MiscPreferences::regExpButtonClicked()
+{
+ if ( _regExpEditDialog==0 )
+ _regExpEditDialog = KParts::ComponentFactory::createInstanceFromQuery<QDialog>
+ ("KRegExpEditor/KRegExpEditor", QString::null, this );
+
+ KRegExpEditorInterface *iface = dynamic_cast<KRegExpEditorInterface *>( _regExpEditDialog );
+ if( iface )
+ {
+ iface->setRegExp( contextInfoEdit->text() );
+ if( _regExpEditDialog->exec() == QDialog::Accepted )
+ contextInfoEdit->setText( iface->regExp() );
+ }
+}
+
+
+SpellPreferences::SpellPreferences(QWidget* parent)
+ : QWidget(parent)
+{
+ QWidget* page = this;
+ QVBoxLayout* layout=new QVBoxLayout(page);
+ layout->setSpacing(KDialog::spacingHint());
+ layout->setMargin(KDialog::marginHint());
+
+
+ onFlyBtn = new QCheckBox(i18n("On the &fly spellchecking"),page, "kcfg_OnFlySpellCheck");
+ layout->addWidget(onFlyBtn);
+
+ QWhatsThis::add(onFlyBtn, i18n("<qt><p><b>On the fly spellchecking</b></p>"
+ "<p>Activate this to let KBabel spell check the text "
+ "as you type. Mispelled words will be colored by the error color.</p></qt>"));
+
+ spellConfig = new KSpellConfig(page,"spellConfigWidget",0,false);
+ layout->addWidget(spellConfig);
+ remIgnoredBtn = new QCheckBox(i18n("&Remember ignored words"),page, "kcfg_RememberIgnored");
+ layout->addWidget(remIgnoredBtn);
+
+ connect( spellConfig, SIGNAL( configChanged() )
+ , this, SIGNAL ( settingsChanged() ) );
+
+ QLabel *tempLabel = new QLabel(i18n("F&ile to store ignored words:"),page);
+ layout->addWidget(tempLabel);
+ ignoreURLEdit = new KURLRequester(page, "kcfg_IgnoreURL");
+ layout->addWidget(ignoreURLEdit);
+ tempLabel->setBuddy(ignoreURLEdit);
+
+ connect(remIgnoredBtn,SIGNAL(toggled(bool)),ignoreURLEdit
+ ,SLOT(setEnabled(bool)));
+
+
+ QString msg = i18n("<qt><p><b>Remember ignored words</b></p>"
+ "<p>Activate this, to let KBabel ignore the words, where you have "
+ "chosen <i>Ignore All</i> in the spell check dialog, "
+ "in every spell check.</p></qt>");
+
+ QWhatsThis::add(remIgnoredBtn,msg);
+ QWhatsThis::add(tempLabel,msg);
+ QWhatsThis::add(ignoreURLEdit,msg);
+
+ layout->addStretch(1);
+
+ page->setMinimumSize(sizeHintForWidget(page));
+
+ setMinimumSize(sizeHint());
+}
+
+
+
+void SpellPreferences::updateWidgets(const SpellcheckSettings& settings)
+{
+ spellConfig->setClient(settings.spellClient);
+ spellConfig->setNoRootAffix(settings.noRootAffix);
+ spellConfig->setRunTogether(settings.runTogether);
+ spellConfig->setEncoding(settings.spellEncoding);
+ spellConfig->setDictionary(settings.spellDict);
+}
+
+
+void SpellPreferences::mergeSettings(SpellcheckSettings& settings) const
+{
+ settings.noRootAffix=spellConfig->noRootAffix();
+ settings.runTogether=spellConfig->runTogether();
+ settings.spellClient=spellConfig->client();
+ settings.spellEncoding=spellConfig->encoding();
+ settings.spellDict=spellConfig->dictionary();
+
+ settings.valid=true;
+}
+
+void SpellPreferences::defaults(const SpellcheckSettings& settings)
+{
+ remIgnoredBtn->setChecked(settings.rememberIgnored);
+ ignoreURLEdit->setURL(settings.ignoreURL);
+
+ onFlyBtn->setChecked(settings.onFlySpellcheck);
+
+ KSpellConfig spCfg;
+ *spellConfig = spCfg;
+}
+
+CatmanPreferences::CatmanPreferences(QWidget* parent)
+ : QWidget(parent)
+{
+ QWidget* page = this;
+
+ QVBoxLayout* layout=new QVBoxLayout(page);
+ layout->setSpacing(KDialog::spacingHint());
+ layout->setMargin(KDialog::marginHint());
+
+ QGroupBox* box=new QGroupBox(1,Qt::Horizontal,page);
+ box->setMargin(KDialog::marginHint());
+ layout->addWidget(box);
+
+ QLabel* label=new QLabel(i18n("&Base folder of PO files:"),box);
+ QHBox* hbox = new QHBox(box);
+ hbox->setSpacing(KDialog::spacingHint());
+
+ const KFile::Mode mode = static_cast<KFile::Mode>( KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly );
+
+
+ _poDirEdit = new KURLRequester(hbox, "kcfg_PoBaseDir");
+ _poDirEdit->setMode( mode );
+ _poDirEdit->setMinimumSize(250,_poDirEdit->sizeHint().height());
+ label->setBuddy(_poDirEdit);
+
+
+ label=new QLabel(i18n("Ba&se folder of POT files:"),box);
+ hbox = new QHBox(box);
+ hbox->setSpacing(KDialog::spacingHint());
+
+ _potDirEdit = new KURLRequester(hbox, "kcfg_PotBaseDir");
+ _potDirEdit->setMode( mode );
+ _potDirEdit->setMinimumSize(250,_potDirEdit->sizeHint().height());
+ label->setBuddy(_potDirEdit);
+
+
+
+ QWhatsThis::add(box,i18n("<qt><p><b>Base folders</b></p>\n"
+ "<p>Type in the folders which contain all your PO and POT files.\n"
+ "The files and the folders in these folders will then be merged into one\n"
+ "tree.</p></qt>"));
+
+
+ box=new QGroupBox(1,Qt::Horizontal,page);
+ box->setMargin(KDialog::marginHint());
+ layout->addWidget(box);
+
+ _openWindowButton = new QCheckBox(i18n("O&pen files in new window"),box, "kcfg_OpenWindow");
+
+
+ QWhatsThis::add(_openWindowButton,i18n("<qt><p><b>Open files in new window</b></p>\n"
+"<p>If this is activated all files that are opened from the Catalog Manager are opened\n"
+"in a new window.</p></qt>"));
+
+ _killButton = new QCheckBox( i18n("&Kill processes on exit") , box, "kcfg_KillCmdOnExit" );
+
+ QWhatsThis::add( _killButton , i18n("<qt><p><b>Kill processes on exit</b></p>\n"
+"<p>If you check this, KBabel tries to kill the processes, that have not exited already when KBabel exits,\n"
+"by sending a kill signal to them.</p>\n"
+"<p>NOTE: It is not guaranteed that the processes will be killed.</p></qt>") );
+
+
+ _indexButton = new QCheckBox( i18n("Create inde&x for file contents"), box, "kcfg_IndexWords" );
+
+ QWhatsThis::add( _indexButton , i18n("<qt><p><b>Create index for file contents</b></p>\n"
+"<p>If you check this, KBabel will create an index for each PO file to speed up the find/replace functions.</p>\n"
+"<p>NOTE: This will slow down updating the file information considerably.</p></qt>") );
+
+ m_msgfmtButton = new QCheckBox( i18n("Run &msgfmt before processing a file"), box, "kcfg_msgfmt" );
+
+ QWhatsThis::add( m_msgfmtButton, i18n("<qt><p><b>Run msgfmt before processing a file</b></p>"
+ "<p>If you enable this, KBabel will run Gettext's "
+ "msgfmt tool before processing a file.</p>"
+ "<p>Enabling this setting is recommended, even if it causes processing to be slower. "
+ "This setting is enabled by default.</p>"
+ "<p>Disabling is useful for slow computers and when you want "
+ "to translate PO files that are not supported by the current version "
+ "of the Gettext tools that are on your system. "
+ "The drawback of disabling is that hardly any syntax checking is done by the processing code, "
+ "so invalid PO files could be shown as good ones, "
+ "even if Gettext tools would reject such files.</p></qt>") );
+
+ layout->addStretch(1);
+
+ page->setMinimumSize(sizeHintForWidget(page));
+
+ setMinimumSize(sizeHint());
+}
+
+
+void CatmanPreferences::defaults(const CatManSettings& settings)
+{
+ _poDirEdit->setURL(settings.poBaseDir);
+ _potDirEdit->setURL(settings.potBaseDir);
+
+ _openWindowButton->setChecked(settings.openWindow);
+
+ _killButton->setChecked(settings.killCmdOnExit );
+ _indexButton->setChecked(settings.indexWords );
+ m_msgfmtButton->setChecked( settings.msgfmt );
+}
+
+DirCommandsPreferences::DirCommandsPreferences(QWidget* parent)
+ : QWidget(parent)
+{
+ QWidget* page = this;
+
+ QVBoxLayout* layout=new QVBoxLayout(page);
+ layout->setSpacing(KDialog::spacingHint());
+ layout->setMargin(KDialog::marginHint());
+
+ QGroupBox* box = new QGroupBox( 1 , Qt::Horizontal , i18n("Commands for Folders") , page );
+ box->setMargin( KDialog::marginHint() );
+ layout->addWidget( box );
+
+ _dirCmdEdit = new CmdEdit( box );
+ new QLabel( i18n("Replaceables:\n@PACKAGE@, @PODIR@, @POTDIR@\n"
+ "@POFILES@, @MARKEDPOFILES@"), box);
+
+ connect (_dirCmdEdit, SIGNAL(widgetChanged()), this, SIGNAL(settingsChanged()));
+
+ QWhatsThis::add( box , i18n("<qt><p><b>Commands for folders</b></p>"
+"<p>Insert here the commands you want to execute in folders from "
+"the Catalog Manager. The commands are then shown in the submenu "
+"<b>Commands</b> in the Catalog Manager's context menu.</p>"
+"<p>The following strings will be replaced in a command:<ul>"
+"<li>@PACKAGE@: The name of the folder without path</li>"
+"<li>@PODIR@: The name of the PO-folder with path</li>"
+"<li>@POTDIR@: The name of the template folder with path</li>"
+"<li>@POFILES@: The names of the PO files with path</li>"
+"<li>@MARKEDPOFILES@: The names of the marked PO files with path</li>"
+"</ul></p>"
+"</qt>") );
+
+
+
+ layout->addStretch(1);
+ page->setMinimumSize(sizeHintForWidget(page));
+
+ setMinimumSize(sizeHint());
+}
+
+
+DirCommandsPreferences::~DirCommandsPreferences()
+{
+}
+
+
+void DirCommandsPreferences::updateWidgets(const CatManSettings& settings)
+{
+ _dirCmdEdit->setCommands( settings.dirCommands , settings.dirCommandNames );
+}
+
+
+void DirCommandsPreferences::mergeSettings(CatManSettings& settings) const
+{
+ _dirCmdEdit->commands( settings.dirCommands , settings.dirCommandNames );
+}
+
+void DirCommandsPreferences::defaults(const CatManSettings& settings)
+{
+ _dirCmdEdit->setCommands( settings.dirCommands, settings.dirCommandNames );
+}
+
+
+FileCommandsPreferences::FileCommandsPreferences(QWidget* parent)
+ : QWidget(parent)
+{
+ QWidget* page = this;
+
+ QVBoxLayout* layout=new QVBoxLayout(page);
+ layout->setSpacing(KDialog::spacingHint());
+ layout->setMargin(KDialog::marginHint());
+
+ QGroupBox* box=new QGroupBox( 1 , Qt::Horizontal , i18n("Commands for Files") , page );
+ box->setMargin( KDialog::marginHint() );
+ layout->addWidget( box );
+
+ _fileCmdEdit = new CmdEdit( box );
+ new QLabel( i18n("Replaceables:\n"
+"@PACKAGE@, @POFILE@,@POTFILE@,\n@PODIR@, @POTDIR@"), box);
+
+ connect (_fileCmdEdit, SIGNAL(widgetChanged()), this, SIGNAL(settingsChanged()));
+
+ QWhatsThis::add( box , i18n("<qt><p><b>Commands for files</b></p>"
+"<p>Insert here the commands you want to execute on files from "
+"the Catalog Manager. The commands are then shown in the submenu "
+"<b>Commands</b> in the Catalog Manager's context menu.</p>"
+"<p>The following strings will be replaced in a command:<ul>"
+"<li>@PACKAGE@: The name of the file without path and extension</li>"
+"<li>@POFILE@: The name of the PO-file with path and extension</li>"
+"<li>@POTFILE@: The name of the corresponding template file with path "
+"and extension</li>"
+"<li>@POEMAIL@: The name and email address of the last translator</li>"
+"<li>@PODIR@: The name of the folder the PO-file is in, with path</li>"
+"<li>@POTDIR@: The name of the folder the template file is in, with "
+"path</li></ul></p></qt>") );
+
+
+
+ layout->addStretch(1);
+ page->setMinimumSize(sizeHintForWidget(page));
+
+ setMinimumSize(sizeHint());
+}
+
+
+FileCommandsPreferences::~FileCommandsPreferences()
+{
+}
+
+
+void FileCommandsPreferences::updateWidgets(const CatManSettings& settings)
+{
+ _fileCmdEdit->setCommands( settings.fileCommands , settings.fileCommandNames );
+}
+
+
+void FileCommandsPreferences::mergeSettings(CatManSettings& settings) const
+{
+ _fileCmdEdit->commands( settings.fileCommands , settings.fileCommandNames );
+}
+
+void FileCommandsPreferences::defaults(const CatManSettings& settings)
+{
+ _fileCmdEdit->setCommands( settings.fileCommands, settings.fileCommandNames );
+}
+
+ViewPreferences::ViewPreferences(QWidget* parent)
+ : QWidget(parent)
+{
+ QWidget* page = this;
+
+ QVBoxLayout* layout=new QVBoxLayout(page);
+ layout->setSpacing(KDialog::spacingHint());
+ layout->setMargin(KDialog::marginHint());
+
+ QGroupBox* box=new QGroupBox(2, Qt::Horizontal,i18n("Shown Columns"),page);
+ box->setMargin(KDialog::marginHint());
+ layout->addWidget(box);
+
+ _flagColumnCheckbox = new QCheckBox( i18n("Fla&g"), box, "kcfg_ShowFlagColumn" );
+ _fuzzyColumnCheckbox = new QCheckBox( i18n("&Fuzzy"), box, "kcfg_ShowFuzzyColumn" );
+ _untranslatedColumnCheckbox = new QCheckBox( i18n("&Untranslated"), box, "kcfg_ShowUntranslatedColumn" );
+ _totalColumnCheckbox = new QCheckBox( i18n("&Total"), box, "kcfg_ShowTotalColumn" );
+ _cvsColumnCheckbox = new QCheckBox( i18n("SVN/&CVS status"), box, "kcfg_ShowCVSColumn" );
+ _revisionColumnCheckbox = new QCheckBox( i18n("Last &revision"), box, "kcfg_ShowRevisionColumn" );
+ _translatorColumnCheckbox = new QCheckBox( i18n("Last t&ranslator"), box, "kcfg_ShowTranslatorColumn" );
+
+ QWhatsThis::add(box,i18n("<qt><p><b>Shown columns</b></p>\n"
+ "<p></p></qt>"));
+
+ layout->addStretch(1);
+
+ page->setMinimumSize(sizeHintForWidget(page));
+
+ setMinimumSize(sizeHint());
+}
+
+
+void ViewPreferences::defaults(const CatManSettings& _settings)
+{
+ _flagColumnCheckbox->setChecked(_settings.flagColumn);
+ _fuzzyColumnCheckbox->setChecked(_settings.fuzzyColumn);
+ _untranslatedColumnCheckbox->setChecked(_settings.untranslatedColumn);
+ _totalColumnCheckbox->setChecked(_settings.totalColumn);
+ _cvsColumnCheckbox->setChecked(_settings.cvsColumn);
+ _revisionColumnCheckbox->setChecked(_settings.revisionColumn);
+ _translatorColumnCheckbox->setChecked(_settings.translatorColumn);
+}
+
+SourceContextPreferences::SourceContextPreferences(QWidget* parent): QWidget(parent)
+{
+ QWidget* page = this;
+ QVBoxLayout* layout=new QVBoxLayout(page);
+ layout->setSpacing(KDialog::spacingHint());
+ layout->setMargin(KDialog::marginHint());
+
+ QHBox* box = new QHBox(page);
+ box->setSpacing(KDialog::spacingHint());
+ QLabel* tempLabel=new QLabel(i18n("&Base folder for source code:"),box);
+
+ const KFile::Mode mode = static_cast<KFile::Mode>( KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly );
+ _coderootEdit = new KURLRequester ( box, "kcfg_CodeRoot" );
+ _coderootEdit->setMode( mode );
+ _coderootEdit->setMinimumSize( 250, _coderootEdit->sizeHint().height() );
+ tempLabel->setBuddy( _coderootEdit );
+ layout->addWidget(box);
+
+ // FIXME: use KConfigXT
+ _pathsEditor = new KListEditor(page);
+ _pathsEditor->setTitle(i18n("Path Patterns"));
+ layout->addWidget(_pathsEditor);
+
+ connect ( _pathsEditor, SIGNAL (itemsChanged ())
+ , this, SIGNAL (itemsChanged ()));
+
+ _pathsEditor->installEventFilter(this);
+
+ setMinimumSize(sizeHint());
+}
+
+SourceContextPreferences::~SourceContextPreferences()
+{
+}
+
+void SourceContextPreferences::mergeSettings(KBabel::SourceContextSettings& settings) const
+{
+ settings.sourcePaths=_pathsEditor->list();
+}
+
+void SourceContextPreferences::updateWidgets(const KBabel::SourceContextSettings& settings)
+{
+ _pathsEditor->setList(settings.sourcePaths);
+}
+
+void SourceContextPreferences::defaults(const KBabel::SourceContextSettings& settings)
+{
+ _pathsEditor->setList(settings.sourcePaths);
+}
+
+bool SourceContextPreferences::eventFilter( QObject *, QEvent *e )
+{
+ if( e->type() == QEvent::KeyPress )
+ {
+ QKeyEvent *ke = dynamic_cast<QKeyEvent*>(e);
+ if( ke->key() == Key_Return || ke->key() == Key_Enter )
+ return true;
+ }
+ return false;
+}
+
+#include "projectprefwidgets.moc"
diff --git a/kbabel/commonui/projectprefwidgets.h b/kbabel/commonui/projectprefwidgets.h
new file mode 100644
index 00000000..81a1b3e6
--- /dev/null
+++ b/kbabel/commonui/projectprefwidgets.h
@@ -0,0 +1,285 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2001 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2001-2005 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef PROJECTPREFWIDGETS_H
+#define PROJECTPREFWIDGETS_H
+
+#include <ktabctl.h>
+#include <qptrlist.h>
+#include "projectsettings.h"
+
+
+class KLineEdit;
+class QLineEdit;
+class QCheckBox;
+class QComboBox;
+class QListBox;
+class QRadioButton;
+class QSpinBox;
+class CmdEdit;
+class KFontChooser;
+class KColorButton;
+class KComboBox;
+class KSpellConfig;
+class KURLRequester;
+class QPushButton;
+class QGroupBox;
+class KListEditor;
+class ToolSelectionWidget;
+class KIntNumInput;
+class KURLRequester;
+
+struct ModuleInfo;
+
+class KDE_EXPORT SavePreferences : public KTabCtl
+{
+ Q_OBJECT
+public:
+ SavePreferences(QWidget* parent=0);
+ void defaults(const KBabel::SaveSettings& settings);
+ void setAutoSaveVisible(const bool on);
+
+private:
+ QCheckBox* _lastButton;
+ QCheckBox* _revisionButton;
+ QCheckBox* _languageButton;
+ QCheckBox* _charsetButton;
+ QCheckBox* _encodingButton;
+ QCheckBox* _projectButton;
+
+ QCheckBox* _updateButton;
+ QCheckBox* _autoCheckButton;
+ QCheckBox* _saveObsoleteButton;
+
+ QComboBox* _encodingBox;
+ QCheckBox* _oldEncodingButton;
+
+ QRadioButton* _defaultDateButton;
+ QRadioButton* _localDateButton;
+ QRadioButton* _customDateButton;
+ QLineEdit* _dateFormatEdit;
+
+ QLineEdit* _projectEdit;
+
+ QRadioButton* _removeFSFButton;
+ QRadioButton* _updateFSFButton;
+ QRadioButton* _nochangeFSFButton;
+ QCheckBox* _translatorCopyrightButton;
+
+ QCheckBox* _descriptionButton;
+ QLineEdit* _descriptionEdit;
+
+ KIntNumInput * _autoSaveDelay;
+ QGroupBox * _autoSaveBox;
+
+private slots:
+ void customDateActivated(bool on);
+};
+
+
+class IdentityPreferences : public QWidget
+{
+ Q_OBJECT
+public:
+ IdentityPreferences(QWidget *parent = 0, const QString& project = "");
+ virtual bool eventFilter(QObject *, QEvent*);
+ void defaults(const KBabel::IdentitySettings& settings);
+
+private slots:
+ void checkTestPluralButton();
+ void testPluralForm();
+ void lookupGnuPluralFormHeader();
+
+private:
+ QLineEdit* _nameEdit;
+ QLineEdit* _localNameEdit;
+ QLineEdit* _mailEdit;
+ QLineEdit* _langEdit;
+ QLineEdit* _langCodeEdit;
+ QLineEdit* _listEdit;
+
+ QLineEdit* _timezoneEdit;
+ QSpinBox *_pluralFormsBox;
+ QPushButton *_testPluralButton;
+ QCheckBox* _checkPluralArgumentBox;
+ QLineEdit* _gnuPluralFormHeaderEdit;
+ QPushButton *_testGnuPluralFormButton;
+};
+
+
+class MiscPreferences : public QWidget
+{
+ Q_OBJECT
+public:
+ MiscPreferences(QWidget *parent=0);
+ void defaults(const KBabel::MiscSettings& settings);
+
+private slots:
+ void regExpButtonClicked();
+
+private:
+ void setContextInfo(QString reg);
+ QString contextInfo() const;
+
+ KLineEdit *contextInfoEdit;
+ KLineEdit *accelMarkerEdit;
+
+ QDialog *_regExpEditDialog;
+ QPushButton *_regExpButton;
+
+ QRadioButton* bzipButton;
+ QRadioButton* gzipButton;
+ QCheckBox* compressSingle;
+};
+
+class SpellPreferences : public QWidget
+{
+ Q_OBJECT
+public:
+ SpellPreferences(QWidget *parent=0);
+
+ void mergeSettings(KBabel::SpellcheckSettings& set) const;
+ void updateWidgets(const KBabel::SpellcheckSettings& settings);
+ void defaults(const KBabel::SpellcheckSettings& settings);
+
+signals:
+ void settingsChanged();
+
+private:
+ KSpellConfig* spellConfig;
+ QCheckBox* remIgnoredBtn;
+ QCheckBox* onFlyBtn;
+ KURLRequester* ignoreURLEdit;
+
+};
+
+class CatmanPreferences : public QWidget
+{
+ Q_OBJECT
+public:
+ CatmanPreferences(QWidget *parent = 0);
+ void defaults(const KBabel::CatManSettings& settings);
+
+private:
+ KURLRequester* _poDirEdit;
+ KURLRequester* _potDirEdit;
+
+ QCheckBox* _openWindowButton;
+
+ QCheckBox* _killButton;
+ QCheckBox* _indexButton;
+ QCheckBox* m_msgfmtButton;
+};
+
+class DirCommandsPreferences : public QWidget
+{
+ Q_OBJECT
+public:
+ DirCommandsPreferences(QWidget *parent = 0);
+ virtual ~DirCommandsPreferences();
+
+ void mergeSettings(KBabel::CatManSettings& settings) const;
+ void updateWidgets(const KBabel::CatManSettings&);
+ void defaults(const KBabel::CatManSettings& settings);
+
+signals:
+ void settingsChanged();
+
+private:
+ CmdEdit* _dirCmdEdit;
+};
+
+class FileCommandsPreferences : public QWidget
+{
+ Q_OBJECT
+public:
+ FileCommandsPreferences(QWidget *parent = 0);
+ virtual ~FileCommandsPreferences();
+
+ void mergeSettings(KBabel::CatManSettings& settings) const;
+ void updateWidgets(const KBabel::CatManSettings& settings);
+ void defaults(const KBabel::CatManSettings& settings);
+
+signals:
+ void settingsChanged();
+
+private:
+ CmdEdit* _fileCmdEdit;
+};
+
+class ViewPreferences : public QWidget
+{
+ Q_OBJECT
+public:
+ ViewPreferences(QWidget *parent = 0);
+ void defaults(const KBabel::CatManSettings& settings);
+
+private:
+ QCheckBox* _flagColumnCheckbox;
+ QCheckBox* _fuzzyColumnCheckbox;
+ QCheckBox* _untranslatedColumnCheckbox;
+ QCheckBox* _totalColumnCheckbox;
+ QCheckBox* _cvsColumnCheckbox;
+ QCheckBox* _revisionColumnCheckbox;
+ QCheckBox* _translatorColumnCheckbox;
+};
+
+/**
+* This class implements preference widget for source context
+*
+* @short Class for setting preferences for source context
+* @author Stanislav Visnovsky <visnovsky@kde.org>
+*/
+class SourceContextPreferences : public QWidget
+{
+ Q_OBJECT
+public:
+ SourceContextPreferences(QWidget* parent=0);
+ virtual ~SourceContextPreferences();
+
+ void mergeSettings(KBabel::SourceContextSettings& settings) const;
+ void updateWidgets(const KBabel::SourceContextSettings& settings);
+ void defaults(const KBabel::SourceContextSettings& settings);
+
+ virtual bool eventFilter(QObject *, QEvent*);
+
+signals:
+ void itemsChanged ();
+
+private:
+ KURLRequester* _coderootEdit;
+ KListEditor* _pathsEditor;
+};
+
+#endif // PROJECTPREFWIDGETS_H
diff --git a/kbabel/commonui/projectwizard.cpp b/kbabel/commonui/projectwizard.cpp
new file mode 100644
index 00000000..d1202f4a
--- /dev/null
+++ b/kbabel/commonui/projectwizard.cpp
@@ -0,0 +1,172 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2004 by StanislavVsinovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#include "projectwizard.h"
+#include "projectwizardwidget.h"
+#include "projectwizardwidget2.h"
+
+#include "kbprojectmanager.h"
+
+#include <qcombobox.h>
+
+#include <kapplication.h>
+#include <kmessagebox.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <kurlrequester.h>
+
+using namespace KBabel;
+
+ProjectWizard::ProjectWizard(QWidget *parent,const char *name)
+ : KWizard(parent,name,true)
+{
+ _wizard = new ProjectStep1(this,"project wizard widget");
+
+ // fill the known language codes
+ KConfig all_languages("all_languages", true, false, "locale");
+ QStringList lang_codes = KGlobal::locale()->allLanguagesTwoAlpha();
+ for (QStringList::iterator it = lang_codes.begin();
+ it != lang_codes.end(); ++it)
+ {
+ // we need untranslated entries here, because of Translation Robot!
+ QString entry = (*it);
+ const int i = entry.find('_');
+ entry.replace(0, i, entry.left(i).lower());
+ all_languages.setGroup(entry);
+ entry = all_languages.readEntryUntranslated("Name");
+ if( ! entry.isEmpty() )
+ {
+ _wizard->_projectLanguage->insertItem( entry );
+ m_language_codes[entry] = (*it);
+ }
+ }
+
+ connect( _wizard->_projectName, SIGNAL(textChanged(const QString &)), this, SLOT(textChanged(const QString &)));
+ connect( _wizard->_projectFile, SIGNAL(textChanged(const QString &)), this, SLOT(textChanged(const QString &)));
+ connect( this, SIGNAL( helpClicked( void ) ), this, SLOT( slotHelpClicked( void ) ) );
+
+ addPage(_wizard, i18n("Basic Project Information"));
+
+ _wizard2 = new ProjectStep2(this,"project wizard widget2");
+ _wizard2->_poDirEdit->setMode( KFile::Directory );
+ _wizard2->_potDirEdit->setMode( KFile::Directory );
+ addPage(_wizard2, i18n("Translation Files"));
+
+ setFinishEnabled (_wizard2, true);
+ setNextEnabled (_wizard, false);
+}
+
+QString ProjectWizard::url()
+{
+ return _wizard->_projectFile->url();
+}
+
+Project::Ptr ProjectWizard::project()
+{
+ Project::Ptr p = ProjectManager::open( _wizard->_projectFile->url() );
+ p->setName( _wizard->_projectName->text() );
+
+ enum type { KDE, GNOME, TP, Other };
+
+ type project_type = (type) _wizard->_projectType->currentItem();
+
+ KBabel::CatManSettings catman = p->catManSettings();
+ catman.poBaseDir = _wizard2->_poDirEdit->url();
+ catman.potBaseDir = _wizard2->_potDirEdit->url();
+ p->setSettings (catman);
+
+ KBabel::IdentitySettings identity = p->identitySettings();
+ // Language
+ identity.languageName = _wizard->_projectLanguage->currentText();
+ // LanguageCode
+ identity.languageCode = m_language_codes[identity.languageName];
+ p->setSettings (identity);
+
+ KBabel::SaveSettings save = p->saveSettings();
+ // autochecksyntax (not for KDE - it uses incompatible plural forms formatting)
+ if( project_type == KDE )
+ {
+ save.autoSyntaxCheck = false;
+ }
+ p->setSettings (save);
+
+ KBabel::MiscSettings misc = p->miscSettings();
+ if (project_type == GNOME)
+ {
+ misc.accelMarker = '_';
+ }
+ p->setSettings (misc);
+
+ return p;
+}
+
+void ProjectWizard::next()
+{
+ // check if the file exists
+ QFileInfo file(url());
+
+ if( file.exists() )
+ {
+ if (KMessageBox::warningContinueCancel(0, i18n("The file '%1' already exists.\n"
+ "Do you want to replace it?").arg(url()), i18n("File Exists"), i18n("Replace") ) == KMessageBox::Cancel)
+ return;
+ }
+
+ KWizard::next();
+}
+
+void ProjectWizard::textChanged(const QString &)
+{
+ setNextEnabled( _wizard, !_wizard->_projectName->text().isEmpty() && !_wizard->_projectFile->url().isEmpty() );
+}
+
+Project::Ptr ProjectWizard::newProject()
+{
+ ProjectWizard* dialog = new ProjectWizard();
+ if( dialog->exec() == QDialog::Accepted )
+ {
+ Project::Ptr res = dialog->project();
+ delete dialog;
+ res->config()->sync();
+ return res;
+ }
+
+ return 0;
+}
+
+void ProjectWizard::slotHelpClicked( void )
+{
+ kapp->invokeHelp( "preferences-project-wizard", "kbabel" );
+}
+
+#include "projectwizard.moc"
diff --git a/kbabel/commonui/projectwizard.h b/kbabel/commonui/projectwizard.h
new file mode 100644
index 00000000..5c994784
--- /dev/null
+++ b/kbabel/commonui/projectwizard.h
@@ -0,0 +1,74 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef PROJECTWIZARD_H
+#define PROJECTWIZARD_H
+
+#include <kwizard.h>
+
+#include "kbproject.h"
+
+#include "qmap.h"
+#include "qstring.h"
+
+class ProjectStep1;
+class ProjectStep2;
+
+namespace KBabel {
+
+class KDE_EXPORT ProjectWizard : public KWizard
+{
+ Q_OBJECT
+public:
+ ProjectWizard(QWidget* parent = 0, const char * name = 0);
+
+ Project::Ptr project();
+
+ QString url();
+
+ static Project::Ptr newProject();
+
+private slots:
+ void textChanged(const QString &);
+ void slotHelpClicked( void );
+ virtual void next();
+
+private:
+ ProjectStep1* _wizard;
+ ProjectStep2* _wizard2;
+
+ QMap<QString, QString> m_language_codes;
+};
+
+}
+
+#endif // PROJECTPREF_H
diff --git a/kbabel/commonui/projectwizardwidget.ui b/kbabel/commonui/projectwizardwidget.ui
new file mode 100644
index 00000000..3ad04de7
--- /dev/null
+++ b/kbabel/commonui/projectwizardwidget.ui
@@ -0,0 +1,266 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>ProjectStep1</class>
+<author>Stanislav Visnovsky &lt;visnovsky@kde.org&gt;</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>ProjectStep1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>486</width>
+ <height>432</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1_3</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;font size="+1"&gt;Welcome to Project Wizard!&lt;/font&gt;
+&lt;br/&gt;
+&lt;p&gt;
+The wizard will help you to setup a new translation
+project for KBabel.
+&lt;/p&gt;
+&lt;p&gt;
+First of all, you need to choose the project name
+and the file, where the configuration should be stored.
+&lt;/p&gt;
+&lt;p&gt;
+You should also choose a language to translate into
+and also a type of the translation project.
+&lt;/p&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KURLRequester" row="1" column="1">
+ <property name="name">
+ <cstring>_projectFile</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;
+&lt;p&gt;&lt;b&gt;Configuration File Name&lt;/b&gt;&lt;br/&gt;
+The name of a file to store the configuration of the
+project.&lt;/p&gt;
+&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Language:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>_projectLanguage</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;
+&lt;p&gt;
+&lt;b&gt;Language&lt;/b&gt;&lt;br/&gt;
+The destination language of the project, i.e., the language
+to translate into. It should follow the ISO 631 language naming
+standard.&lt;/p&gt;
+&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Project &amp;name:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>_projectName</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;&lt;p&gt;&lt;b&gt;Project name&lt;/b&gt;&lt;br/&gt;
+The project name is an identification of a project for
+you. It is shown in the project configuration dialog
+as well as in the title of windows opened for the project.
+&lt;br/&gt;
+&lt;br/&gt;
+&lt;b&gt;Note:&lt;/b&gt; The project name cannot be later changed.&lt;
+&lt;/p&gt;&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="2" column="1">
+ <property name="name">
+ <cstring>_projectLanguage</cstring>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;
+&lt;p&gt;
+&lt;b&gt;Language&lt;/b&gt;&lt;br/&gt;
+The destination language of the project, i.e., the language
+to translate into. It should follow the ISO 631 language naming
+standard.&lt;/p&gt;
+&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="3" column="0">
+ <property name="name">
+ <cstring>textLabel2_2</cstring>
+ </property>
+ <property name="text">
+ <string>Project &amp;type:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>_projectType</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;
+&lt;p&gt;
+&lt;b&gt;Project Type&lt;/b&gt;
+The project type allows to tune the settings for the
+particular type of the well-known translation projects.
+For example, it sets up the validation tools,
+an accelerator marker and formatting of the header.
+&lt;/p&gt;
+&lt;p&gt;Currently known types:
+&lt;ul&gt;
+&lt;li&gt;&lt;b&gt;KDE&lt;/b&gt;: K Desktop Environment Internalization project&lt;/li&gt;
+&lt;li&gt;&lt;b&gt;GNOME&lt;/b&gt;: GNOME Translation project&lt;/li&gt;
+&lt;li&gt;&lt;b&gt;Translation Robot&lt;/b&gt;: Translation Project Robot&lt;/li&gt;
+&lt;li&gt;&lt;b&gt;Other&lt;/b&gt;: Other kind of project. No tuning will be
+done&lt;/li&gt;
+&lt;/ul&gt;
+&lt;/p&gt;
+&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>_projectName</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;&lt;p&gt;&lt;b&gt;Project name&lt;/b&gt;&lt;br/&gt;
+The project name is an identification of a project for
+you. It is shown in the project configuration dialog
+as well as in the title of windows opened for the project.
+&lt;br/&gt;
+&lt;br/&gt;
+&lt;b&gt;Note:&lt;/b&gt; The project name cannot be later changed.&lt;
+&lt;/p&gt;&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Configuration &amp;file name:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>_projectFile</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;
+&lt;p&gt;&lt;b&gt;Configuration File Name&lt;/b&gt;&lt;br/&gt;
+The name of a file to store the configuration of the
+project.&lt;/p&gt;
+&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="3" column="1">
+ <item>
+ <property name="text">
+ <string>KDE</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>GNOME</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Translation Project Robot</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Other</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>_projectType</cstring>
+ </property>
+ <property name="editable">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;
+&lt;p&gt;
+&lt;b&gt;Project Type&lt;/b&gt;
+The project type allows to tune the settings for the
+particular type of the well-known translation projects.
+For example, it sets up the validation tools,
+an accelerator marker and formatting of the header.
+&lt;/p&gt;
+&lt;p&gt;Currently known types:
+&lt;ul&gt;
+&lt;li&gt;&lt;b&gt;KDE&lt;/b&gt;: K Desktop Environment Internalization project&lt;/li&gt;
+&lt;li&gt;&lt;b&gt;GNOME&lt;/b&gt;: GNOME Translation project&lt;/li&gt;
+&lt;li&gt;&lt;b&gt;Translation Robot&lt;/b&gt;: Translation Project Robot&lt;/li&gt;
+&lt;li&gt;&lt;b&gt;Other&lt;/b&gt;: Other kind of project. No tuning will be
+done&lt;/li&gt;
+&lt;/ul&gt;
+&lt;/p&gt;
+&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </vbox>
+</widget>
+<tabstops>
+ <tabstop>_projectName</tabstop>
+ <tabstop>_projectFile</tabstop>
+ <tabstop>_projectLanguage</tabstop>
+ <tabstop>_projectType</tabstop>
+</tabstops>
+<includes>
+ <include location="local" impldecl="in implementation">projectwizardwidget.ui.h</include>
+</includes>
+<layoutdefaults spacing="6" margin="11"/>
+<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
+<includehints>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klineedit.h</includehint>
+</includehints>
+</UI>
diff --git a/kbabel/commonui/projectwizardwidget.ui.h b/kbabel/commonui/projectwizardwidget.ui.h
new file mode 100644
index 00000000..6f16e162
--- /dev/null
+++ b/kbabel/commonui/projectwizardwidget.ui.h
@@ -0,0 +1,40 @@
+/****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2004-2005 Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+#include <kdialog.h>
diff --git a/kbabel/commonui/projectwizardwidget2.ui b/kbabel/commonui/projectwizardwidget2.ui
new file mode 100644
index 00000000..05d21a20
--- /dev/null
+++ b/kbabel/commonui/projectwizardwidget2.ui
@@ -0,0 +1,157 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>ProjectStep2</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>ProjectStep2</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>529</width>
+ <height>365</height>
+ </rect>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;&lt;p&gt;&lt;b&gt;Translation Files&lt;/b&gt;&lt;/p&gt;
+&lt;p&gt;Type in the folders which contain all your PO and POT files.
+The files and the folders in these folders will then be merged into one tree.&lt;/p&gt;&lt;/qt&gt;</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;font size="+1"&gt;The Translation Files&lt;/font&gt;
+&lt;br/&gt;&lt;br/&gt;
+If the project contains more than one file to translate, it
+better to organize the files.
+
+KBabel distinguishes two kind of the translation files:
+
+&lt;ul&gt;
+&lt;li&gt;&lt;b&gt;Templates&lt;/b&gt;: the files to be translated&lt;/li&gt;
+&lt;li&gt;&lt;b&gt;Translated files&lt;/b&gt;: the files already translated (at least
+partially)&lt;/li&gt;
+&lt;/ul&gt;
+
+Choose the folders to store the files. If you
+leave the entries empty, the Catalog Manager
+will not work.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Base folder of PO files:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>_poDirEdit</cstring>
+ </property>
+ </widget>
+ <widget class="KURLRequester">
+ <property name="name">
+ <cstring>_poDirEdit</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Ba&amp;se folder of POT files:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>_potDirEdit</cstring>
+ </property>
+ </widget>
+ <widget class="KURLRequester">
+ <property name="name">
+ <cstring>_potDirEdit</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <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>31</width>
+ <height>100</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kbabel/commonui/roughtransdlg.cpp b/kbabel/commonui/roughtransdlg.cpp
new file mode 100644
index 00000000..de321044
--- /dev/null
+++ b/kbabel/commonui/roughtransdlg.cpp
@@ -0,0 +1,762 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2001 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2002-2003 by StanislavVsinovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include "catalog.h"
+#include "catalogsettings.h"
+#include "editcmd.h"
+#include "dictchooser.h"
+#include "kbabeldictbox.h"
+#include "regexpextractor.h"
+#include "roughtransdlg.h"
+
+#include <qmemarray.h>
+#include <qcheckbox.h>
+#include <qhbuttongroup.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qradiobutton.h>
+#include <qtimer.h>
+#include <qvgroupbox.h>
+#include <qvbox.h>
+#include <qwhatsthis.h>
+
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kprogress.h>
+
+
+#include <kdebug.h>
+
+using namespace KBabel;
+
+RoughTransDlg::RoughTransDlg(KBabelDictBox *dict, Catalog *cat
+ , QWidget *parent,const char *name)
+ : KDialogBase(parent,name,true
+ ,i18n("Caption of dialog","Rough Translation")
+ , User1|User2|User3|Close)
+ ,catalog(cat)
+ ,active(false)
+ ,stop(false)
+ ,cancel(false)
+ ,dictBox(dict)
+ ,exactTransCounter(0)
+ ,partTransCounter(0)
+ ,totalTried(0)
+{
+ setButtonBoxOrientation(Vertical);
+ setButtonText(User1,i18n("&Start"));
+ setButtonText(User2,i18n("S&top"));
+ setButtonText(User3,i18n("C&ancel"));
+
+ enableButton(User2,false);
+ enableButton(User3,false);
+
+ QWidget *mw = new QWidget(this);
+ setMainWidget(mw);
+
+ QVBoxLayout *mainLayout = new QVBoxLayout(mw);
+
+ configWidget = new QVBox(mw);
+ mainLayout->addWidget(configWidget);
+
+ QVGroupBox *box = new QVGroupBox(i18n("What to Translate"),configWidget);
+
+ QHButtonGroup *bBox = new QHButtonGroup(box);
+ bBox->setMargin(0);
+ bBox->setFrameStyle(QFrame::NoFrame);
+ whatBox = bBox;
+ untransButton = new QCheckBox(i18n("U&ntranslated entries"),bBox);
+ fuzzyButton = new QCheckBox(i18n("&Fuzzy entries"),bBox);
+ transButton = new QCheckBox(i18n("T&ranslated entries"),bBox);
+
+ connect(bBox,SIGNAL(clicked(int)),this,SLOT(msgButtonClicked(int)));
+
+ QWhatsThis::add(bBox,i18n("<qt><p><b>What entries to translate</b></p>"
+ "<p>Choose here, for which entries of the file KBabel "
+ "tries to find a translation. Changed entries are always "
+ "marked as fuzzy, no matter which option you choose.</p></qt>"));
+
+ box = new QVGroupBox(i18n("How to Translate"),configWidget);
+ bBox = new QHButtonGroup(box);
+ bBox->setFrameStyle(QFrame::NoFrame);
+ bBox->setMargin(0);
+
+ searchMatchButton = new QCheckBox(i18n("&Use dictionary settings")
+ ,bBox);
+
+ fuzzyMatchButton = new QCheckBox(i18n("Fu&zzy translation (slow)")
+ ,bBox);
+ singleWordButton = new QCheckBox(i18n("&Single word translation")
+ ,bBox);
+
+ QWhatsThis::add(bBox,i18n("<qt><p><b>How messages get translated</b></p>"
+ "<p>Here you can define if a message can only get translated "
+ "completely, if similar messages are acceptable or if KBabel "
+ "is supposed to try translating "
+ "the single words of a message if no translation of the "
+ "complete message or similar message was found.</p></qt>"));
+
+
+ box = new QVGroupBox(i18n("Options"),configWidget);
+
+ markFuzzyButton = new QCheckBox(i18n("&Mark changed entries as fuzzy"),box);
+ markFuzzyButton->setChecked(true);
+ QWhatsThis::add(markFuzzyButton,
+ i18n("<qt><p><b>Mark changed entries as fuzzy</b></p>"
+ "<p>When a translation for a message is found, the entry "
+ "will be marked <b>fuzzy</b> by default. This is because the "
+ "translation is just guessed by KBabel and you should always "
+ "check the results carefully. Deactivate this option only if "
+ "you know what you are doing.</p></qt>"));
+
+
+ connect(markFuzzyButton, SIGNAL(toggled(bool))
+ , this, SLOT(fuzzyButtonToggled(bool)));
+
+ kdeButton = new QCheckBox(i18n("Initialize &KDE-specific entries"),box);
+ kdeButton->setChecked(true);
+ QWhatsThis::add(kdeButton,
+ i18n("<qt><p><b>Initialize KDE-specific entries</b></p>"
+ "<p>Initialize \"Comment=\" and \"Name=\" entries "
+ "if a translation is not found. Also, \"NAME OF TRANSLATORS\" "
+ "and \"EMAIL OF TRANSLATORS\" is filled with identity settings.</p></qt>"));
+
+ QVGroupBox *dBox = new QVGroupBox(i18n("Dictionaries"),configWidget);
+ configWidget->setStretchFactor(dBox,1);
+
+ QPtrList<ModuleInfo> moduleList = dict->moduleInfos();
+
+ KConfig *config = KGlobal::config();
+ KConfigGroupSaver gs(config,"RoughTranslation");
+ QStringList selectedList=config->readListEntry("Selected");
+ if(selectedList.isEmpty())
+ {
+ int a = dict->activeModule();
+ ModuleInfo *mi = moduleList.at(a);
+ if(mi)
+ {
+ selectedList.append(mi->id);
+ }
+ }
+ dictChooser = new DictChooser(dict,selectedList,dBox,"dictChooser");
+
+ QWhatsThis::add(dictChooser,i18n("<qt><p><b>Dictionaries</b></p>"
+ "<p>Choose here, which dictionaries have to be used for "
+ "finding a translation. If you select more than one "
+ "dictionary, they are used in the same order as they "
+ "are displayed in the list.</p>"
+ "<p>The <b>Configure</b> button allows you to temporarily "
+ "configure selected dictionary. The original settings "
+ "will be restored after closing the dialog.</p></qt>"));
+
+ QLabel* label = new QLabel( i18n("Messages:"), mw );
+ progressbar = new KProgress(mw,"progressbar");
+ progressbar->setTextEnabled(true);
+ progressbar->setFormat("%v/%m (%p%)");
+ QHBoxLayout* pblayout= new QHBoxLayout(mainLayout);
+ pblayout->add(label);
+ pblayout->add(progressbar);
+
+ transButton->setChecked(config->readBoolEntry("Translated",false));
+ untransButton->setChecked(config->readBoolEntry("Untranslated",true));
+ fuzzyButton->setChecked(config->readBoolEntry("Fuzzies",false));
+
+ bool flag = config->readBoolEntry("fuzzyMatch",true);
+ fuzzyMatchButton->setChecked(flag);
+
+ flag = config->readBoolEntry("searchMatch",true);
+ searchMatchButton->setChecked(flag);
+
+ flag = config->readBoolEntry("singleWord",true);
+ singleWordButton->setChecked(flag);
+
+ flag = config->readBoolEntry("kdeSpecific",true);
+ kdeButton->setChecked(flag);
+
+ msgButtonClicked(0);
+}
+
+RoughTransDlg::~RoughTransDlg()
+{
+ KConfig *config=KGlobal::config();
+ KConfigGroupSaver gs(config,"RoughTranslation");
+ config->writeEntry("Selected",dictChooser->selectedDicts());
+
+ bool flag=transButton->isChecked();
+ config->writeEntry("Translated",flag);
+ flag=untransButton->isChecked();
+ config->writeEntry("Untranslated",flag);
+ flag=fuzzyButton->isChecked();
+ config->writeEntry("Fuzzies",flag);
+ flag=singleWordButton->isChecked();
+ config->writeEntry("singleWord",flag);
+ flag=fuzzyMatchButton->isChecked();
+ config->writeEntry("fuzzyMatch",flag);
+ flag=searchMatchButton->isChecked();
+ config->writeEntry("searchMatch",flag);
+ flag=kdeButton->isChecked();
+ config->writeEntry("kdeSpecific",flag);
+
+}
+
+void RoughTransDlg::slotUser1()
+{
+ configWidget->setEnabled(false);
+ enableButton(User1,false);
+ enableButton(Close,false);
+ enableButton(User2,true);
+ enableButton(User3,true);
+
+ active=true;
+ stop=false;
+ cancel=false;
+
+ exactTransCounter=0;
+ partTransCounter=0;
+ totalTried=0;
+
+ QTimer::singleShot(0,this, SLOT(translate()));
+}
+
+void RoughTransDlg::translate()
+{
+ bool markFuzzy = markFuzzyButton->isChecked();
+ bool translated = transButton->isChecked();
+ bool untranslated = untransButton->isChecked();
+ bool fuzzies = fuzzyButton->isChecked();
+ bool kdeSpecific=kdeButton->isChecked();
+
+ int total=catalog->numberOfEntries();
+ progressbar->setTotalSteps(total);
+
+ QStringList dictList = dictChooser->selectedDicts();
+
+ catalog->applyBeginCommand(0,Msgstr,0);
+
+ bool singleWords=singleWordButton->isChecked();
+ bool fuzzyMatch=fuzzyMatchButton->isChecked();
+ bool searchMatch=searchMatchButton->isChecked();
+ QRegExp contextReg=catalog->miscSettings().contextInfo;
+ QChar accelMarker=catalog->miscSettings().accelMarker;
+ QRegExp endPunctReg("[\\.?!: ]+$");
+
+
+ for(int i = 0; i < total; i++)
+ {
+ progressbar->setProgress(i+1);
+ kapp->processEvents(100);
+
+ if(stop || cancel) break;
+
+ // FIXME: should care about plural forms
+ QString msg=catalog->msgid(i,true).first();
+ QString translation;
+
+ // this is KDE specific:
+ if( kdeSpecific )
+ {
+ if( catalog->pluralForm(i) == NoPluralForm )
+ {
+ QString origTrans = catalog->msgstr(i).first();
+ if(msg.find("_: NAME OF TRANSLATORS\\n")==0)
+ {
+ QString authorName;
+ if( !catalog->identitySettings().authorLocalizedName.isEmpty() )
+ authorName = catalog->identitySettings().authorLocalizedName;
+ else // fallback to non-localized name
+ if( !catalog->identitySettings().authorName.isEmpty() )
+ authorName = catalog->identitySettings().authorName;
+ else continue; // there is no name to be inserted
+
+ if( !QStringList::split(',', origTrans).contains(authorName) )
+ {
+ if(origTrans.isEmpty() ) translation=authorName;
+ else translation+=origTrans+","+authorName;
+ }
+ }
+ else if(msg.find("_: EMAIL OF TRANSLATORS\\n")==0)
+ {
+ // skip, if email is not specified in settings
+ if( catalog->identitySettings().authorEmail.isEmpty() ) continue;
+
+ if( !QStringList::split(',', origTrans).contains(catalog->identitySettings().authorEmail) )
+ {
+ if(origTrans.isEmpty() ) translation=catalog->identitySettings().authorEmail;
+ else translation=origTrans+","+catalog->identitySettings().authorEmail;
+ }
+ }
+ else if (msg.find("ROLES_OF_TRANSLATORS") == 0)
+ {
+ QString temp = "<othercredit role=\\\"translator\\\">\n<firstname></firstname>"
+ "<surname></surname>\n<affiliation><address><email>" +
+ catalog->identitySettings( ).authorEmail+"</email></address>\n"
+ "</affiliation><contrib></contrib></othercredit>";
+ if (origTrans.isEmpty( ))
+ translation = temp;
+ else if (origTrans.find(catalog->identitySettings( ).authorEmail) < 0)
+ translation = origTrans + "\n" + temp;
+ }
+ else if (msg.find("CREDIT_FOR_TRANSLATORS") == 0)
+ {
+ QString authorName;
+ if (!catalog->identitySettings( ).authorLocalizedName.isEmpty( ))
+ authorName = catalog->identitySettings( ).authorLocalizedName;
+ else if (!catalog->identitySettings( ).authorName.isEmpty( ))
+ authorName = catalog->identitySettings( ).authorName;
+ QString temp = "<para>" + authorName + "\n" + "<email>" +
+ catalog->identitySettings( ).authorEmail + "</email></para>";
+ if (origTrans.isEmpty( ))
+ translation = temp;
+ else if (origTrans.find(authorName) < 0 &&
+ origTrans.find(catalog->identitySettings( ).authorEmail) < 0)
+ translation = origTrans + "\n" + temp;
+ }
+ }
+ }
+ else // not kdeSpecific
+ {
+ // skip KDE specific texts
+ if( msg.find("_: EMAIL OF TRANSLATORS\\n")==0 || msg.find("_: NAME OF TRANSLATORS\\n")==0 ||
+ msg.find("ROLES_OF_TRANSLATORS")==0 || msg.find("CREDIT_FOR_TRANSLATORS")==0)
+ continue;
+ }
+
+ if( translation.isEmpty() ) // KDE-specific translation didn't work
+ {
+ if( !untranslated && catalog->isUntranslated(i) ) continue;
+ if( !translated && !catalog->isUntranslated(i) && !catalog->isFuzzy(i) ) continue;
+ if( !fuzzies && catalog->isFuzzy(i) ) continue;
+ }
+
+ totalTried++;
+
+ if(msg.contains(contextReg))
+ {
+ msg.replace(contextReg,"");
+ }
+
+ // try exact translation
+ QStringList::Iterator dit = dictList.begin();
+ while(translation.isEmpty() && dit != dictList.end())
+ {
+ dictBox->setActiveModule(*dit);
+ translation = dictBox->translate(msg);
+
+ ++dit;
+ }
+
+ if(!translation.isEmpty())
+ {
+ exactTransCounter++;
+ }
+
+ // try search settings translation
+ else if (searchMatch) {
+ QString tr;
+ int score, best_score = 0;
+ dit = dictList.begin();
+ while(dit != dictList.end())
+ {
+ dictBox->setActiveModule(*dit);
+ tr = dictBox->searchTranslation(msg,score);
+ kdDebug() << "Found: " << tr << ", score " << score << endl;
+
+ if (score > best_score) {
+ kdDebug() << "Best score" << endl;
+ translation = tr;
+ best_score = score;
+ }
+
+ ++dit;
+ }
+
+ if(!translation.isEmpty())
+ {
+ partTransCounter++;
+ }
+ }
+
+ // try fuzzy translation
+ else if (fuzzyMatch) {
+ QString tr;
+ int score, best_score = 0;
+ dit = dictList.begin();
+ while(dit != dictList.end())
+ {
+ dictBox->setActiveModule(*dit);
+ tr = dictBox->fuzzyTranslation(msg,score);
+
+ if (score > best_score) {
+ translation = tr;
+ best_score = score;
+ }
+
+ ++dit;
+ }
+
+ if(!translation.isEmpty())
+ {
+ partTransCounter++;
+ }
+ }
+
+ kdDebug() << "Best translation so far: " << translation << endl;
+
+ // try single word translation
+ if(translation.isEmpty() && singleWords)
+ {
+ QStringList wordList;
+ QChar accel;
+ QString endingPunctuation;
+ int pos = msg.findRev(endPunctReg);
+ if(pos >= 0)
+ {
+ endingPunctuation = msg.right(msg.length()-pos);
+ }
+
+ msg=msg.simplifyWhiteSpace();
+ msg=msg.stripWhiteSpace();
+
+
+ RegExpExtractor te(catalog->tagSettings().tagExpressions);
+ te.setString(msg);
+ msg=te.matchesReplaced(" KBABELTAG ");
+
+ QString word;
+ int length = msg.length();
+ QRegExp digitReg("^[0-9]*$");
+ for(int index=0; index < length; index++)
+ {
+ QChar c=msg[index];
+
+ if(c==accelMarker)
+ {
+ index++;
+ if(index < length)
+ {
+ if(msg[index].isLetterOrNumber())
+ {
+ word+=msg[index];
+ accel=msg[index];
+ }
+ else if(!word.isEmpty() )
+ {
+ if(!word.contains(digitReg))
+ wordList.append(word);
+
+ word=QString::null;
+ }
+ }
+ else if(!word.isEmpty())
+ {
+ if(!word.contains(digitReg))
+ wordList.append(word);
+
+ word=QString::null;
+ }
+
+ }
+ else if(c.isLetterOrNumber())
+ {
+ word+=c;
+ }
+ else if(c == '\\')
+ {
+ if(index < length-2)
+ {
+ if(msg[index+1]=='n' && msg[index+2].isSpace())
+ {
+ if(!word.isEmpty() && !word.contains(digitReg))
+ wordList.append(word);
+
+ word=QString::null;
+
+ wordList.append("\\n\n");
+ index+=2;
+ }
+ else if(!word.isEmpty() )
+ {
+ if(!word.contains(digitReg))
+ wordList.append(word);
+
+ word=QString::null;
+ }
+ }
+ else if(!word.isEmpty())
+ {
+ if(!word.contains(digitReg))
+ wordList.append(word);
+
+ word=QString::null;
+ }
+ }
+ else if(!word.isEmpty())
+ {
+ if(!word.contains(digitReg)) {
+ wordList.append(word);
+ }
+
+ word=QString::null;
+ }
+ }
+
+ // handle the last word as well
+ if( !word.isEmpty() ) wordList.append(word);
+
+ dit = dictList.begin();
+ int wordCounter=0;
+ while(wordCounter==0 && dit != dictList.end())
+ {
+ dictBox->setActiveModule(*dit);
+
+ for(QStringList::Iterator it=wordList.begin();
+ it!=wordList.end(); ++it)
+ {
+ if( (*it)=="\\n\n" )
+ {
+ translation+="\\n\n";
+ }
+ else if( (*it)=="KBABELTAG" )
+ {
+ translation+=te.nextMatch();
+ }
+ else
+ {
+ QString trans = dictBox->translate(*it);
+
+ if(!trans.isEmpty())
+ {
+ wordCounter++;
+ if(!translation.isEmpty())
+ {
+ translation += ' ';
+ }
+ translation += trans;
+ }
+ }
+ }
+
+ if(wordCounter==0)
+ translation=QString::null;
+
+ ++dit;
+ }
+
+ if(!translation.isEmpty())
+ {
+ partTransCounter++;
+ // try to set the correct keyboard accelerator
+ if(!accel.isNull())
+ {
+ int index = translation.find(accel,0,false);
+ if(index >= 0)
+ {
+ translation.insert(index,accelMarker);
+ }
+ }
+
+ translation+=endingPunctuation;
+ }
+ }
+
+ // this is KDE specific:
+ if(kdeSpecific && translation.isEmpty())
+ {
+ if( msg.startsWith("Name=") ) {
+ translation="Name=";
+ partTransCounter++;
+ }
+ if( msg.startsWith("Comment=") ) {
+ translation="Comment=";
+ partTransCounter++;
+ }
+ }
+
+ if(!translation.isEmpty())
+ {
+ if(!catalog->isUntranslated(i))
+ {
+ QStringList msgs = catalog->msgstr(i);
+ uint counter = 0;
+ for( QStringList::Iterator it = msgs.begin() ; it != msgs.end() ; ++it)
+ {
+ DelTextCmd* delCmd = new DelTextCmd(0
+ ,(*it),counter++);
+ delCmd->setPart(Msgstr);
+ delCmd->setIndex(i);
+ catalog->applyEditCommand(delCmd,0);
+ }
+ }
+
+ for( int count=0; count < catalog->numberOfPluralForms(i) ; count++ )
+ {
+ InsTextCmd* insCmd = new InsTextCmd(0,translation,count);
+ insCmd->setPart(Msgstr);
+ insCmd->setIndex(i);
+ catalog->applyEditCommand(insCmd,0);
+ }
+
+ if(markFuzzy)
+ {
+ catalog->setFuzzy(i,true);
+ }
+ }
+ }
+
+ catalog->applyEndCommand(0,Msgstr,0);
+
+ if(stop || cancel)
+ {
+ if(cancel)
+ {
+ catalog->undo();
+ }
+ else
+ {
+ msgButtonClicked(0);
+ }
+ progressbar->setProgress(0);
+ configWidget->setEnabled(true);
+ active = false;
+
+ enableButton(User1,true);
+ enableButton(Close,true);
+ enableButton(User2,false);
+ enableButton(User3,false);
+
+ return;
+ }
+
+ showStatistics();
+}
+
+void RoughTransDlg::showStatistics()
+{
+ int nothing=totalTried-partTransCounter-exactTransCounter;
+ KLocale *locale = KGlobal::locale();
+ QString statMsg = i18n("Result of the translation:\n"
+ "Edited entries: %1\n"
+ "Exact translations: %2 (%3%)\n"
+ "Approximate translations: %4 (%5%)\n"
+ "Nothing found: %6 (%7%)")
+ .arg( locale->formatNumber(totalTried,0) )
+ .arg( locale->formatNumber(exactTransCounter,0) )
+ .arg( locale->formatNumber( ((double)(10000*exactTransCounter/QMAX(totalTried,1)))/100) )
+ .arg( locale->formatNumber(partTransCounter,0) )
+ .arg( locale->formatNumber(((double)(10000*partTransCounter/QMAX(totalTried,1)))/100) )
+ .arg( locale->formatNumber(nothing,0) )
+ .arg( locale->formatNumber(((double)(10000*nothing/QMAX(totalTried,1)))/100) );
+
+ KMessageBox::information(this, statMsg
+ , i18n("Rough Translation Statistics"));
+
+ dictChooser->restoreConfig();
+ accept();
+}
+
+void RoughTransDlg::slotClose()
+{
+ if(active)
+ {
+ cancel = true;
+ return;
+ }
+ else
+ {
+ dictChooser->restoreConfig();
+ accept();
+ }
+}
+
+void RoughTransDlg::slotUser2()
+{
+ stop=true;
+}
+
+void RoughTransDlg::slotUser3()
+{
+ cancel=true;
+}
+
+void RoughTransDlg::msgButtonClicked(int id)
+{
+ if(!transButton->isChecked() && !untransButton->isChecked()
+ && !fuzzyButton->isChecked())
+ {
+ QButton *button = whatBox->find(id);
+ if(button == transButton)
+ {
+ transButton->setChecked(true);
+ }
+ else if(button == untransButton)
+ {
+ untransButton->setChecked(true);
+ }
+ else if(button == fuzzyButton)
+ {
+ fuzzyButton->setChecked(true);
+ }
+ }
+
+ progressbar->setTotalSteps(catalog->numberOfEntries());
+
+ enableButton(User1,catalog->numberOfEntries());
+}
+
+void RoughTransDlg::fuzzyButtonToggled(bool on)
+{
+ if(!on)
+ {
+ QString msg=i18n("<qt><p>"
+ "When a translation for a message is found, the entry "
+ "will be marked <b>fuzzy</b> by default. This is because the "
+ "translation is just guessed by KBabel and you should always "
+ "check the results carefully. Deactivate this option only if "
+ "you know what you are doing.</p></qt>");
+
+ KMessageBox::information(this, msg, QString::null,"MarkFuzzyWarningInRoughTransDlg");
+ }
+}
+
+void RoughTransDlg::statistics(int &total, int& exact, int& part) const
+{
+ total = totalTried;
+ exact = exactTransCounter;
+ part = partTransCounter;
+}
+
+#include "roughtransdlg.moc"
diff --git a/kbabel/commonui/roughtransdlg.h b/kbabel/commonui/roughtransdlg.h
new file mode 100644
index 00000000..e51378a5
--- /dev/null
+++ b/kbabel/commonui/roughtransdlg.h
@@ -0,0 +1,110 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2001 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef ROUGHTRANSDLG_H
+#define ROUGHTRANSDLG_H
+
+#include <kdialogbase.h>
+
+
+class KBabelDictBox;
+class DictChooser;
+
+namespace KBabel
+{
+ class Catalog;
+}
+
+class KProgress;
+class QCheckBox;
+class QHButtonGroup;
+class QRadioButton;
+class QVBox;
+
+class KDE_EXPORT RoughTransDlg : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ RoughTransDlg(KBabelDictBox* dictBox, KBabel::Catalog* catalog, QWidget *parent
+ , const char *name=0);
+ ~RoughTransDlg();
+
+ void statistics(int &total, int& exactTranslated
+ , int& partlyTranslated) const;
+
+protected slots:
+ void slotUser1();
+ void slotUser2();
+ void slotUser3();
+
+ void slotClose();
+
+ void fuzzyButtonToggled(bool);
+
+ virtual void msgButtonClicked(int);
+ virtual void translate();
+ virtual void showStatistics();
+
+protected:
+ KBabel::Catalog *catalog;
+
+ bool active;
+ bool stop;
+ bool cancel;
+
+ KProgress *progressbar;
+private:
+ KBabelDictBox *dictBox;
+
+ DictChooser *dictChooser;
+ QVBox *configWidget;
+
+
+ QHButtonGroup *whatBox;
+ QCheckBox *transButton;
+ QCheckBox *untransButton;
+ QCheckBox *fuzzyButton;
+
+ QCheckBox *singleWordButton;
+ QCheckBox *fuzzyMatchButton;
+ QCheckBox *searchMatchButton;
+
+ QCheckBox *markFuzzyButton;
+ QCheckBox *kdeButton;
+
+ int exactTransCounter;
+ int partTransCounter;
+ int totalTried;
+};
+
+#endif // ROUGHTRANSDLG_H
diff --git a/kbabel/commonui/toolaction.cpp b/kbabel/commonui/toolaction.cpp
new file mode 100644
index 00000000..14589996
--- /dev/null
+++ b/kbabel/commonui/toolaction.cpp
@@ -0,0 +1,108 @@
+/* This file is part of KBabel
+ Copyright (C) 2002 Stanislav Visnovsky <visnovsky@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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#include "toolaction.h"
+
+#include <kdebug.h>
+
+ToolAction::ToolAction( const QString & text, const KShortcut& cut, const KDataToolInfo & info, const QString & command,
+ QObject * parent, const char * name )
+ : KAction( text, info.iconName() == "unknown" ? QString::null : info.iconName(), cut, parent, name ),
+ m_command( command ),
+ m_info( info )
+{
+}
+
+void ToolAction::slotActivated()
+{
+ emit toolActivated( m_info, m_command );
+}
+
+QPtrList<KAction> ToolAction::dataToolActionList( const QValueList<KDataToolInfo> & tools, const QObject *receiver, const char* slot, const QStringList& command, bool excludeCommand, KActionCollection* parent, const QString& namePrefix )
+{
+ QPtrList<KAction> actionList;
+ if ( tools.isEmpty() )
+ return actionList;
+
+ QValueList<KDataToolInfo>::ConstIterator entry = tools.begin();
+ for( ; entry != tools.end(); ++entry )
+ {
+ QStringList userCommands = (*entry).userCommands();
+ QStringList commands = (*entry).commands();
+ QStringList shortcuts = (*entry).service()->property("Shortcuts").toStringList();
+ Q_ASSERT(!commands.isEmpty());
+ if ( commands.count() != userCommands.count() )
+ kdWarning() << "KDataTool desktop file error (" << (*entry).service()
+ << "). " << commands.count() << " commands and "
+ << userCommands.count() << " descriptions." << endl;
+
+ QStringList::ConstIterator uit = userCommands.begin();
+ QStringList::ConstIterator cit = commands.begin();
+ QStringList::ConstIterator sit = shortcuts.begin();
+ for (; uit != userCommands.end() && cit != commands.end(); ++uit, ++cit)
+ {
+ if( !excludeCommand == command.contains(*cit) )
+ {
+ QString sc=*sit;
+
+ ToolAction * action = new ToolAction( *uit, (sc.isEmpty()?QString::null:sc), *entry, *cit
+ , parent
+ , QString(namePrefix+(*entry).service()->library()+"_"+(*cit)).utf8() );
+ connect( action, SIGNAL( toolActivated( const KDataToolInfo &, const QString & ) ),
+ receiver, slot );
+
+ actionList.append( action );
+ }
+ if( sit != shortcuts.end() ) sit++;
+ }
+ }
+
+ return actionList;
+}
+
+QValueList<KDataToolInfo> ToolAction::validationTools()
+{
+ QValueList<KDataToolInfo> result;
+
+ QValueList<KDataToolInfo> tools = KDataToolInfo::query("CatalogItem", "application/x-kbabel-catalogitem", KGlobal::instance());
+
+ for( QValueList<KDataToolInfo>::ConstIterator entry = tools.begin(); entry != tools.end(); ++entry )
+ {
+ if( (*entry).commands().contains("validate") )
+ {
+ result.append( *entry );
+ }
+ }
+
+ return result;
+}
+
+#include "toolaction.moc"
diff --git a/kbabel/commonui/toolaction.h b/kbabel/commonui/toolaction.h
new file mode 100644
index 00000000..11e32c89
--- /dev/null
+++ b/kbabel/commonui/toolaction.h
@@ -0,0 +1,72 @@
+/* This file is part of KBabel
+ Copyright (C) 2002 Stanislav Visnovsky <visnovsky@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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#ifndef TOOLACTION_H
+#define TOOLACTION_H
+
+#include <qobject.h>
+#include <kaction.h>
+#include <kdatatool.h>
+
+class KShortcut;
+class KActionCollection;
+
+class KDE_EXPORT ToolAction : public KAction
+{
+ Q_OBJECT
+public:
+ ToolAction( const QString & text, const KShortcut& cut, const KDataToolInfo & info, const QString & command, QObject * parent = 0, const char * name = 0);
+
+ /**
+ * return the list of KActions created for a list of tools. @ref command
+ * allows to specify rescriction of commands, for which the list should
+ * or shouldn't be created according to the @ref excludeCommand flag.
+ */
+ static QPtrList<KAction> dataToolActionList( const QValueList<KDataToolInfo> & tools, const QObject *receiver, const char* slot, const QStringList& command, bool excludeCommand, KActionCollection* parent=0, const QString& namePrefix=QString::null );
+
+ /**
+ * returns information about all available validation tools (KDataTools with support for CatalogItem
+ * and the "validate" command.
+ */
+ static QValueList<KDataToolInfo> validationTools();
+
+signals:
+ void toolActivated( const KDataToolInfo & info, const QString & command );
+
+protected:
+ virtual void slotActivated();
+
+private:
+ QString m_command;
+ KDataToolInfo m_info;
+};
+
+#endif
diff --git a/kbabel/commonui/toolselectionwidget.cpp b/kbabel/commonui/toolselectionwidget.cpp
new file mode 100644
index 00000000..8657657d
--- /dev/null
+++ b/kbabel/commonui/toolselectionwidget.cpp
@@ -0,0 +1,105 @@
+/* This file is part of KBabel
+ Copyright (C) 2002 Stanislav Visnovsky <visnovsky@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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#include "toolselectionwidget.h"
+
+#include <kdatatool.h>
+#include <kdebug.h>
+
+#include <qlistbox.h>
+
+ToolSelectionWidget::ToolSelectionWidget( QWidget * parent, const char * name )
+ : KActionSelector( parent, name )
+{
+}
+
+void ToolSelectionWidget::loadTools( const QStringList &commands,
+ const QValueList<KDataToolInfo>& tools)
+{
+ if ( tools.isEmpty() ) return;
+
+ _allTools = tools;
+
+ QValueList<KDataToolInfo>::ConstIterator entry = tools.begin();
+ for( ; entry != tools.end(); ++entry )
+ {
+ QStringList userCommands = (*entry).userCommands();
+ QStringList toolCommands = (*entry).commands();
+ Q_ASSERT(!toolCommands.isEmpty());
+ if ( toolCommands.count() != userCommands.count() )
+ kdWarning() << "KDataTool desktop file error (" << (*entry).service()
+ << "). " << toolCommands.count() << " commands and "
+ << userCommands.count() << " descriptions." << endl;
+
+ QStringList::ConstIterator uit = userCommands.begin();
+ QStringList::ConstIterator cit = toolCommands.begin();
+ for (; uit != userCommands.end() && cit != toolCommands.end(); ++uit, ++cit )
+ {
+ if( commands.contains(*cit) )
+ {
+ availableListBox()->insertItem( *uit );
+ }
+ }
+ }
+}
+
+void ToolSelectionWidget::setSelectedTools( const QStringList& tools )
+{
+ availableListBox()->clear();
+ selectedListBox()->clear();
+ QValueList<KDataToolInfo>::ConstIterator entry = _allTools.begin();
+ for( ; entry != _allTools.end(); ++entry )
+ {
+ QString uic=*(*entry).userCommands().at((*entry).commands().findIndex("validate"));
+ if( tools.contains((*entry).service()->library()) )
+ selectedListBox()->insertItem( uic );
+ else
+ availableListBox()->insertItem( uic );
+ }
+}
+
+QStringList ToolSelectionWidget::selectedTools()
+{
+ QStringList usedNames;
+ for( uint i=0; i<selectedListBox()->count() ; i++ )
+ usedNames += selectedListBox()->text(i);
+
+ QStringList result;
+ QValueList<KDataToolInfo>::ConstIterator entry = _allTools.begin();
+ for( ; entry != _allTools.end(); ++entry )
+ {
+ if( usedNames.contains(*((*entry).userCommands().at((*entry).commands().findIndex("validate")))) )
+ result += (*entry).service()->library();
+ }
+ return result;
+}
+
+#include "toolselectionwidget.moc"
diff --git a/kbabel/commonui/toolselectionwidget.h b/kbabel/commonui/toolselectionwidget.h
new file mode 100644
index 00000000..5bad520b
--- /dev/null
+++ b/kbabel/commonui/toolselectionwidget.h
@@ -0,0 +1,57 @@
+/* This file is part of KBabel
+ Copyright (C) 2002 Stanislav Visnovsky <visnovsky@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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#ifndef TOOLSELECTIONWIDGET_H
+#define TOOLSELECTIONWIDGET_H
+
+#include "kactionselector.h"
+#include <kdemacros.h>
+
+class KDataToolInfo;
+
+class KDE_EXPORT ToolSelectionWidget : public KActionSelector
+{
+ Q_OBJECT
+public:
+ ToolSelectionWidget(QWidget* parent=0, const char* name=0 );
+
+ QStringList selectedTools();
+
+ void loadTools (const QStringList& commands, const QValueList<KDataToolInfo> & tools);
+
+public slots:
+ void setSelectedTools( const QStringList& tools );
+
+private:
+ QValueList<KDataToolInfo> _allTools;
+};
+
+#endif
diff --git a/kbabel/configure.in.in b/kbabel/configure.in.in
new file mode 100644
index 00000000..88312d46
--- /dev/null
+++ b/kbabel/configure.in.in
@@ -0,0 +1,12 @@
+AM_PROG_LEX
+
+AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+AC_CHECK_HEADER(FlexLexer.h,
+ [kde_have_flex=yes],
+ [kde_have_flex=no])
+
+if test "$kde_have_flex" = "no"; then
+ DO_NOT_COMPILE="$DO_NOT_COMPILE kbabel"
+fi
+AC_LANG_RESTORE
diff --git a/kbabel/datatools/Makefile.am b/kbabel/datatools/Makefile.am
new file mode 100644
index 00000000..07600eac
--- /dev/null
+++ b/kbabel/datatools/Makefile.am
@@ -0,0 +1,39 @@
+## Makefile.am for kbabeldict
+
+# this has all of the subdirectories that make will recurse into. if
+# there are none, comment this out
+SUBDIRS = arguments accelerators context equations pluralforms xml \
+not-translated whitespace length setfuzzy punctuation regexp
+
+#pkgincludedir = $(includedir)/kbabel
+
+# this is the program that gets installed. it's name is used for all
+# of the other Makefile.am variables
+#lib_LTLIBRARIES = libkbabeltools.la
+
+# set the include path for X, qt and KDE
+INCLUDES = $(all_includes)
+
+
+# which sources should be compiled for kbabeldict
+#libkbabeltools_la_SOURCES = toolaction.cpp kactionselector.cpp toolselectionwidget.cpp
+#libkbabeltools_la_LIBADD = $(LIB_KDECORE) $(LIB_KIO)
+#libkbabeltools_la_LDFLAGS = $(all_libraries) -module -version-info 1:0:0 -no-undefined
+
+# these are the headers for your project
+#noinst_HEADERS = kactionselector.h toolselectionwidget.h
+#pkginclude_HEADERS = toolaction.h
+
+# let automoc handle all of the meta source files (moc)
+METASOURCES = AUTO
+
+# KDE_OPTIONS = nofinal
+#rcdir = $(kde_datadir)/kbabel
+#rc_DATA = kbabelui.rc
+
+#api:
+# mkdir -p API && kdoc -d API -u $$PWD/API -p -lkdeui -lkdecore -lqt -ldcop *.h
+
+#distclean-local:
+# rm -r -f API
+
diff --git a/kbabel/datatools/accelerators/Makefile.am b/kbabel/datatools/accelerators/Makefile.am
new file mode 100644
index 00000000..f204e78a
--- /dev/null
+++ b/kbabel/datatools/accelerators/Makefile.am
@@ -0,0 +1,19 @@
+
+INCLUDES = -I$(srcdir)/../../common -I../../common $(all_includes)
+kbabel_accelstool_la_LIBADD = $(LIB_KIO) ../../common/libkbabelcommon.la
+
+####### Files
+
+kde_module_LTLIBRARIES = kbabel_accelstool.la
+
+kbabel_accelstool_la_SOURCES = main.cc
+
+kbabel_accelstool_la_LDFLAGS = $(all_libraries) -avoid-version -module -no-undefined
+
+noinst_HEADERS = main.h
+
+kbabel_accelstool_la_METASOURCES = AUTO
+
+service_DATA = kbabel_accelstool.desktop
+servicedir = $(kde_servicesdir)
+
diff --git a/kbabel/datatools/accelerators/kbabel_accelstool.desktop b/kbabel/datatools/accelerators/kbabel_accelstool.desktop
new file mode 100644
index 00000000..ffe5bb15
--- /dev/null
+++ b/kbabel/datatools/accelerators/kbabel_accelstool.desktop
@@ -0,0 +1,105 @@
+[Desktop Entry]
+Name=Accelerator Validation for KBabel
+Name[bg]=ВалидноÑÑ‚ на уÑкорител - KBabel
+Name[bs]=Provjera akceleratora za KBabel
+Name[ca]=Validació dels acceleradors per a KBabel
+Name[cs]=Validace akcelerátorů pro KBabel
+Name[cy]=Dilysiad Cyflymydd i KBabel
+Name[da]=Accelerator-validering for KBabel
+Name[de]=Kurzbefehl-Überprüfung für KBabel
+Name[el]=Έλεγχος εγκυÏότητας πλήκτÏων επιτάχυνσης για το KBabel
+Name[es]=Validación de accesos rápidos para KBabel
+Name[et]=KBabeli kiirklahvide kontrollija
+Name[eu]=Bizkortzaile balidazioa KBabel-entzat
+Name[fa]=اعتبارسنجی شتاب‌ده برای KBabel
+Name[fi]=Pikavalintojen tarkistus KBabelissa
+Name[fr]=Validation des accélérateurs clavier pour KBabel
+Name[ga]=Bailíochtú na nAicearraí le haghaidh KBabel
+Name[gl]=Validación de Aceleradores para KBabel
+Name[hi]=के-बेबल के लिठतà¥à¤µà¤°à¤• वेलिडेशन
+Name[hu]=Gyorsbillentyű-ellenőrző a KBabelhez
+Name[is]=Flýtilyklastaðfestir fyrir KBabel
+Name[it]=Convalida dei tasti acceleratori per KBabel
+Name[ja]=KBabel アクセラレータ検証
+Name[ka]=KBabel-ის áƒáƒ¥áƒ¡áƒ”ლერáƒáƒ¢áƒáƒ áƒ˜ დáƒáƒ›áƒ›áƒáƒ¬áƒ›áƒ”ბელი
+Name[kk]=KBabel-дің акÑелераторларды текÑеруі
+Name[lt]= KBabel prieigos klavišų žymių patikros įrankis
+Name[ms]=Pengesahan Kekunci Pintas untuk KBabel
+Name[nb]=Sjekk av snarveistaster i KBabel
+Name[nds]=Tastkombinatschoonprööv för KBabel
+Name[ne]=केबà¥à¤¯à¤¾à¤¬à¤²à¤•à¤¾ लागि गतिबरà¥à¤§à¤• पà¥à¤°à¤®à¤¾à¤£à¥€à¤•à¤°à¤£
+Name[nl]=Sneltoetsvalidatie voor KBabel
+Name[nn]=Sjekk av snarvegstastar i KBabel
+Name[pa]=ਕਬਬੇਲ ਲਈ ਪਰਵੇਸ਼ਕ ਪਰਮਾਣਕ
+Name[pl]=Sprawdzanie klawiszy skrótu w KBabel
+Name[pt]=Validação de Aceleradores para o KBabel
+Name[pt_BR]=Validação de Acelerador para o KBabel
+Name[ru]=Проверка акÑелераторов Ð´Ð»Ñ KBabel
+Name[sk]=Kontrola akcelerátorov pre KBabel
+Name[sl]=Pospeševalni potrjevalnik za KBabel
+Name[sr]=Овера таÑтера за брзи приÑтуп за KBabel
+Name[sr@Latn]=Overa tastera za brzi pristup za KBabel
+Name[sv]=Validering av snabbtangenter för Kbabel
+Name[ta]= Kபாபேலà¯à®•à¯à®•à¯ தரà¯à®®à®¤à®¿à®ªà¯à®ªà¯ செலà¯à®²à¯à®ªà®Ÿà®¿à®šà¯ சோதனை
+Name[tg]=Тафтиши акÑелаторҳо барои KBabel
+Name[tr]=KBabel için Hızlandırma Onayı
+Name[uk]=Перевірка акÑелератора Ð´Ð»Ñ KBabel
+Name[zh_CN]=KBabel çš„å¿«æ·é”®æ£€æŸ¥å™¨
+Name[zh_TW]=KBabel 的快速éµæª¢æŸ¥å™¨
+ValidationString=accelerator
+X-KDE-Library=kbabel_accelstool
+Type=Service
+Commands=validate
+Comment=Check Accelerators
+Comment[bg]=Проверка на уÑкорителите
+Comment[bs]=Provjeri akceleratore
+Comment[ca]=Comprova els acceleradors
+Comment[cs]=Zkontrolovat akcelerátory
+Comment[cy]=Gwirio Cyflymyddion
+Comment[da]=Tjek acceleratorer
+Comment[de]=Kurzbefehle prüfen
+Comment[el]=Έλεγχος πλήκτÏων επιτάχυνσης
+Comment[es]=Comprobar teclas rápidas
+Comment[et]=Kiirklahvide kontroll
+Comment[eu]=Egiaztatu bizkortzaileak
+Comment[fa]=بررسی شتاب‌دهها
+Comment[fi]=Tarkista pikavalinnat
+Comment[fr]=Vérification des accélérateurs clavier
+Comment[ga]=Seiceáil Aicearraí
+Comment[gl]=Verificación de Aceleradores
+Comment[he]=בודק מזנקי×
+Comment[hi]=तà¥à¤µà¤°à¤• जांच करें
+Comment[hu]=A gyorsbillentyűk ellenőrzése
+Comment[is]=Athuga flýtilykla
+Comment[it]=Controlla tasti acceleratori
+Comment[ja]=アクセラレータを検証
+Comment[ka]=áƒáƒ¥áƒ¡áƒ”ლერáƒáƒªáƒ˜áƒ˜áƒ¡ შემáƒáƒ¬áƒ›áƒ”ბáƒ
+Comment[kk]=ÐкÑелераторларды текÑеру
+Comment[lt]=Patikrinti prieigos klavišų žymes
+Comment[ms]=Periksa Kekunci Pintas
+Comment[nb]=Sjekk snarveistastene
+Comment[nds]=Tastkombinatschonen pröven
+Comment[ne]=गतिबरà¥à¤§à¤• जाà¤à¤š गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥
+Comment[nl]=Sneltoetsen controleren
+Comment[nn]=Sjekk snarvegstastar
+Comment[pa]=ਪਰਵੇਸ਼ਕ ਜਾਂਚ
+Comment[pl]=Sprawdzenie klawiszy skrótu
+Comment[pt]=Verificação de Aceleradores
+Comment[pt_BR]=Verifica Aceleradores
+Comment[ru]=Проверка акÑелераторов
+Comment[sk]=Kontrola akcelerátorov
+Comment[sl]=Preveri pospeševalnike
+Comment[sr]=Провери таÑтере за брзи приÑтуп
+Comment[sr@Latn]=Proveri tastere za brzi pristup
+Comment[sv]=Kontrollera snabbtangenter
+Comment[ta]=தரà¯à®®à®¤à®¿à®ªà¯à®ªà¯ சரிபாரà¯à®ªà¯à®ªà¯
+Comment[tg]=Тафтиши акÑелаторҳо
+Comment[tr]=Hızlandırıcıları Denetle
+Comment[uk]=Перевірити акÑелератори
+Comment[zh_CN]=检查快æ·é”®
+Comment[zh_TW]=檢查快速éµ
+Shortcuts=Ctrl+H
+ServiceTypes=KBabelValidator,KDataTool
+DataType=CatalogItem
+DataMimeTypes=application/x-kbabel-catalogitem
+ReadOnly=true
diff --git a/kbabel/datatools/accelerators/main.cc b/kbabel/datatools/accelerators/main.cc
new file mode 100644
index 00000000..4d94354e
--- /dev/null
+++ b/kbabel/datatools/accelerators/main.cc
@@ -0,0 +1,137 @@
+/* This file is part of KBabel
+ based Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ 2002 Stanislav Visnovsky <visnovsky@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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#include <resources.h>
+#include "catalogitem.h"
+#include "catalogsettings.h"
+#include "main.h"
+
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <klocale.h>
+
+/***************************************************
+ *
+ * Factory
+ *
+ ***************************************************/
+
+K_EXPORT_COMPONENT_FACTORY( kbabel_accelstool, KGenericFactory<AcceleratorTool> ( "kbabeldatatool" ) )
+
+using namespace KBabel;
+
+AcceleratorTool::AcceleratorTool( QObject* parent, const char* name, const QStringList & )
+ : KDataTool( parent, name ), _cache_origin( 0 )
+{
+ // bogus translation just for allowing the translation
+ i18n("what check found errors","accelerator");
+}
+
+bool AcceleratorTool::run( const QString& command, void* data, const QString& datatype, const QString& mimetype )
+{
+ if ( command != "validate" )
+ {
+ kdDebug(KBABEL) << "Accelerator Tool does only accept the command 'validate'" << endl;
+ kdDebug(KBABEL) << " The commands " << command << " is not accepted" << endl;
+ return FALSE;
+ }
+
+ // Check wether we can accept the data
+ if ( datatype != "CatalogItem" )
+ {
+ kdDebug(KBABEL) << "Accelerator Tool only accepts datatype CatalogItem" << endl;
+ return FALSE;
+ }
+
+ if ( mimetype != "application/x-kbabel-catalogitem" )
+ {
+ kdDebug(KBABEL) << "Accelerator Tool only accepts mimetype application/x-kbabel-catalogitem" << endl;
+ return FALSE;
+ }
+
+ if( command == "validate" )
+ {
+ CatalogItem* item = (CatalogItem*)(data);
+
+ if( _cache_origin != item->project() )
+ {
+ _context = item->project()->miscSettings().contextInfo;
+ _marker = item->project()->miscSettings().accelMarker;
+ _cache_origin = item->project();
+ }
+
+ bool hasError = false;
+
+ if(!item->isUntranslated())
+ {
+ // FIXME: this should care about plural forms in msgid
+ QString lineid=item->msgid().first();
+ lineid.replace( _context, "");
+ lineid.replace(QRegExp("\\n"),"");
+ lineid.simplifyWhiteSpace();
+ QString regStr(_marker);
+ regStr+="[^\\s]";
+ QRegExp reg(regStr);
+
+ QStringList str = item->msgstr(true);
+ for( QStringList::Iterator form = str.begin() ; form != str.end(); form++ )
+ {
+ QString linestr=(*form);
+ linestr.simplifyWhiteSpace();
+
+ int n = lineid.contains(reg);
+ if( _marker == '&' )
+ n = n - lineid.contains(QRegExp("(&[a-z,A-Z,\\-,0-9,#]*;)|(&&(?!&+))"));
+ int m = linestr.contains(reg);
+ if( _marker == '&' )
+ m = m - linestr.contains(QRegExp("(&[a-z,A-Z,\\-,0-9,#]*;)|(&&(?!&+))"));
+ hasError = hasError || ( n<=1 && m != n);
+ }
+ }
+
+ if(hasError)
+ {
+ item->appendError( "Accelerator" );
+ }
+ else
+ {
+ item->removeError( "Accelerator" );
+ }
+
+ return !hasError;
+ }
+ return FALSE;
+}
+
+#include "main.moc"
diff --git a/kbabel/datatools/accelerators/main.h b/kbabel/datatools/accelerators/main.h
new file mode 100644
index 00000000..559fe112
--- /dev/null
+++ b/kbabel/datatools/accelerators/main.h
@@ -0,0 +1,56 @@
+/* This file is part of KBabel
+ based on Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ 2002 Stanislav Visnovsky <visnovsky@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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#ifndef __main_h__
+#define __main_h__
+
+#include "kbproject.h"
+
+#include <kdatatool.h>
+
+#include <qregexp.h>
+
+class AcceleratorTool : public KDataTool
+{
+ Q_OBJECT
+
+public:
+ AcceleratorTool( QObject* parent, const char* name, const QStringList & );
+ virtual bool run( const QString& command, void* data, const QString& datatype, const QString& mimetype);
+
+private:
+ QRegExp _context;
+ QChar _marker;
+ KBabel::Project::Ptr _cache_origin;
+};
+
+#endif
diff --git a/kbabel/datatools/arguments/Makefile.am b/kbabel/datatools/arguments/Makefile.am
new file mode 100644
index 00000000..5585d438
--- /dev/null
+++ b/kbabel/datatools/arguments/Makefile.am
@@ -0,0 +1,19 @@
+
+INCLUDES = -I$(srcdir)/../../common -I../../common $(all_includes)
+kbabel_argstool_la_LIBADD = $(LIB_KIO) ../../common/libkbabelcommon.la
+
+####### Files
+
+kde_module_LTLIBRARIES = kbabel_argstool.la
+
+kbabel_argstool_la_SOURCES = main.cc
+
+kbabel_argstool_la_LDFLAGS = $(all_libraries) -avoid-version -module -no-undefined
+
+noinst_HEADERS = main.h
+
+kbabel_argstool_la_METASOURCES = AUTO
+
+service_DATA = kbabel_argstool.desktop
+servicedir = $(kde_servicesdir)
+
diff --git a/kbabel/datatools/arguments/kbabel_argstool.desktop b/kbabel/datatools/arguments/kbabel_argstool.desktop
new file mode 100644
index 00000000..e90ba652
--- /dev/null
+++ b/kbabel/datatools/arguments/kbabel_argstool.desktop
@@ -0,0 +1,106 @@
+[Desktop Entry]
+Name=Argument Validation for KBabel
+Name[bg]=ВалидноÑÑ‚ на аргументите - KBabel
+Name[bs]=Provjera argumenata za KBabel
+Name[ca]=Validació dels arguments per a KBabel
+Name[cs]=Validace argumentů pro KBabel
+Name[cy]= Dilysiant Ymresymiad i KBabel
+Name[da]=Argument-validering for KBabel
+Name[de]=Argument-Überprüfung für KBabel
+Name[el]=Έλεγχος εγκυÏότητας οÏισμάτων για το KBabel
+Name[es]=Validació de argumentos para KBabel
+Name[et]=KBabeli argumentide kontrollija
+Name[eu]=Argumentu balidazioa KBabel-entzat
+Name[fa]=اعتبارسنجی نشانوند برای KBabel
+Name[fi]=Argumenttien tarkistus KBabelissa
+Name[fr]=Validation d'un argument pour KBabel
+Name[ga]=Bailíochtú Argóintí le haghaidh KBabel
+Name[gl]=Validación de Argumentos para KBabel
+Name[hi]=के-बेबल के लिठआरà¥à¤—à¥à¤®à¥‡à¤‚ट वेलिडेशन
+Name[hu]=Argumentumellenőrző a KBabelhez
+Name[is]=Viðfangastaðfestir fyrir KBabel
+Name[it]=Convalida argomenti per KBabel
+Name[ja]=KBabel 引数検証
+Name[ka]=KBabel-ის áƒáƒ áƒ’უმენტთრდáƒáƒ›áƒ›áƒáƒ¬áƒ›áƒ”ბელი
+Name[kk]=KBabel-дың аргументтерін текÑеруі
+Name[lt]=Kbabel argumentų patikros įrankis
+Name[ms]=Pengesahan Argumen untuk KBabel
+Name[nb]=Argumentsjekk for KBabel
+Name[nds]=Argumentenprööv för KBabel
+Name[ne]=केबà¥à¤¯à¤¾à¤¬à¤²à¤•à¤¾ लागि विषय पà¥à¤°à¤®à¤¾à¤£à¥€à¤•à¤°à¤£
+Name[nl]=Argumentenvalidatie voor KBabel
+Name[nn]=Argumentsjekk for KBabel
+Name[pa]=ਕੇਬਬੇਲ ਲਈ ਆਰਗੂਮਿੰਟ ਪੜਤਾਲ
+Name[pl]=Sprawdzenie argumentów w KBabel
+Name[pt]=Validação de Argumentos para o KBabel
+Name[pt_BR]=Validação de Argumentos para o KBabel
+Name[ru]=Проверка аргументов Ð´Ð»Ñ KBabel
+Name[sk]=Kontrola argumentov pre KBabel
+Name[sl]=Argumentni potrjevalnik za KBabel
+Name[sr]=Овера аргумената за KBabel
+Name[sr@Latn]=Overa argumenata za KBabel
+Name[sv]=Validering av parametrar för Kbabel
+Name[ta]= Kபாபேலà¯à®•à¯à®•à¯ தரà¯à®®à®¤à®¿à®ªà¯à®ªà¯ செலà¯à®²à¯à®ªà®Ÿà®¿à®šà¯ சோதனை
+Name[tg]=Тафтиши далелҳо барои KBabel
+Name[tr]=KBabel için Hızlandırma Argümanı
+Name[uk]=Перевірка аргументів Ð´Ð»Ñ KBabel
+Name[zh_CN]=KBabel çš„å‚数检查器
+Name[zh_TW]=KBabel çš„åƒæ•¸æª¢æŸ¥å™¨
+X-KDE-Library=kbabel_argstool
+Type=Service
+Commands=validate
+Comment=Check Arguments
+Comment[bg]=Проверка на аргументите
+Comment[bs]=Provjeri argumente
+Comment[ca]=Comprova els arguments
+Comment[cs]=Zkontrolovat argumenty
+Comment[cy]=Gwirio Ymresymiadau
+Comment[da]=Tjek argumenter
+Comment[de]=Argumente prüfen
+Comment[el]=Έλεγχος οÏισμάτων
+Comment[eo]=Kontroli argumentojn
+Comment[es]=Comprobar argumentos
+Comment[et]=Argumentide kontroll
+Comment[eu]=Egiaztatu argumentuak
+Comment[fa]=بررسی نشانوندها
+Comment[fi]=Tarkista argumentit
+Comment[fr]=Vérification des arguments
+Comment[ga]=Seiceáil Argóintí
+Comment[gl]=Verificación dos argumentos
+Comment[he]=בודק ×רגומנטי×
+Comment[hi]=आरà¥à¤—à¥à¤®à¥‡à¤‚ट जांच करें
+Comment[hu]=Az argumentumok ellenőrzése
+Comment[is]=Athuga viðföng
+Comment[it]=Controlla argomenti
+Comment[ja]=引数を検証
+Comment[ka]=áƒáƒ áƒ’უმენტების შემáƒáƒ¬áƒ›áƒ”ბáƒ
+Comment[kk]=Ðргументтерді текÑеру
+Comment[lt]=Patikrinti argumentus
+Comment[ms]=Periksa Argumen
+Comment[nb]=Sjekk argumenter
+Comment[nds]=Argumenten pröven
+Comment[ne]=विषय जाà¤à¤š गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥
+Comment[nl]=Argumenten controleren
+Comment[nn]=Sjekk argument
+Comment[pa]=ਆਰਗੂਮਿੰਟ ਜਾਂਚ
+Comment[pl]=Sprawdzenie argumentów
+Comment[pt]=Verificação dos argumentos
+Comment[pt_BR]=Verifica Argumentos
+Comment[ru]=Проверить аргументы
+Comment[sk]=Kontrola argumentov
+Comment[sl]=Preveri argumente
+Comment[sr]=Провери аргументе
+Comment[sr@Latn]=Proveri argumente
+Comment[sv]=Kontrollera parametrar
+Comment[ta]= தரà¯à®®à®¤à®¿à®ªà¯à®ªà¯à®•à®³à¯ˆ சரிபாரà¯à®ªà¯à®ªà¯
+Comment[tg]=Тафтиш кардани далелҳо
+Comment[tr]=Argümanların Denetimi
+Comment[uk]=Перевірити аргументи
+Comment[zh_CN]=检查å‚æ•°
+Comment[zh_TW]=檢查åƒæ•¸
+Shortcuts=Ctrl+D
+ValidationString=arguments
+ServiceTypes=KDataTool,KBabelValidator
+DataType=CatalogItem
+DataMimeTypes=application/x-kbabel-catalogitem
+ReadOnly=true
diff --git a/kbabel/datatools/arguments/main.cc b/kbabel/datatools/arguments/main.cc
new file mode 100644
index 00000000..92c9765c
--- /dev/null
+++ b/kbabel/datatools/arguments/main.cc
@@ -0,0 +1,277 @@
+/* This file is part of KBabel
+ based Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ 2002-2003 Stanislav Visnovsky <visnovsky@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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#include <resources.h>
+#include "catalogitem.h"
+#include "catalogsettings.h"
+#include "main.h"
+
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+/***************************************************
+ *
+ * Factory
+ *
+ ***************************************************/
+
+K_EXPORT_COMPONENT_FACTORY( kbabel_argstool, KGenericFactory<ArgumentTool> ( "kbabeldatatool" ) )
+
+using namespace KBabel;
+
+ArgumentTool::ArgumentTool( QObject* parent, const char* name, const QStringList & )
+ : KDataTool( parent, name ), _cache_origin( 0 )
+{
+ i18n( "what check found errors","arguments");
+}
+
+bool ArgumentTool::run( const QString& command, void* data, const QString& datatype, const QString& mimetype )
+{
+ if ( command != "validate" )
+ {
+ kdDebug(KBABEL) << "Argument Tool does only accept the command 'validate' and 'shortcut'" << endl;
+ kdDebug(KBABEL) << " The commands " << command << " is not accepted" << endl;
+ return FALSE;
+ }
+
+ // Check wether we can accept the data
+ if ( datatype != "CatalogItem" )
+ {
+ kdDebug(KBABEL) << "Argument Tool only accepts datatype CatalogItem" << endl;
+ return FALSE;
+ }
+
+ if ( mimetype != "application/x-kbabel-catalogitem" )
+ {
+ kdDebug(KBABEL) << "Argument Tool only accepts mimetype application/x-kbabel-catalogitem" << endl;
+ return FALSE;
+ }
+
+ if( command == "validate" )
+ {
+ CatalogItem* item = (CatalogItem*)(data);
+
+ if( item->isNoCformat() ) return true;
+ bool hasError = false;
+
+ if( _cache_origin != item->project() )
+ {
+ _context = item->project()->miscSettings().contextInfo;
+ _checkPlurals = item->project()->identitySettings().checkPluralArgument;
+ _cache_origin = item->project();
+ }
+
+ if(!item->isUntranslated())
+ {
+
+ QString formatChars="dioxXucsfeEgGp%";
+
+ if( _checkPlurals ) formatChars+="n";
+
+ // FIXME: this should care about plural forms in msgid
+ QString line=item->msgid().first();
+ QStringList argList;
+
+// if( isPluralForm() )
+ {
+ // FIXME: this is KDE specific
+ if( line.startsWith("_n:" ))
+ {
+ // truncate text after first \n to get args only once
+ line = line.mid(0,line.find("\\n"));
+ }
+ }
+ line.replace(_context, "");
+ line.replace(QRegExp("\\n"),"");
+ line.simplifyWhiteSpace();
+
+ // flag, for GNU only we can allow reordering
+ bool non_gnu = (item->pluralForm() == KDESpecific);
+
+ int index=line.find(QRegExp("%."));
+
+ while(index>=0)
+ {
+ int endIndex=line.find(QRegExp("[^\\d]"),index+1);
+ if(endIndex<0)
+ {
+ endIndex=line.length();
+ }
+ else if( formatChars.contains(line[endIndex]) )
+ {
+ endIndex++;
+ }
+
+ if(endIndex - index > 1 ) {
+ QString arg = line.mid(index,endIndex-index);
+ if( arg.contains( QRegExp("\\d") ) ) {
+ non_gnu = true;
+ }
+ argList.append(arg);
+
+ }
+
+ index=line.find(QRegExp("%."),endIndex);
+ }
+
+ if( item->pluralForm()==KDESpecific)
+ {
+ // FIXME: this is KDE specific
+ if( _checkPlurals && line.startsWith("_n:" ) && !argList.contains("%n") )
+ {
+ argList.append("%n");
+ }
+ }
+
+ // generate for each plural form to be checked separately
+ line=item->msgstr().first();
+ QStringList lines;
+
+ // FIXME; this is KDE specific
+ if( item->pluralForm() == KDESpecific )
+ {
+ lines = QStringList::split("\\n",line);
+ }
+ else
+ {
+ lines.append(line);
+ }
+
+ QStringList argCache = argList;
+ QStringList foundArgs;
+
+ for(QStringList::Iterator i = lines.begin() ; i!=lines.end() ; i++)
+ {
+ // initialize for the next plural form
+ foundArgs.clear();
+ argList = argCache;
+
+ line=(*i);
+
+ line.replace(QRegExp("\\n"),"");
+
+ QRegExp argdesc(
+ "%((["+formatChars+"])"
+ +"|(\\d)+"
+ +"|(\\d)+\\$(["+formatChars+"])"
+ +")" ) ;
+ index = -1;
+
+ do {
+
+ index = argdesc.search( line, index+1 );
+
+ if( index == -1 ) break;
+
+ // do not add a redundant argument, if it is non GNU
+ if( !non_gnu || !foundArgs.contains( argdesc.cap(0) ) )
+ foundArgs.append( argdesc.cap( 0 ) );
+ } while( true );
+
+ // now, compare the list
+ argList = argCache;
+
+ if( non_gnu ) {
+ for ( QStringList::Iterator it = foundArgs.begin(); it != foundArgs.end(); ++it ) {
+ if( argList.find( *it ) == argList.end() ) {
+ hasError = true;
+ break;
+ } else {
+ argList.remove( *it );
+ }
+ }
+
+ if( ! argList.isEmpty() ) {
+ hasError = true;
+ }
+ }
+ else
+ {
+ // handle GNU with replacements
+ QStringList::Iterator oit = argList.begin();
+ for ( QStringList::Iterator it = foundArgs.begin(); it != foundArgs.end(); ++it , ++oit) {
+ if( *it == *oit ) {
+ // argument is the same, mark as used
+ *oit = QString::null;
+ } else {
+ // try to strip replacement
+ int index = (*it).find( '$' );
+ if( index == -1 ) {
+ // there is no replacement, this is wrong
+ hasError = true;
+ break;
+ }
+ QString place = (*it).mid( 1, index-1 );
+ QString arg = (*it).right( index );
+ arg[0] = '%';
+ QStringList::Iterator a = argList.at( place.toInt()-1 );
+ if( a != argList.end() && (*a) == arg )
+ {
+ (*a) = QString::null;
+ }
+ else
+ {
+ // duplicate or index is too high
+ hasError = true;
+ }
+ }
+ }
+
+ for ( QStringList::Iterator it = argList.begin(); it != argList.end(); ++it) {
+ if( ! (*it).isNull () ) {
+ // argument is the same, mark as used
+ hasError = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if(hasError)
+ {
+ item->appendError( "Arguments" );
+ }
+ else
+ {
+ item->removeError( "Arguments" );
+ }
+
+ return !hasError;
+ }
+ return FALSE;
+}
+
+#include "main.moc"
diff --git a/kbabel/datatools/arguments/main.h b/kbabel/datatools/arguments/main.h
new file mode 100644
index 00000000..a05cce49
--- /dev/null
+++ b/kbabel/datatools/arguments/main.h
@@ -0,0 +1,55 @@
+/* This file is part of KBabel
+ based on Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ 2002-2003 Stanislav Visnovsky <visnovsky@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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#ifndef __main_h__
+#define __main_h__
+
+#include "kbproject.h"
+
+#include <kdatatool.h>
+
+#include <qregexp.h>
+
+class ArgumentTool : public KDataTool
+{
+ Q_OBJECT
+
+public:
+ ArgumentTool( QObject* parent, const char* name, const QStringList & );
+ virtual bool run( const QString& command, void* data, const QString& datatype, const QString& mimetype);
+private:
+ KBabel::Project::Ptr _cache_origin;
+ QRegExp _context;
+ bool _checkPlurals;
+};
+
+#endif
diff --git a/kbabel/datatools/context/Makefile.am b/kbabel/datatools/context/Makefile.am
new file mode 100644
index 00000000..4d4a7c0e
--- /dev/null
+++ b/kbabel/datatools/context/Makefile.am
@@ -0,0 +1,19 @@
+
+INCLUDES = -I$(srcdir)/../../common -I../../common $(all_includes)
+kbabel_contexttool_la_LIBADD = $(LIB_KIO) ../../common/libkbabelcommon.la
+
+####### Files
+
+kde_module_LTLIBRARIES = kbabel_contexttool.la
+
+kbabel_contexttool_la_SOURCES = main.cc
+
+kbabel_contexttool_la_LDFLAGS = $(all_libraries) -avoid-version -module -no-undefined
+
+noinst_HEADERS = main.h
+
+kbabel_contexttool_la_METASOURCES = AUTO
+
+service_DATA = kbabel_contexttool.desktop
+servicedir = $(kde_servicesdir)
+
diff --git a/kbabel/datatools/context/kbabel_contexttool.desktop b/kbabel/datatools/context/kbabel_contexttool.desktop
new file mode 100644
index 00000000..482fefcf
--- /dev/null
+++ b/kbabel/datatools/context/kbabel_contexttool.desktop
@@ -0,0 +1,100 @@
+[Desktop Entry]
+Name=Translated Context Info Validation for KBabel
+Name[bg]=ВалидноÑÑ‚ на контекÑтната Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ - KBabel
+Name[bs]=Provjera prevedenih kontekst informacija za KBabel
+Name[ca]=Validació de la informació al context traduït per a KBabel
+Name[cs]=Validace přeložených kontextových informací
+Name[cy]=Dilysiant Gwybodaeth Cyd-destun wedi'i cyfieithu i KBabel
+Name[da]=Oversat sammenhængsinfo-validering for KBabel
+Name[de]=Kontextinfo-Überprüfung für KBabel
+Name[el]=Έλεγχος εγκυÏότητας μεταφÏασμένων σχετικών πληÏοφοÏιών για το KBabel
+Name[es]=Validación de información de contexto traducida para KBabel
+Name[et]=KBabeli tõlgitud kontekstiinfo kontrollija
+Name[eu]=Itzulitako kontestuen informazioaren balidazioa KBabel-entzat
+Name[fa]=اعتبارسنجی اطلاعات متن ترجمه‌شده برای KBabel
+Name[fi]=Käännetyn kontekstitiedon tarkistus KBabelissa
+Name[fr]=Validation des informations de contexte de traduction pour KBabel
+Name[gl]=Validación da Información de Contexto para KBabel
+Name[hi]=के-बेबल के लिठअनूदित कॉनà¥à¤Ÿà¥‡à¤•à¥à¤¸à¥à¤Ÿ जानकारी वेलिडेशन
+Name[hu]=Ellenőrző a fordítási kontextushoz a KBabelben
+Name[is]=Staðfesting þýddra samhengisupplýsinga fyrir KBabel
+Name[it]=Convalida delle informazioni di contesto tradotte per KBabel
+Name[ja]=KBabel 翻訳ã•ã‚ŒãŸæ–‡è„ˆæƒ…報を検索
+Name[ka]=თáƒáƒ áƒ’მნის კáƒáƒœáƒ¢áƒ”ქსტის ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ KBabel-სთვის
+Name[kk]=KBabel-дың аударылған контекÑтік мәліметін текÑеру
+Name[lt]=KBabel išverstos kontekstinės informacijos patikros įrankis
+Name[ms]=Pengesahan Info Konteks Telah Diterjemah untuk KBabel
+Name[nb]=Sjekk av oversatt sammenhengsinformasjon i KBabel
+Name[nds]=Prööv op översett Infokontext för KBabel
+Name[ne]=केबà¥à¤¯à¤¾à¤¬à¤²à¤•à¤¾ लागि अनà¥à¤¬à¤¾à¤¦ गरिà¤à¤•à¥‹ पà¥à¤°à¤¸à¤™à¥à¤— सूचना पà¥à¤°à¤®à¤¾à¤£à¥€à¤•à¤°à¤£
+Name[nl]=Vertaalde contextinformatie-validatie voor KBabel
+Name[nn]=Sjekk av omsett samanhengsinformasjon i KBabel
+Name[pl]=Sprawdzanie kontekstu tłumaczonej informacji dla KBabel
+Name[pt]=Validação da Informação de Contexto do KBabel
+Name[pt_BR]=Validação de Informações de Contexto Traduzidas para o KBabel
+Name[ru]=Проверка переведённой контекÑтной информации Ð´Ð»Ñ KBabel
+Name[sk]=Kontrola kontextu v preklade pre KBabel
+Name[sl]=Potrjevalnik informacij prevedene vsebine za KBabel
+Name[sr]=Овера преведених контекÑтних информација за KBabel
+Name[sr@Latn]=Overa prevedenih kontekstnih informacija za KBabel
+Name[sv]=Validering av översatt sammanhangsinformation för Kbabel
+Name[ta]= Kபாபேலà¯à®•à¯à®•à¯ மொழிபெயரà¯à®ªà¯à®ªà¯ சூழல௠தகவல௠செலà¯à®²à¯à®ªà®Ÿà®¿à®¯à®¾à®•à¯à®•à®®à¯
+Name[tg]=Тафтиши ахбороти тарҷумашудаи матнӣ барои KBabel
+Name[tr]=KBabel için Çevrilen Bağlam Bilgisi Denetimi
+Name[uk]=Перевірка інформації контекÑту перекладу Ð´Ð»Ñ KBabel
+Name[zh_CN]=KBabel 的上下文信æ¯ç¿»è¯‘检查器
+Name[zh_TW]=KBabel 的已翻譯內容資訊確èª
+ValidationString=context information
+X-KDE-Library=kbabel_contexttool
+Type=Service
+Commands=validate
+Comment=Look for Translated Context Info
+Comment[bg]=ТърÑене на контекÑтна Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° преведените
+Comment[bs]=Potraži prevedene kontekstne informacije
+Comment[ca]=Mira la informació al context traduït
+Comment[cs]=Vyhledat přeložené kontextové informace
+Comment[cy]=Chwilio am Gwybodaeth Cyd-destun wedi'i cyfieithu
+Comment[da]=Kig efter oversat sammenhængsinfo
+Comment[de]=Suche nach übersetzter Kontextinformation
+Comment[el]=Έλεγχος για μεταφÏασμένες σχετικές πληÏοφοÏίες
+Comment[es]=Buscar información de contexto traducida
+Comment[et]=Tõlgitud kontekstiinfo otsimine
+Comment[eu]=Bilatu itzulitako kontestuaren informazioa
+Comment[fa]=جستجوی اطلاعات متن ترجمه‌شده
+Comment[fi]=Etsi käännettyä kontekstitietoa
+Comment[fr]=Analyse les informations de contexte de traduction
+Comment[gl]=Verificar a información de contexto
+Comment[hi]=अनूदित कॉनà¥à¤Ÿà¥‡à¤•à¥à¤¸à¥à¤Ÿ जानकारी के लिठदेखें
+Comment[hu]=A kontextusfordítások kiszűrése
+Comment[is]=Leita að þýddum samhengisupplýsingum
+Comment[it]=Cerca informazioni di contesto tradotte
+Comment[ja]=翻訳ã•ã‚ŒãŸæ–‡è„ˆæƒ…報を検索
+Comment[ka]=თáƒáƒ áƒ’მნის კáƒáƒœáƒ¢áƒ”ქსტის ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ ძიებáƒ
+Comment[kk]=Ðударылған контекÑтік мәліметін қарау
+Comment[lt]=Ieškoti išverstos kontekstinės informacijos
+Comment[ms]=Cari Info Konteks Telah Diterjemah
+Comment[nb]=Se etter oversatt kontekstinformasjon
+Comment[nds]=Op översett Kontextinformatschonen pröven
+Comment[ne]=अनà¥à¤¬à¤¾à¤¦ गरिà¤à¤•à¥‹ पà¥à¤°à¤¸à¤™à¥à¤— सूचना अवलोकन
+Comment[nl]=Vertaalde contextinformatie zoeken
+Comment[nn]=Sjå etter omsett samanhengsinformasjon
+Comment[pl]=Sprawdzenie kontekstu tłumaczonej informacji
+Comment[pt]=Verificar a existência de traduções da informação de contexto
+Comment[pt_BR]=Procura por Informações de Contexto Traduzidas
+Comment[ru]=ПоиÑк переведённой контекÑтной информации
+Comment[sk]=Hľadanie preloženej kontextovej informácie
+Comment[sl]=Vpogled v Informacije prevedene vsebine
+Comment[sr]=Изглед за преведене контекÑтне информације
+Comment[sr@Latn]=Izgled za prevedene kontekstne informacije
+Comment[sv]=Leta efter översatt sammanhangsinformation
+Comment[ta]= மொழிபெயரà¯à®ªà¯à®ªà¯ சூழல௠தகவலை பாரà¯
+Comment[tg]=ҶуÑтуҷӯи ахбороти тарҷумашудаи матнӣ
+Comment[tr]=Çevrilen Bağlam Bilgisi için Görünüş
+Comment[uk]=Пошук за інформацією контекÑту перекладу
+Comment[zh_CN]=查找翻译的上下文信æ¯
+Comment[zh_TW]=尋找已翻譯的內容資訊
+Shortcuts=Ctrl+L
+ServiceTypes=KDataTool,KBabelValidator
+DataType=CatalogItem
+DataMimeTypes=application/x-kbabel-catalogitem
+ReadOnly=true
diff --git a/kbabel/datatools/context/main.cc b/kbabel/datatools/context/main.cc
new file mode 100644
index 00000000..19af3afd
--- /dev/null
+++ b/kbabel/datatools/context/main.cc
@@ -0,0 +1,115 @@
+/* This file is part of KBabel
+ based Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ 2002 Stanislav Visnovsky <visnovsky@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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#include <resources.h>
+#include "catalogitem.h"
+#include "catalogsettings.h"
+#include "main.h"
+
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+/***************************************************
+ *
+ * Factory
+ *
+ ***************************************************/
+
+K_EXPORT_COMPONENT_FACTORY( kbabel_contexttool, KGenericFactory<ContextTool> ( "kbabeldatatool" ) )
+
+using namespace KBabel;
+
+ContextTool::ContextTool( QObject* parent, const char* name, const QStringList & )
+ : KDataTool( parent, name ), _cache_origin( 0 )
+{
+ i18n("what check found errors","context info");
+}
+
+bool ContextTool::run( const QString& command, void* data, const QString& datatype, const QString& mimetype )
+{
+ if ( command != "validate" )
+ {
+ kdDebug(KBABEL) << "Context Tool does only accept the command 'validate' and 'shortcut'" << endl;
+ kdDebug(KBABEL) << " The commands " << command << " is not accepted" << endl;
+ return FALSE;
+ }
+
+ // Check wether we can accept the data
+ if ( datatype != "CatalogItem" )
+ {
+ kdDebug(KBABEL) << "Context Tool only accepts datatype CatalogItem" << endl;
+ return FALSE;
+ }
+
+ if ( mimetype != "application/x-kbabel-catalogitem" )
+ {
+ kdDebug(KBABEL) << "Context Tool only accepts mimetype application/x-kbabel-catalogitem" << endl;
+ return FALSE;
+ }
+
+ if( command == "validate" )
+ {
+ CatalogItem* item = (CatalogItem*)(data);
+
+ if( _cache_origin != item->project() )
+ {
+ _context = item->project()->miscSettings().contextInfo;
+ _cache_origin = item->project();
+ }
+
+ bool hasError = false;
+
+ if(!item->isUntranslated() && item->msgid().first().contains(_context)
+ && item->msgstr().first().contains(_context) )
+ {
+ hasError = true;
+ }
+
+ if(hasError)
+ {
+ item->appendError( "context info" );
+ }
+ else
+ {
+ item->removeError( "context info" );
+ }
+
+ return !hasError;
+ }
+ return FALSE;
+}
+
+#include "main.moc"
diff --git a/kbabel/datatools/context/main.h b/kbabel/datatools/context/main.h
new file mode 100644
index 00000000..99035691
--- /dev/null
+++ b/kbabel/datatools/context/main.h
@@ -0,0 +1,52 @@
+/* This file is part of KBabel
+ based on Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ 2002 Stanislav Visnovsky <visnovsky@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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#ifndef __main_h__
+#define __main_h__
+
+#include "kbproject.h"
+
+#include <kdatatool.h>
+
+class ContextTool : public KDataTool
+{
+ Q_OBJECT
+
+public:
+ ContextTool( QObject* parent, const char* name, const QStringList & );
+ virtual bool run( const QString& command, void* data, const QString& datatype, const QString& mimetype);
+private:
+ KBabel::Project::Ptr _cache_origin;
+ QRegExp _context;
+};
+
+#endif
diff --git a/kbabel/datatools/equations/Makefile.am b/kbabel/datatools/equations/Makefile.am
new file mode 100644
index 00000000..9b49892d
--- /dev/null
+++ b/kbabel/datatools/equations/Makefile.am
@@ -0,0 +1,19 @@
+
+INCLUDES = -I$(srcdir)/../../common -I../../common $(all_includes)
+kbabel_equationstool_la_LIBADD = $(LIB_KIO) ../../common/libkbabelcommon.la
+
+####### Files
+
+kde_module_LTLIBRARIES = kbabel_equationstool.la
+
+kbabel_equationstool_la_SOURCES = main.cc
+
+kbabel_equationstool_la_LDFLAGS = $(all_libraries) -avoid-version -module -no-undefined
+
+noinst_HEADERS = main.h
+
+kbabel_equationstool_la_METASOURCES = AUTO
+
+service_DATA = kbabel_equationstool.desktop
+servicedir = $(kde_servicesdir)
+
diff --git a/kbabel/datatools/equations/kbabel_equationstool.desktop b/kbabel/datatools/equations/kbabel_equationstool.desktop
new file mode 100644
index 00000000..cc3544a5
--- /dev/null
+++ b/kbabel/datatools/equations/kbabel_equationstool.desktop
@@ -0,0 +1,104 @@
+[Desktop Entry]
+Name=Equation Validation for KBabel
+Name[bg]=ВалидноÑÑ‚ на изравнÑването - KBabel
+Name[bs]=Provjera jednakosti za KBabel
+Name[ca]=Validació de les equacions per a KBabel
+Name[cs]=Validace rovnic
+Name[cy]=Dilysiant Hafaliad i KBabel
+Name[da]=Lignings-validering for KBabel
+Name[de]=Formel-Überprüfung für KBabel
+Name[el]=Έλεγχος εγκυÏότητας εξισώσεων για το KBabel
+Name[es]=Validación de ecuaciones para KBabel
+Name[et]=KBabeli võrduste kontrollija
+Name[eu]=Ekuazioen balidazioa KBabel-entzat
+Name[fa]=اعتبارسنجی معادله برای KBabel
+Name[fi]=Yhtälöiden tarkistus KBabelissa
+Name[fr]=Validateur de similitudes pour KBabel
+Name[ga]=Bailíochtú Cothromóidí le haghaidh KBabel
+Name[gl]=Validación de ecuacións para KBabel
+Name[hi]=के-बेबल के लिठसमीकरण वेलिडेशन
+Name[hu]=Egyenletellenőrző a KBabelhez
+Name[is]=Jöfnustaðfesting fyrir KBabel
+Name[it]=Convalida delle equazioni per KBabel
+Name[ja]=KBabel ç­‰å¼æ¤œè¨¼
+Name[ka]=KBabel-ს ფáƒáƒ áƒ›áƒ£áƒšáƒáƒ—რდáƒáƒ›áƒáƒ¬áƒ›áƒ”ბáƒ
+Name[kk]=KBabel-дың баламаларын текÑеруі
+Name[lt]=KBabel lygybių patikros įrankis
+Name[ms]=Pengesahan Persamaan untuk KBabel
+Name[nb]=Likningssjekk for KBabel
+Name[nds]=Gliekenprööv för KBabel
+Name[ne]=केबà¥à¤¯à¤¾à¤¬à¤²à¤•à¤¾ लागि समीकरण पà¥à¤°à¤®à¤¾à¤£à¥€à¤•à¤°à¤£
+Name[nl]=Vergelijkingenvalidatie voor KBabel
+Name[nn]=Likningssjekk for KBabel
+Name[pl]=Sprawdzenie równań w KBabel
+Name[pt]=Validação de Equações para o KBabel
+Name[pt_BR]=Validação de Equação para o KBabel
+Name[ru]=Проверка уравнений Ð´Ð»Ñ KBabel
+Name[sk]=Kontrola rovníc pre KBabel
+Name[sl]=Potrjevalnik enaÄb za KBabel
+Name[sr]=Овера једначина за KBabel
+Name[sr@Latn]=Overa jednaÄina za KBabel
+Name[sv]=Validering av ekvationer för Kbabel
+Name[ta]= Kபாபேலà¯à®•à¯à®•à¯ சமனà¯à®ªà®¾à®Ÿà¯ செலà¯à®²à¯à®ªà®Ÿà®¿à®šà¯ சோதனை
+Name[tg]=Тафтиши баробар барои KBabel
+Name[tr]=KBabel için Denklem Denetimi
+Name[uk]=Перевірка рівнÑнь Ð´Ð»Ñ KBabel
+Name[zh_CN]=KBabel çš„ç­‰å¼æ£€æŸ¥å™¨
+Name[zh_TW]=KBabel çš„ç­‰å¼æª¢æŸ¥å™¨
+X-KDE-Library=kbabel_equationstool
+Type=Service
+Commands=validate
+Comment=Check Equations
+Comment[bg]=Проверка на изравнÑването
+Comment[bs]=Provjeri jednakosti
+Comment[ca]=Comprova les equacions
+Comment[cs]=Zkontrolovat rovnice
+Comment[cy]=Gwirio Hafaliadau
+Comment[da]=Tjek ligninger
+Comment[de]=Formeln prüfen
+Comment[el]=Έλεγχος εξισώσεων
+Comment[es]=Comprobar ecuaciones
+Comment[et]=Võrduste kontroll
+Comment[eu]=Egiaztatu ekuazioak
+Comment[fa]=بررسی معادله‌ها
+Comment[fi]=Tarkista yhtälöt
+Comment[fr]=Vérifier les identités
+Comment[ga]=Seiceáil Cothromóidí
+Comment[gl]=Verifica as ecuacións
+Comment[he]=בודק משוו×ות
+Comment[hi]=समीकरण जांच करें
+Comment[hu]=Az egyenletek ellenőrzése
+Comment[is]=Athuga jöfnur
+Comment[it]=Controlla equazioni
+Comment[ja]= ç­‰å¼ã‚’検証
+Comment[ka]=ფáƒáƒ áƒ›áƒ£áƒšáƒáƒ—რშემáƒáƒ¬áƒ›áƒ”ბáƒ
+Comment[kk]=Баламаларды текÑеру
+Comment[lt]=Tikrinti lygybes
+Comment[ms]=Periksa Persamaan
+Comment[nb]=Sjekk likninger
+Comment[nds]=Glieken pröven
+Comment[ne]=समीकरण जाà¤à¤š गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥
+Comment[nl]=Vergelijkingen controleren
+Comment[nn]=Sjekk likningar
+Comment[pa]=ਸਮੀਕਰਨ ਜਾਂਚ
+Comment[pl]=Sprawdzenie równań
+Comment[pt]=Verifica as equações
+Comment[pt_BR]=Verifica Equações
+Comment[ru]=Проверить уравнениÑ
+Comment[sk]=Kontrola rovníc
+Comment[sl]=Preveri enaÄbe
+Comment[sr]=Провери једначине
+Comment[sr@Latn]=Proveri jednaÄine
+Comment[sv]=Kontrollera ekvationer
+Comment[ta]= சமனà¯à®ªà®¾à®Ÿà¯ சரிபாரà¯à®ªà¯à®ªà¯
+Comment[tg]=Тафтиш кардани баробарҳо
+Comment[tr]=Denklemleri Denetle
+Comment[uk]=Перевірити рівнÑннÑ
+Comment[zh_CN]=检查等å¼
+Comment[zh_TW]=檢查等å¼
+ServiceTypes=KDataTool,KBabelValidator
+Shortcuts=Ctrl+J
+ValidationString=equations
+DataType=CatalogItem
+DataMimeTypes=application/x-kbabel-catalogitem
+ReadOnly=true
diff --git a/kbabel/datatools/equations/main.cc b/kbabel/datatools/equations/main.cc
new file mode 100644
index 00000000..bab01785
--- /dev/null
+++ b/kbabel/datatools/equations/main.cc
@@ -0,0 +1,113 @@
+/* This file is part of KBabel
+ based Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ 2002 Stanislav Visnovsky <visnovsky@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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#include <resources.h>
+#include "catalogitem.h"
+#include "catalogsettings.h"
+#include "main.h"
+
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+/***************************************************
+ *
+ * Factory
+ *
+ ***************************************************/
+
+K_EXPORT_COMPONENT_FACTORY( kbabel_equationstool, KGenericFactory<EquationsTool> ( "kbabeldatatool" ) )
+
+using namespace KBabel;
+
+EquationsTool::EquationsTool( QObject* parent, const char* name, const QStringList & )
+ : KDataTool( parent, name ), _equation("^[a-zA-Z0-9]+=.+")
+{
+ i18n("what check found errors","equations");
+}
+
+bool EquationsTool::run( const QString& command, void* data, const QString& datatype, const QString& mimetype )
+{
+ if ( command != "validate" )
+ {
+ kdDebug(KBABEL) << "Equations Tool does only accept the command 'validate' and 'shortcut'" << endl;
+ kdDebug(KBABEL) << " The commands " << command << " is not accepted" << endl;
+ return FALSE;
+ }
+
+ // Check wether we can accept the data
+ if ( datatype != "CatalogItem" )
+ {
+ kdDebug(KBABEL) << "Equations Tool only accepts datatype CatalogItem" << endl;
+ return FALSE;
+ }
+
+ if ( mimetype != "application/x-kbabel-catalogitem" )
+ {
+ kdDebug(KBABEL) << "Equations Tool only accepts mimetype application/x-kbabel-catalogitem" << endl;
+ return FALSE;
+ }
+
+ if( command == "validate" )
+ {
+ CatalogItem* item = (CatalogItem*)(data);
+
+ bool hasError = false;
+
+ if(!item->isUntranslated() && !item->msgid().first().contains('\n')
+ && item->msgid().first().contains(_equation))
+ {
+ int index = item->msgid().first().find('=');
+ QString left = item->msgid().first().left(index);
+ index = item->msgstr().first().find('=');
+ if(left != item->msgstr().first().left(index))
+ hasError = true;
+ }
+
+ if(hasError)
+ {
+ item->appendError( "equations" );
+ }
+ else
+ {
+ item->removeError( "equations" );
+ }
+
+ return !hasError;
+ }
+ return FALSE;
+}
+
+#include "main.moc"
diff --git a/kbabel/datatools/equations/main.h b/kbabel/datatools/equations/main.h
new file mode 100644
index 00000000..6edff1c6
--- /dev/null
+++ b/kbabel/datatools/equations/main.h
@@ -0,0 +1,50 @@
+/* This file is part of KBabel
+ based on Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ 2002 Stanislav Visnovsky <visnovsky@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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#ifndef __main_h__
+#define __main_h__
+
+#include <qregexp.h>
+#include <kdatatool.h>
+
+class EquationsTool : public KDataTool
+{
+ Q_OBJECT
+
+public:
+ EquationsTool( QObject* parent, const char* name, const QStringList & );
+ virtual bool run( const QString& command, void* data, const QString& datatype, const QString& mimetype);
+private:
+ QRegExp _equation;
+};
+
+#endif
diff --git a/kbabel/datatools/length/Makefile.am b/kbabel/datatools/length/Makefile.am
new file mode 100644
index 00000000..62231402
--- /dev/null
+++ b/kbabel/datatools/length/Makefile.am
@@ -0,0 +1,19 @@
+
+INCLUDES = -I$(srcdir)/../../common -I../../common $(all_includes)
+kbabel_lengthtool_la_LIBADD = $(LIB_KIO) ../../common/libkbabelcommon.la
+
+####### Files
+
+kde_module_LTLIBRARIES = kbabel_lengthtool.la
+
+kbabel_lengthtool_la_SOURCES = main.cc
+
+kbabel_lengthtool_la_LDFLAGS = $(all_libraries) -avoid-version -module -no-undefined
+
+noinst_HEADERS = main.h
+
+kbabel_lengthtool_la_METASOURCES = AUTO
+
+service_DATA = kbabel_lengthtool.desktop
+servicedir = $(kde_servicesdir)
+
diff --git a/kbabel/datatools/length/kbabel_lengthtool.desktop b/kbabel/datatools/length/kbabel_lengthtool.desktop
new file mode 100644
index 00000000..2171f44e
--- /dev/null
+++ b/kbabel/datatools/length/kbabel_lengthtool.desktop
@@ -0,0 +1,98 @@
+[Desktop Entry]
+Name=Translated Message Length Validator for KBabel
+Name[bg]=ВалидноÑÑ‚ на дължината на преведените ÑÑŠÐ¾Ð±Ñ‰ÐµÐ½Ð¸Ñ - KBabel
+Name[bs]=Provjera dužine prevedenih poruka za KBabel
+Name[ca]=Un validador per a KBabel de la llargària dels missatges traduïts
+Name[cs]=Validátor délky přeložených zpráv
+Name[cy]=Dilysydd Hyd Neges wedi'i Gyfieithu ar gyfer KBabel
+Name[da]=Oversat beskedlængde godkender for KBabel
+Name[de]=Überprüfung der übersetzten Nachrichtenlänge für KBabel
+Name[el]=Ελεγκτής εγκυÏότητας μήκους μεταφÏασμένων μηνυμάτων για το KBabel
+Name[eo]=Longeckontrolilo por tradukitaj mesaÄoj
+Name[es]=Validador de longitud de mensajes traducidos para KBabel
+Name[et]=KBabeli tõlgitud teadete pikkuse kontrollija
+Name[eu]=Itzulitako mezu luzera balidatzailea KBabel-entzat
+Name[fa]=اعتبارسنج طول پیام ترجمه‌شده برای KBabel
+Name[fi]=Käännetyn viestin pituuden tarkistus KBabelissa
+Name[fr]=Un validateur de longueur de message pour KBabel
+Name[gl]=Validador do tamaño da mensaxe traducida para KBabel
+Name[hu]=Üzenethossz-ellenőrző a KBabelhez
+Name[is]=Staðfestir á lengd þýddra skeyta fyrir KBabel
+Name[it]=Convalidatore di KBabel per la lunghezza dei messaggi tradotti
+Name[ja]=KBabel 翻訳メッセージã®é•·ã•ã‚’検証
+Name[ka]=ნáƒáƒ—áƒáƒ áƒ’მნი შეტყáƒáƒ‘ინებების სიგრძის დáƒáƒ›áƒáƒ¬áƒ›áƒ”ბრKBabel-სთვის
+Name[kk]=KBabel-дың аударылған жазулардың ұзындығын текÑеруі
+Name[lt]=KBabel išverstų pranešimų ilgio patikros įrankis
+Name[nb]=Sjekk av lengden på oversatte strenger i KBabel
+Name[nds]=Textlängde-Prööv för KBabel
+Name[ne]=केबà¥à¤¯à¤¾à¤¬à¤²à¤•à¤¾ लागि अनà¥à¤¬à¤¾à¤¦ गरिà¤à¤•à¥‹ सनà¥à¤¦à¥‡à¤¶ लमà¥à¤¬à¤¾à¤‡ पà¥à¤°à¤®à¤¾à¤£à¤¿à¤¤à¤•à¤°à¥à¤¤à¤¾
+Name[nl]=Vertaalde-tekstlengte-validatie voor KBabel
+Name[nn]=Sjekk av lengda på omsette strengar i KBabel
+Name[pl]=Sprawdzenie długości przetłumaczonego komunikatu w KBabel
+Name[pt]=Validador do Tamanho da Mensagem Traduzida para o KBabel
+Name[pt_BR]=Um Validador de Tamanho de Mensagem Traduzida para o KBabel
+Name[ru]=Проверка длины переведённых Ñообщений Ð´Ð»Ñ KBabel
+Name[sk]=Kontrola dĺžky preložených textov pre KBabel
+Name[sl]=Potrjevalnik dolžin prevedenih sporoÄil za KBabel
+Name[sr]=Оверивач дужине преведених порука за KBabel
+Name[sr@Latn]=OverivaÄ dužine prevedenih poruka za KBabel
+Name[sv]=Validering av meddelandelängd för översättningar i Kbabel
+Name[ta]= Kபாபேலà¯à®•à¯à®•à®¾à®© மொழிபெயரà¯à®ªà¯à®ªà¯ செயà¯à®¤à®¿ அளவ௠மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà®¾à®³à®°à¯
+Name[tg]=Утилитаи тафтиши дарозии ахборҳои тарҷумакунанда барои KBabel
+Name[tr]=KBabel için Çevrilen Mesaj Uzunluk Kontrolü
+Name[uk]=Перевірка довжини перекладених фраз Ð´Ð»Ñ KBabel
+Name[zh_CN]=KBabel 已翻译消æ¯çš„长度检查器
+Name[zh_TW]=KBabel 的已翻譯訊æ¯é•·åº¦æª¢æŸ¥å™¨
+ValidationString=length checking
+X-KDE-Library=kbabel_lengthtool
+Type=Service
+Commands=validate
+Comment=Check Translated Message Length
+Comment[bg]=Проверка дължината на преведените ÑъобщениÑ
+Comment[bs]=Provjeri dužinu prevedenih poruka
+Comment[ca]=Comprova la llargària del missatge traduït
+Comment[cs]=Zkontrolovat délku přeložené zprávy
+Comment[cy]=Gwirio hyd neges wedi'i gyfieithu
+Comment[da]=Tjek oversat beskedlængde
+Comment[de]=Prüfung der übersetzten Nachrichtenlänge
+Comment[el]=Έλεγχος μήκους μεταφÏασμένων μηνυμάτων
+Comment[eo]=Kontrolu longecon de tradukita mesaÄo
+Comment[es]=Comprobar longitud de los mensajes traducidos
+Comment[et]=Tõlgitud teate pikkuse kontroll
+Comment[eu]=Egiaztatu itzulitako mezuen luzera
+Comment[fa]=بررسی طول پیام ترجمه‌شده
+Comment[fi]=Tarkista käännetyn viestin pituus
+Comment[fr]=Vérifie la longueur des messages traduits
+Comment[gl]=Verificación do tamaño da mensaxe traducida
+Comment[hi]=अनूदित संदेश लंबाई जाà¤à¤šà¥‡à¤‚
+Comment[hu]=A lefordított üzenetek hosszának ellenőrzése
+Comment[is]=Athuga lengd þýddra skeyta
+Comment[it]=Controlla la lunghezza dei messaggi tradotti
+Comment[ja]=翻訳メッセージã®é•·ã•ã‚’検証
+Comment[ka]=ნáƒáƒ—áƒáƒ áƒ’მნი შეტყáƒáƒ‘ინებების სიგრძის შემáƒáƒ¬áƒ›áƒ”ბáƒ
+Comment[kk]=Ðударылған жазулардың ұзындығын текÑеру
+Comment[lt]=Tikrinti išverstų pranešimų ilgį
+Comment[nb]=Sjekk lengden på oversatte strenger
+Comment[nds]=Översett Textlängde pröven
+Comment[ne]=अनà¥à¤¬à¤¾à¤¦ गरिà¤à¤•à¥‹ सनà¥à¤¦à¥‡à¤¶ लमà¥à¤¬à¤¾à¤‡ जाà¤à¤š गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥
+Comment[nl]=Lengte van vertaalde tekst controleren
+Comment[nn]=Sjekk lengda på omsette strengar
+Comment[pl]=Sprawdzenie długości przetłumaczonego komunikatu
+Comment[pt]=Verificação do Tamanho da Mensagem Traduzida
+Comment[pt_BR]=Verifica o Comprimento da Mensagem Traduzida
+Comment[ru]=Проверить длину переведённых Ñообщений
+Comment[sk]=Kontrola dĺžky preložených textov
+Comment[sl]=Preveri dolžino prevedenih sporoÄil
+Comment[sr]=Провери дужину преведених порука
+Comment[sr@Latn]=Proveri dužinu prevedenih poruka
+Comment[sv]=Kontrollera meddelandelängd för översättningar
+Comment[ta]= மொழிபெயர௠செயà¯à®¤à®¿ நீளம௠சரிபாரà¯à®ªà¯à®ªà¯
+Comment[tg]=Тафтиш кардани дарозии хабарҳои тарҷумашуда
+Comment[tr]=Çevrilen Mesaj Uzunluğunu Denetle
+Comment[uk]=Перевірити довжину перекладених фраз
+Comment[zh_CN]=检查已翻译消æ¯çš„长度
+Comment[zh_TW]=檢查已翻譯訊æ¯é•·åº¦
+ServiceTypes=KDataTool,KBabelValidator
+DataType=CatalogItem
+DataMimeTypes=application/x-kbabel-catalogitem
+ReadOnly=true
diff --git a/kbabel/datatools/length/main.cc b/kbabel/datatools/length/main.cc
new file mode 100644
index 00000000..ee595dc9
--- /dev/null
+++ b/kbabel/datatools/length/main.cc
@@ -0,0 +1,142 @@
+/* This file is part of KBabel
+ based Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ 2002 Stanislav Visnovsky <visnovsky@kde.org>
+ 2003 Dwayne Bailey <dwayne@translate.org.za>
+
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#include <resources.h>
+#include "catalog.h"
+#include "catalogitem.h"
+#include "catalogsettings.h"
+#include "main.h"
+#include <math.h>
+
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+/***************************************************
+ *
+ * Factory
+ *
+ ***************************************************/
+
+K_EXPORT_COMPONENT_FACTORY( kbabel_lengthtool, KGenericFactory<LengthTool> ( "kbabeldatatool" ) )
+
+using namespace KBabel;
+
+LengthTool::LengthTool( QObject* parent, const char* name, const QStringList & )
+ : KDataTool( parent, name ), _cache_origin( 0 )
+{
+ i18n("which check found errors","translation has inconsistent length");
+}
+
+bool LengthTool::run( const QString& command, void* data, const QString& datatype, const QString& mimetype )
+{
+
+ if ( command != "validate" )
+ {
+ kdDebug(KBABEL) << "Length Tool only accepts the 'validate' command" << endl;
+ kdDebug(KBABEL) << " The command " << command << " is not accepted" << endl;
+ return false;
+ }
+
+ // Check wether we can accept the data
+ if ( datatype != "CatalogItem" )
+ {
+ kdDebug(KBABEL) << "Length Tool only accept the CatalogItem datatype" << endl;
+ return false;
+ }
+
+ if ( mimetype != "application/x-kbabel-catalogitem" )
+ {
+ kdDebug(KBABEL) << "Length Tool only accept the 'application/x-kbabel-catalogitem' mimetype" << endl;
+ return false;
+ }
+
+ if( command == "validate" )
+ {
+
+ CatalogItem* item = (CatalogItem*)(data);
+ bool hasError = false;
+ QStringList str, id;
+
+ if(!item->isUntranslated()) {
+
+ if( _cache_origin != item->project() )
+ {
+ _context = item->project()->miscSettings().contextInfo;
+ _plurals = item->project()->miscSettings().singularPlural;
+ _cache_origin = item->project();
+ }
+
+ //Ensure KDE plural forms are in a StringList
+ if( item->pluralForm() == KDESpecific ) {
+ str = QStringList::split( "\\n", item->msgstr().first(), true );
+ id = QStringList::split( "\\n",
+ item->msgid().first().replace( QRegExp(_plurals), ""), true );
+ } else {
+ str = item->msgstr();
+ id = item->msgid();
+ }
+
+ //Check for translations that are too short or too long
+ //This may not be totally correct but we check both
+ //the singular and plural forms against each translated plural.
+ //FIXME: replace 10% check with configurable setting or a statistical
+ //based expected length relationship
+ int idlen, strlen;
+ for( QStringList::Iterator i = id.begin() ; i != id.end() ; i++ ) {
+ QString iditem = (*i);
+ idlen = iditem.replace( QRegExp(_context),"").length();
+ for( QStringList::Iterator j = str.begin() ; j != str.end() ; j++ ) {
+ QString stritem = (*j);
+ strlen = stritem.length();
+ hasError = hasError || (strlen < (0.1 * idlen))
+ || (strlen > (10 * idlen));
+ }
+ }
+
+ }
+
+ if(hasError)
+ item->appendError( "translation has inconsistant length" );
+ else
+ item->removeError( "translation has inconsistant length" );
+
+ return !hasError;
+ }
+ return false;
+}
+
+#include "main.moc"
diff --git a/kbabel/datatools/length/main.h b/kbabel/datatools/length/main.h
new file mode 100644
index 00000000..225c91ad
--- /dev/null
+++ b/kbabel/datatools/length/main.h
@@ -0,0 +1,54 @@
+/* This file is part of KBabel
+ based on Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ 2002 Stanislav Visnovsky <visnovsky@kde.org>
+ 2003 Dwayne Bailey <dwayne@translate.org.za>
+
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#ifndef __main_h__
+#define __main_h__
+
+#include "kbproject.h"
+
+#include <kdatatool.h>
+
+class LengthTool : public KDataTool
+{
+ Q_OBJECT
+
+public:
+ LengthTool( QObject* parent, const char* name, const QStringList & );
+ virtual bool run( const QString& command, void* data, const QString& datatype, const QString& mimetype);
+private:
+ KBabel::Project::Ptr _cache_origin;
+ QRegExp _context;
+ QRegExp _plurals;
+};
+
+#endif
diff --git a/kbabel/datatools/length/test.po b/kbabel/datatools/length/test.po
new file mode 100644
index 00000000..d1bb209d
--- /dev/null
+++ b/kbabel/datatools/length/test.po
@@ -0,0 +1,46 @@
+# Test file to validate the length checking tool
+# Dwayne Bailey <dwayne@translate.org.za>, 2003
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: test\n"
+"Last-Translator: Dwayne Bailey <dwayne@translate.org.za>\n"
+"PO-Revision-Date: 2003-01-09 09:35+0200\n"
+"Language-Team: <english@translate.org.za>\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.2\n"
+
+# msgstr < 10% of msgid
+# Expected Result = error
+msgid "Some translation string"
+msgstr "aa"
+
+# msgstr > 10 * length of msgid
+# Expected Result = error
+msgid "Short"
+msgstr "Very long translation of a very short string. "
+"This should be picked up. Not really sure what a more"
+" correct approach might be."
+
+# Shortness test with KDE plural forms
+# Expected Result = error
+msgid ""
+"_n: Some translation string\n"
+"Second form %n"
+msgstr ""
+"aa\n"
+"Second form %n transaltion"
+
+# SHortness test with GNU plural forms
+# Expected Result = error
+msgid "Some translation string"
+msgid_plural "The second form %n"
+msgstr[0] "aa"
+msgstr[1] "Second for %n"
+
+# Shortness test with KDE context info
+# Expected Result = error
+msgid "_: Translation comment\n"
+"Some translation string"
+msgstr "aa"
diff --git a/kbabel/datatools/not-translated/Makefile.am b/kbabel/datatools/not-translated/Makefile.am
new file mode 100644
index 00000000..7ae7fe1c
--- /dev/null
+++ b/kbabel/datatools/not-translated/Makefile.am
@@ -0,0 +1,19 @@
+
+INCLUDES = -I$(srcdir)/../../common -I../../common $(all_includes)
+kbabel_nottranslatedtool_la_LIBADD = $(LIB_KIO) ../../common/libkbabelcommon.la
+
+####### Files
+
+kde_module_LTLIBRARIES = kbabel_nottranslatedtool.la
+
+kbabel_nottranslatedtool_la_SOURCES = main.cc
+
+kbabel_nottranslatedtool_la_LDFLAGS = $(all_libraries) -avoid-version -module -no-undefined
+
+noinst_HEADERS = main.h
+
+kbabel_nottranslatedtool_la_METASOURCES = AUTO
+
+service_DATA = kbabel_nottranslatedtool.desktop
+servicedir = $(kde_servicesdir)
+
diff --git a/kbabel/datatools/not-translated/kbabel_nottranslatedtool.desktop b/kbabel/datatools/not-translated/kbabel_nottranslatedtool.desktop
new file mode 100644
index 00000000..e3c267bf
--- /dev/null
+++ b/kbabel/datatools/not-translated/kbabel_nottranslatedtool.desktop
@@ -0,0 +1,97 @@
+[Desktop Entry]
+Name=Check for Translated Strings Containing English for KBabel
+Name[bg]=Проверка за преведени низове, Ñъдържащи английÑки - KBabel
+Name[bs]=Provjera prevedenih stringova koji sadrže engleski za KBabel
+Name[ca]=Comprova per a KBabel les entrades traduïdes que contenen anglès
+Name[cs]=Vyhledat pÅ™eložené Å™etÄ›zce obsahující angliÄtinu
+Name[cy]=Gwirio am Linynnau wedi'u Cyfieithu sy'n Cynnwys Saesneg i KBabel
+Name[da]=Tjek for oversatte strenge der indeholder engelsk for KBabel
+Name[de]=Überprüfung übersetzter Texte, die Englisch enthalten, für KBabel
+Name[el]=Έλεγχος για μεταφÏασμένα κείμενα που πεÏιέχουν αγγλικά για το KBabel
+Name[es]=Comprobar cadenas traducidas con contenido en inglés para KBabel
+Name[et]=KBabeli inglise keelt sisaldavate tõlgitud teadete kontrollija
+Name[eu]=Bilatu ingeles hitzak itzulitako kateen artean KBabel-entzat
+Name[fa]=بررسی برای رشته‌های ترجمه‌شده حاوی انگلیسی برای KBabel
+Name[fi]=Englantia sisältävien merkkijonojen tarkistus KBabelissa
+Name[fr]=Vérifie si les chaînes traduites contiennent de l'anglais pour KBabel
+Name[gl]=Verificación de mensaxes traducidas que conteñan Inglés para KBabel
+Name[hu]=KBabel-eszköz angol nyelvű részek kereséséhez (a lefordított üzenetekben)
+Name[is]=Leita að þýddum strengjum sem innihalda ensku fyrir KBabel
+Name[it]=Controllo di stringhe tradotte contenenti inglese per KBabel
+Name[ja]=KBabel 翻訳文字列内ã®è‹±èªžã‚’検索
+Name[ka]=ინგლისურის შემცველი ნáƒáƒ—áƒáƒ áƒ’მნი სტრიქáƒáƒœáƒ”ბის შემáƒáƒ¬áƒ›áƒ”ბრKBabel-სთვის
+Name[kk]=KBabel аударылғанда ағылшын жазуы қалғанын текÑеруі
+Name[lt]=KBabel išverstų pranešimų, kuriuose yra anglų kalbos žodžių, patikra
+Name[nb]=Sjekk for oversatte strenger som inneholder engelsk i KBabel
+Name[nds]=Prööv op översett Texten mit Engelsch dor binnen för KBabel
+Name[ne]=केबà¥à¤¯à¤¾à¤¬à¤²à¤•à¤¾ लागि अनà¥à¤¬à¤¾à¤¦ गरिà¤à¤•à¤¾ अङà¥à¤—à¥à¤°à¥‡à¤œà¥€ समाविषà¥à¤Ÿ सà¥à¤Ÿà¥à¤°à¤¿à¤™à¤¹à¤°à¥‚को जाà¤à¤š
+Name[nl]=Controle op vertaalde tekst met Engelse termen voor KBabel
+Name[nn]=Sjekk for omsette strengar som inneheld engelsk i Kbabel
+Name[pl]=Sprawdzenie czy przetłumaczony komunikat zawiera angielskie słowa w KBabel
+Name[pt]=Verificação de Mensagens Traduzidas que Contenham Inglês para o KBabel
+Name[pt_BR]=Verifica por Strings Traduzidos Contendo Inglês para o KBabel
+Name[ru]=Проверка переведённых Ñтрок на равенÑтво оригинальным Ð´Ð»Ñ KBabel
+Name[sk]=Kontrola anglického textu v preklade pre KBabel
+Name[sl]=Preveri prevedene nize, ki vsebujejo angleÅ¡Äino; za KBabel
+Name[sr]=Провера за преведене низове знакова који Ñадрже енглеÑки за KBabel
+Name[sr@Latn]=Provera za prevedene nizove znakova koji sadrže engleski za KBabel
+Name[sv]=Kontrollera översatta strängar som innehåller engelska för Kbabel
+Name[ta]=கேபாபேலà¯à®•à¯à®•à®¾à®© ஆஙà¯à®•à®¿à®² மொழிபெயரà¯à®ªà¯à®ªà¯ சரஙà¯à®•à®³à¯ˆ சோதிகà¯à®•à®µà¯à®®à¯.
+Name[tg]=Тафтиши Ñатрҳои тарҷумашуда ба баробарии аÑлӣ барои KBabel
+Name[tr]=KBabel için İngilizce İhtiva Eden Çevrilen Dizgeler Denetimi
+Name[uk]=Перевірка перекладених фраз на вміÑÑ‚ англійÑької Ð´Ð»Ñ KBabel
+Name[zh_CN]=KBabel 检查已翻译字符串包å«è‹±è¯­çš„工具
+Name[zh_TW]=KBabel 的檢查包å«è‹±æ–‡çš„已翻譯字串
+ValidationString=whitespace checking
+X-KDE-Library=kbabel_nottranslatedtool
+Type=Service
+Commands=validate
+Comment=Translations Containing English
+Comment[bg]=Ðизове, Ñъдържащи английÑки
+Comment[bs]=Prijevodi koji sadrže engleski
+Comment[ca]=Traduccions que contenen l'anglès
+Comment[cs]=PÅ™eklady obsahující angliÄtinu
+Comment[cy]=Cyfieithiadau sy'n cynnwys Saesneg
+Comment[da]=Oversættelser der indeholder engelsk
+Comment[de]=Ãœbersetzungen melden, die englischen Text enthalten
+Comment[el]=ΜεταφÏάσεις που πεÏιέχουν αγγλικά
+Comment[es]=Traducciones con contenido en inglés
+Comment[et]=Inglise keelt sisaldavad tõlked
+Comment[eu]=Inglesa duten itzulpenak
+Comment[fa]=ترجمه‌های حاوی انگلیسی
+Comment[fi]=Käännös sisältää englantia
+Comment[fr]=Traductions contenant de l'anglais
+Comment[gl]=Traducións que conteñen Inglés
+Comment[he]=×ª×¨×’×•×ž×™× ×”×ž×›×™×œ×™× ×נגלית
+Comment[hi]=अंगà¥à¤°à¥‡à¤œà¤¼à¥€ यà¥à¤•à¥à¤¤ अनà¥à¤µà¤¾à¤¦
+Comment[hu]=Angol nyelvű részeket tartalmazó fordítások
+Comment[is]=Þýðingar sem innihalda ensku
+Comment[it]=Traduzioni contenenti inglese
+Comment[ja]=翻訳文字列内ã®è‹±èªžã‚’検索
+Comment[ka]=ინგლისურის შემცველი ნáƒáƒ—áƒáƒ áƒ’მნი
+Comment[kk]=Ðударылғанда ағылшын жазуы қалғанын текÑеру
+Comment[lt]=Vertimai, kuriuose yra anglų kalbos žodžių
+Comment[nb]=Oversettelser som inneholder engelsk
+Comment[nds]=Op Engelsch binnen Översetten pröven
+Comment[ne]=अङà¥à¤—à¥à¤°à¥‡à¤œà¥€ समाविषà¥à¤Ÿ अनà¥à¤¬à¤¾à¤¦
+Comment[nl]=Vertalingen die Engels bevatten controleren
+Comment[nn]=Omsetjingar som inneheld engelsk
+Comment[pa]=ਅੰਗਰੇਜ਼ੀ ਰੱਖਣ ਵਾਲੀ ਅਨà©à¨µà¨¾à¨¦
+Comment[pl]=Sprawdzenie czy przetłumaczony komunikat zawiera angielskie słowa
+Comment[pt]=Traduções Que Contêm Inglês
+Comment[pt_BR]=Traduções Contendo Inglês
+Comment[ru]=Переводы, Ñодержащие английÑкий
+Comment[sk]=Preklady obsahujúce angliÄtinu
+Comment[sl]=Prevodi, ki vsebujo angleÅ¡Äino
+Comment[sr]=Преводи који Ñадрже енглеÑки
+Comment[sr@Latn]=Prevodi koji sadrže engleski
+Comment[sv]=Översättningar som innehåller engelska
+Comment[ta]= ஆஙà¯à®•à®¿à®²à®¤à¯à®¤à®¿à®©à¯ மொழிபெயரà¯à®ªà¯à®ªà¯
+Comment[tg]=Тарҷумаҳое, ки англиÑÓ£ доранд
+Comment[tr]=İngilizce İhtiva eden Çeviriler
+Comment[uk]=Переклади, Ñкі міÑÑ‚ÑÑ‚ÑŒ англійÑьку
+Comment[zh_CN]=翻译包å«è‹±è¯­
+Comment[zh_TW]=包å«è‹±æ–‡çš„翻譯
+ServiceTypes=KDataTool,KBabelValidator
+DataType=CatalogItem
+DataMimeTypes=application/x-kbabel-catalogitem
diff --git a/kbabel/datatools/not-translated/main.cc b/kbabel/datatools/not-translated/main.cc
new file mode 100644
index 00000000..1a53db41
--- /dev/null
+++ b/kbabel/datatools/not-translated/main.cc
@@ -0,0 +1,129 @@
+/* This file is part of KBabel
+ based Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ 2002 Stanislav Visnovsky <visnovsky@kde.org>
+ 2003 Dwayne Bailey <dwayne@translate.org.za>
+
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#include <resources.h>
+#include "catalog.h"
+#include "catalogitem.h"
+#include "catalogsettings.h"
+#include "main.h"
+
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+/***************************************************
+ *
+ * Factory
+ *
+ ***************************************************/
+
+K_EXPORT_COMPONENT_FACTORY( kbabel_nottranslatedtool, KGenericFactory<NotTranslatedTool> ( "kbabeldatatool" ) )
+
+using namespace KBabel;
+
+NotTranslatedTool::NotTranslatedTool( QObject* parent, const char* name, const QStringList & )
+ : KDataTool( parent, name ) , _cache_origin( 0 )
+{
+ i18n("which check found errors","English text in translation");
+}
+
+bool NotTranslatedTool::run( const QString& command, void* data, const QString& datatype, const QString& mimetype )
+{
+
+ if ( command != "validate" )
+ {
+ kdDebug(KBABEL) << "Not Translated Tool only accepts the 'validate' command" << endl;
+ kdDebug(KBABEL) << " The command " << command << " is not accepted" << endl;
+ return false;
+ }
+
+ // Check wether we can accept the data
+ if ( datatype != "CatalogItem" )
+ {
+ kdDebug(KBABEL) << "Not Translated Tool only accept the CatalogItem datatype" << endl;
+ return false;
+ }
+
+ if ( mimetype != "application/x-kbabel-catalogitem" )
+ {
+ kdDebug(KBABEL) << "Not Translated Tool only accept the 'application/x-kbabel-catalogitem' mimetype" << endl;
+ return false;
+ }
+
+ if( command == "validate" )
+ {
+ CatalogItem* item = (CatalogItem*)(data);
+ bool hasError = false;
+
+ if(!item->isUntranslated()) {
+ if( _cache_origin != item->project() )
+ {
+ _context = item->project()->miscSettings().contextInfo;
+ _plurals = item->project()->miscSettings().singularPlural;
+ _cache_origin = item->project();
+ }
+
+ //FIXME Expand this to do substring matching of non-translation
+ QStringList id, str;
+ if( item->pluralForm() == KDESpecific ) {
+ str = QStringList::split( "\\n", item->msgstr().first(), true );
+ id = QStringList::split( "\\n",
+ item->msgid().first().replace( QRegExp(_plurals), ""), true );
+ } else {
+ str = item->msgstr();
+ id = item->msgid();
+ }
+ for( QStringList::Iterator i = id.begin() ; i != id.end() ; i++ ) {
+ QString id_str = (*i).replace( QRegExp(_context), "");
+ for( QStringList::Iterator j = str.begin() ; j != str.end() ; j++ ) {
+ QString str_str = (*j);
+ hasError = hasError || ( id_str == str_str );
+ }
+ }
+
+ }
+
+ if(hasError)
+ item->appendError( "english text in translation" );
+ else
+ item->removeError( "english text in translation" );
+
+ return !hasError;
+ }
+ return false;
+}
+
+#include "main.moc"
diff --git a/kbabel/datatools/not-translated/main.h b/kbabel/datatools/not-translated/main.h
new file mode 100644
index 00000000..7386c4d8
--- /dev/null
+++ b/kbabel/datatools/not-translated/main.h
@@ -0,0 +1,55 @@
+/* This file is part of KBabel
+ based on Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ 2002 Stanislav Visnovsky <visnovsky@kde.org>
+ 2003 Dwayne Bailey <dwayne@translate.org.za>
+
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#ifndef __main_h__
+#define __main_h__
+
+#include "kbproject.h"
+
+#include <kdatatool.h>
+
+class NotTranslatedTool : public KDataTool
+{
+ Q_OBJECT
+
+public:
+ NotTranslatedTool( QObject* parent, const char* name, const QStringList & );
+ virtual bool run( const QString& command, void* data, const QString& datatype, const QString& mimetype);
+
+private:
+ KBabel::Project::Ptr _cache_origin;
+ QRegExp _context;
+ QRegExp _plurals;
+};
+
+#endif
diff --git a/kbabel/datatools/not-translated/test.po b/kbabel/datatools/not-translated/test.po
new file mode 100644
index 00000000..5af47fc5
--- /dev/null
+++ b/kbabel/datatools/not-translated/test.po
@@ -0,0 +1,48 @@
+# translation of test.po to
+# Test file to validate the not-translted checking tool
+# Dwayne Bailey <dwayne@translate.org.za>, 2003
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: test-not-translated\n"
+"Last-Translator: Dwayne Bailey <dwayne@translate.org.za>\n"
+"PO-Revision-Date: 2003-01-09 09:35+0200\n"
+"Language-Team: <english@translate.org.za>\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.2\n"
+
+# msgid has not been translted but copied
+# Expected Result = error
+msgid "Same"
+msgstr "Same"
+
+# msgid has not been translted but copied
+# Expected Result = error
+msgid "Some translation string"
+msgstr "Some translation string"
+
+# msgstr contains a sentence that has not been translted
+# Expected Result = error
+msgid "The first sentence. A second sentence. Lastly a third."
+msgstr "Die eerste sin. A second sentence. Lastens 'n derde."
+
+# A same translation with context information
+# Expected Result = error
+msgid "_: Some context information\n"
+"Same"
+msgstr "Same"
+
+# A KDE plural form with the same translation
+# Expected Result == error
+msgid "_n: The first string\n"
+"The second string"
+msgstr "The first string\n"
+"The first string has not been translated"
+
+# A Gettext plural form with the same translation
+# Expected Result == error
+msgid "The first string"
+msgid_plural "The second string"
+msgstr[0] "The first string"
+msgstr[1] "The first string has not been translated"
diff --git a/kbabel/datatools/pluralforms/Makefile.am b/kbabel/datatools/pluralforms/Makefile.am
new file mode 100644
index 00000000..b7d50e80
--- /dev/null
+++ b/kbabel/datatools/pluralforms/Makefile.am
@@ -0,0 +1,19 @@
+
+INCLUDES = -I$(srcdir)/../../common -I../../common $(all_includes)
+kbabel_pluraltool_la_LIBADD = $(LIB_KIO) ../../common/libkbabelcommon.la
+
+####### Files
+
+kde_module_LTLIBRARIES = kbabel_pluraltool.la
+
+kbabel_pluraltool_la_SOURCES = main.cc
+
+kbabel_pluraltool_la_LDFLAGS = $(all_libraries) -avoid-version -module -no-undefined
+
+noinst_HEADERS = main.h
+
+kbabel_pluraltool_la_METASOURCES = AUTO
+
+service_DATA = kbabel_pluralformstool.desktop
+servicedir = $(kde_servicesdir)
+
diff --git a/kbabel/datatools/pluralforms/kbabel_pluralformstool.desktop b/kbabel/datatools/pluralforms/kbabel_pluralformstool.desktop
new file mode 100644
index 00000000..5d579994
--- /dev/null
+++ b/kbabel/datatools/pluralforms/kbabel_pluralformstool.desktop
@@ -0,0 +1,101 @@
+[Desktop Entry]
+Name=Plural Form Validation for KBabel
+Name[bg]=ВалидноÑÑ‚ на мн. форми - KBabel
+Name[bs]=Provjera formi množine za KBabel
+Name[ca]=Validació de les formes plurals per a KBabel
+Name[cs]=Validace množného Äísla
+Name[cy]=Dilysu Ffurf Lluosryw i KBabel
+Name[da]=Validering af flertalsformer for KBabel
+Name[de]=Pluralform-Überprüfung für KBabel
+Name[el]=Έλεγχος εγκυÏότητας φοÏμών Ï€Î»Î·Î¸Ï…Î½Ï„Î¹ÎºÎ¿Ï Î³Î¹Î± το KBabel
+Name[es]=Validación de formas plurales para KBabel
+Name[et]=KBabeli mitmusevormide kontrollija
+Name[eu]=Plural forma balidazioa KBabel-entzat
+Name[fa]=اعتبارسنجی شکل جمع برای KBabel
+Name[fi]=Monikkomuotojen tarkistus KBabelissa
+Name[fr]=Validation des formes plurielles pour KBabel
+Name[gl]=Validación de formas do plural para KBabel
+Name[hi]=के-बेबल के लिठबहà¥à¤µà¤šà¤¨ फारà¥à¤® वेलिडेशन
+Name[hu]=A többes szám ellenőrzése a KBabelben
+Name[is]=Staðfesting fleirtöluforma fyrir KBabel
+Name[it]=Convalida delle forme plurali per KBabel
+Name[ja]=KBabel 複数形検証
+Name[ka]=მრáƒáƒ•áƒšáƒáƒ‘ითი ფáƒáƒ áƒ›áƒ”ბის დáƒáƒ›áƒ›áƒáƒ¬áƒ›áƒ”ბელი KBabel-სთვის
+Name[kk]=KBabel-дың көптік жалғауын текÑеруі
+Name[lt]=KBabel daugiskaitos formų patikros įrankis
+Name[ms]=Pengesahan Bentuk Jama' untuk KBabel
+Name[nb]=Sjekk flertallsformer i KBabel
+Name[nds]=Pluralformprööv för KBabel
+Name[ne]=केबà¥à¤¯à¤¾à¤¬à¤²à¤•à¤¾ लागि बहà¥à¤¬à¤šà¤¨ पà¥à¤°à¤®à¤¾à¤£à¥€à¤•à¤°à¤£
+Name[nl]=Meervoudsvormenvalidatie voor KBabel
+Name[nn]=Sjekk fleirtalsformer i KBabel
+Name[pl]=Sprawdzenie form liczby mnogiej w KBabel
+Name[pt]=Validação de Formas Plurais para o KBabel
+Name[pt_BR]=Validação de Formas Plurais para o KBabel
+Name[ru]=Проверка множеÑтвенных форм Ð´Ð»Ñ KBabel
+Name[sk]=Kontrola množných Äísel pre KBabel
+Name[sl]=Potrjevalnik množinskih oblik za KBabel
+Name[sr]=Овера облика множине за KBabel
+Name[sr@Latn]=Overa oblika množine za KBabel
+Name[sv]=Validering av pluralformer för Kbabel
+Name[ta]= Kபாபேலலà¯à®•à¯à®•à¯ தரà¯à®®à®¤à®¿à®ªà¯à®ªà¯ பனà¯à®®à¯ˆ வடிவமà¯
+Name[tg]=Тафтиши шаклҳои биÑÑ‘Ñ€ барои KBabel
+Name[tr]=KBabel için Çoklu Form Denetimi
+Name[uk]=Перевірка форм множини Ð´Ð»Ñ KBabel
+Name[zh_CN]=KBabel çš„å¤æ•°å½¢å¼æ£€æŸ¥å™¨
+Name[zh_TW]=KBabel 的單複數型檢查器
+ValidationString=plural forms
+X-KDE-Library=kbabel_pluraltool
+Type=Service
+Commands=validate
+Comment=Check Plural Forms
+Comment[bg]=Проверка на мн. форми
+Comment[bs]=Provjeri forme množine
+Comment[ca]=Comprova les formes plurals
+Comment[cs]=Zkontrolovat množné Äíslo
+Comment[cy]=Gwirio Ffurfiau Lluosryw
+Comment[da]=Tjek flertalsformer
+Comment[de]=Überprüfung von Plural-Formen
+Comment[el]=Έλεγχος φοÏμών πληθυντικοÏ
+Comment[es]=Comprobar formas plurales
+Comment[et]=Mitmuse vormide kontroll
+Comment[eu]=Egiaztatu plural formak
+Comment[fa]=بررسی شکلهای جمع
+Comment[fi]=Tarkista monikkomuodot
+Comment[fr]=Vérifie les formes plurielles
+Comment[gl]=Verificación de formas plurais
+Comment[he]=בודק מצבי רבי×
+Comment[hi]=बहà¥à¤µà¤šà¤¨ जाà¤à¤šà¥‡à¤‚
+Comment[hu]=A többes számú alakok ellenőrzése
+Comment[is]=Athuga fleirtöluform
+Comment[it]=Controlla forme plurali
+Comment[ja]=複数形を検証
+Comment[ka]=მრáƒáƒ•áƒšáƒáƒ‘ითი ფáƒáƒ áƒ›áƒ”ბის შემáƒáƒ¬áƒ›áƒ”ბáƒ
+Comment[kk]=Көптік жалғауын текÑеру
+Comment[lt]=Tikrinti daugiskaitos formas
+Comment[ms]=Periksa Bentuk Jama'
+Comment[nb]=Sjekk flertallsformer
+Comment[nds]=Pluralformen pröven
+Comment[ne]=बहà¥à¤¬à¤šà¤¨ जाà¤à¤š गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥
+Comment[nl]=Meervoudsvormen controleren
+Comment[nn]=Sjekk fleirtalsformer
+Comment[pa]=ਬਹà©-ਵਚਨ ਫਾਰਮ ਜਾਂਚ
+Comment[pl]=Sprawdzenie form liczby mnogiej
+Comment[pt]=Verificação de Formas Plurais
+Comment[pt_BR]=Verifica Formas Plurais
+Comment[ru]=Проверить множеÑтвенные формы
+Comment[sk]=Kontrola množných Äísel
+Comment[sl]=Preveri množinske oblike
+Comment[sr]=Провери облике множине
+Comment[sr@Latn]=Proveri oblike množine
+Comment[sv]=Kontrollera pluralformer
+Comment[ta]= சரிபாரà¯à®ªà¯à®ªà¯
+Comment[tg]=Тафтиш кардани шаклҳои биÑÑ‘Ñ€
+Comment[tr]=Çoklu Formları denetle
+Comment[uk]=Перевірити форми множини
+Comment[zh_CN]=检查å¤æ•°å½¢å¼
+Comment[zh_TW]=檢查單複數型
+ServiceTypes=KDataTool,KBabelValidator
+DataType=CatalogItem
+DataMimeTypes=application/x-kbabel-catalogitem
+ReadOnly=true
diff --git a/kbabel/datatools/pluralforms/main.cc b/kbabel/datatools/pluralforms/main.cc
new file mode 100644
index 00000000..a534df6e
--- /dev/null
+++ b/kbabel/datatools/pluralforms/main.cc
@@ -0,0 +1,129 @@
+/* This file is part of KBabel
+ based Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ 2002 Stanislav Visnovsky <visnovsky@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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#include <resources.h>
+#include "catalog.h"
+#include "catalogitem.h"
+#include "catalogsettings.h"
+#include "main.h"
+
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+/***************************************************
+ *
+ * Factory
+ *
+ ***************************************************/
+
+K_EXPORT_COMPONENT_FACTORY( kbabel_pluraltool, KGenericFactory<PluralsTool> ( "kbabeldatatool" ) )
+
+using namespace KBabel;
+
+PluralsTool::PluralsTool( QObject* parent, const char* name, const QStringList & )
+ : KDataTool( parent, name ), _cache_origin( 0 ), _neededForms(-1)
+{
+ i18n("what check found errors", "plural forms");
+}
+
+bool PluralsTool::run( const QString& command, void* data, const QString& datatype, const QString& mimetype )
+{
+ if ( command != "validate" )
+ {
+ kdDebug(KBABEL) << "Plural Forms Tool does only accept the command 'validate' and 'shortcut'" << endl;
+ kdDebug(KBABEL) << " The commands " << command << " is not accepted" << endl;
+ return FALSE;
+ }
+
+ // Check wether we can accept the data
+ if ( datatype != "CatalogItem" )
+ {
+ kdDebug(KBABEL) << "Plural Forms Tool only accepts datatype CatalogItem" << endl;
+ return FALSE;
+ }
+
+ if ( mimetype != "application/x-kbabel-catalogitem" )
+ {
+ kdDebug(KBABEL) << "Plural Forms Tool only accepts mimetype application/x-kbabel-catalogitem" << endl;
+ return FALSE;
+ }
+
+ if( command == "validate" )
+ {
+ if( _neededForms < 0 )
+ {
+ Catalog* cat = new Catalog(this);
+ _neededForms = cat->defaultNumberOfPluralForms();
+ delete cat;
+ }
+
+ CatalogItem* item = (CatalogItem*)(data);
+
+ if( _cache_origin != item->project() )
+ {
+ _plurals = item->project()->miscSettings().singularPlural;
+ _cache_origin = item->project();
+ }
+
+ bool hasError = false;
+
+ if(!item->isUntranslated() && item->pluralForm() == KDESpecific )
+ {
+ if(_neededForms <= 0 || item->msgstr().first().contains(_plurals))
+ {
+ hasError = true;
+ }
+ else if( item->msgstr().first().contains(QString("\\n"))+1 != _neededForms )
+ {
+ hasError = true;
+ }
+ }
+
+ if(hasError)
+ {
+ item->appendError( "plural forms" );
+ }
+ else
+ {
+ item->removeError( "plural forms" );
+ }
+
+ return !hasError;
+ }
+ return FALSE;
+}
+
+#include "main.moc"
diff --git a/kbabel/datatools/pluralforms/main.h b/kbabel/datatools/pluralforms/main.h
new file mode 100644
index 00000000..1537f38f
--- /dev/null
+++ b/kbabel/datatools/pluralforms/main.h
@@ -0,0 +1,53 @@
+/* This file is part of KBabel
+ based on Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ 2002 Stanislav Visnovsky <visnovsky@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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#ifndef __main_h__
+#define __main_h__
+
+#include "kbproject.h"
+
+#include <kdatatool.h>
+
+class PluralsTool : public KDataTool
+{
+ Q_OBJECT
+
+public:
+ PluralsTool( QObject* parent, const char* name, const QStringList & );
+ virtual bool run( const QString& command, void* data, const QString& datatype, const QString& mimetype);
+private:
+ KBabel::Project::Ptr _cache_origin;
+ QRegExp _plurals;
+ int _neededForms;
+};
+
+#endif
diff --git a/kbabel/datatools/punctuation/Makefile.am b/kbabel/datatools/punctuation/Makefile.am
new file mode 100644
index 00000000..5f00234c
--- /dev/null
+++ b/kbabel/datatools/punctuation/Makefile.am
@@ -0,0 +1,19 @@
+
+INCLUDES = -I$(srcdir)/../../common -I../../common $(all_includes)
+kbabel_punctuationtool_la_LIBADD = $(LIB_KIO) ../../common/libkbabelcommon.la
+
+####### Files
+
+kde_module_LTLIBRARIES = kbabel_punctuationtool.la
+
+kbabel_punctuationtool_la_SOURCES = main.cc
+
+kbabel_punctuationtool_la_LDFLAGS = $(all_libraries) -avoid-version -module -no-undefined
+
+noinst_HEADERS = main.h
+
+kbabel_punctuationtool_la_METASOURCES = AUTO
+
+service_DATA = kbabel_punctuationtool.desktop
+servicedir = $(kde_servicesdir)
+
diff --git a/kbabel/datatools/punctuation/kbabel_punctuationtool.desktop b/kbabel/datatools/punctuation/kbabel_punctuationtool.desktop
new file mode 100644
index 00000000..c24ff52e
--- /dev/null
+++ b/kbabel/datatools/punctuation/kbabel_punctuationtool.desktop
@@ -0,0 +1,101 @@
+[Desktop Entry]
+Name=Punctuation Validation for KBabel
+Name[bg]=ВалидноÑÑ‚ на препинателните знаци - KBabel
+Name[bs]=Provjera znakova interpunkcije za KBabel
+Name[ca]=Validació de la puntuació per a KBabel
+Name[cs]=Validace interpunkce
+Name[cy]=Dilysiant Hafaliad i KBabel
+Name[da]=Godkendelse af tegnsætning i KBabel
+Name[de]=Interpunktions-Überprüfung für KBabel
+Name[el]=Έλεγχος εγκυÏότητας στίξης για το KBabel
+Name[es]=Validación de puntuación para KBabel
+Name[et]=KBabeli kirjavahemärkide kontrollija
+Name[eu]=Puntuazio balidazioa KBabel-entzat
+Name[fa]=اعتبارسنجی نقطه‌گذاری برای KBabel
+Name[fi]=Välimerkkien tarkistus KBabelissa
+Name[fr]=Validation de ponctuation pour KBabel
+Name[ga]=Bailíochtú na Poncaíochta le haghaidh KBabel
+Name[gl]=Validación da puntuación para KBabel
+Name[hi]=के-बेबल के लिठविरामचिहà¥à¤¨ वेलिडेशन
+Name[hu]=ÃrásjelellenÅ‘rzÅ‘ a KBabelhez
+Name[is]=Staðfesting greinamerkja fyrir KBabel
+Name[it]=Convalida della punteggiatura per KBabel
+Name[ja]=KBabel å¥èª­ç‚¹æ¤œè¨¼
+Name[ka]=პუნქტუáƒáƒªáƒ˜áƒ˜áƒ¡ დáƒáƒ›áƒ›áƒáƒ¬áƒ›áƒ”ბელი KBabel-სთვის
+Name[kk]=KBabel-дың Ñ‚Ñ‹Ð½Ñ‹Ñ Ð±ÐµÐ»Ð³Ñ–Ð»ÐµÑ€Ñ–Ð½ текÑеруі
+Name[lt]=KBabel skyrybos patikros įrankis
+Name[nb]=Sjekk tegnsetting i KBabel
+Name[nds]=Interpunkschoonprööv för KBabel
+Name[ne]=केबà¥à¤¯à¤¾à¤¬à¤²à¤•à¤¾ लागि बिराम चिनà¥à¤¹ पà¥à¤°à¤®à¤¾à¤£à¥€à¤•à¤°à¤£
+Name[nl]=Punctuatievalidatie voor KBabel
+Name[nn]=Sjekk teiknsetjing i KBabel
+Name[pl]=Sprawdzenie interpunkcji w KBabel
+Name[pt]=Validação de Pontuação para o KBabel
+Name[pt_BR]=Validação de Pontuação para o KBabel
+Name[ru]=Проверка пунктуации Ð´Ð»Ñ KBabel
+Name[sk]=Kontrola interpunkcie pre KBabel
+Name[sl]=Potrjevalnik loÄil za KBabel
+Name[sr]=Овера интерпункције за KBabel
+Name[sr@Latn]=Overa interpunkcije za KBabel
+Name[sv]=Validering av skiljetecken för Kbabel
+Name[ta]= Kபாபேலà¯à®•à¯à®•à¯ தரà¯à®®à®¤à®¿à®ªà¯à®ªà¯ கà¯à®±à®¿à®•à®³à¯
+Name[tg]=Тафтиши пунктуатÑÐ¸Ñ Ð±Ð°Ñ€Ð¾Ð¸ KBabel
+Name[tr]=KBabel için Noktalama denetimi
+Name[uk]=Перевірка пунктуації Ð´Ð»Ñ KBabel
+Name[zh_CN]=KBabel 的标点检查器
+Name[zh_TW]=KBabel 的標點檢查器
+ValidationString=accelerator
+X-KDE-Library=kbabel_punctuationtool
+Type=Service
+Commands=validate
+Comment=Check Punctuation
+Comment[bg]=Проверка на препинателните знаци
+Comment[bs]=Provjeri interpunkciju
+Comment[ca]=Comprova la puntuació
+Comment[cs]=Zkontrolovat interpunkci
+Comment[cy]=Gwirio Hafaliadau
+Comment[da]=Tjek tegnsætning
+Comment[de]=Prüfung der Interpunktion in Übersetzungen
+Comment[el]=Έλεγχος στίξης
+Comment[es]=Comprobar puntuación
+Comment[et]=Kirjavahemärkide kontroll
+Comment[eu]=Egiaztatu puntuazioa
+Comment[fa]=بررسی نقطه‌سنجی
+Comment[fi]=Tarkista välimerkit
+Comment[fr]=Vérifie la ponctuation
+Comment[ga]=Seiceáil Poncaíocht
+Comment[gl]=Verifica a puntuación
+Comment[he]=בודק ניקוד
+Comment[hi]=विरामचिहà¥à¤¨ जांच करें
+Comment[hu]=Az írásjelek ellenőrzése
+Comment[is]=Athuga greinamerki
+Comment[it]=Controlla punteggiatura
+Comment[ja]=å¥èª­ç‚¹ã‚’検証
+Comment[ka]=პუნქტუáƒáƒªáƒ˜áƒ˜áƒ¡ შემáƒáƒ¬áƒ›áƒ”ბáƒ
+Comment[kk]=Ð¢Ñ‹Ð½Ñ‹Ñ Ð±ÐµÐ»Ð³Ñ–Ð»ÐµÑ€Ñ–Ð½ текÑеру
+Comment[lt]=Tikrinti skyrybÄ…
+Comment[nb]=Sjekk tegnsetting
+Comment[nds]=Interpunkschoon pröven
+Comment[ne]=बिराम चिनà¥à¤¹ जाà¤à¤š गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥
+Comment[nl]=Punctuatie controleren
+Comment[nn]=Sjekk teiknsetjing
+Comment[pl]=Sprawdzenie interpunkcji
+Comment[pt]=Verifica a pontuação
+Comment[pt_BR]=Verifica Pontuação
+Comment[ru]=Проверить пунктуацию
+Comment[sk]=Kontrola interpunkcie
+Comment[sl]=Preveri loÄila
+Comment[sr]=Провери интерпункцију
+Comment[sr@Latn]=Proveri interpunkciju
+Comment[sv]=Kontrollera skiljetecken
+Comment[ta]= நிறà¯à®¤à¯à®¤à®•à¯à®•à¯à®±à®¿à®¯à®¿à®Ÿà¯à®¤à®²à¯ சரிபாரà¯à®ªà¯à®ªà¯
+Comment[tg]=Тафтиш кардани пунктуатÑиÑ
+Comment[tr]=Noktalama Denetimi
+Comment[uk]=Перевірити пунктуацію
+Comment[zh_CN]=检查标点
+Comment[zh_TW]=檢查標點
+Shortcuts=Ctrl+P
+ServiceTypes=KBabelValidator,KDataTool
+DataType=CatalogItem
+DataMimeTypes=application/x-kbabel-catalogitem
+ReadOnly=true
diff --git a/kbabel/datatools/punctuation/main.cc b/kbabel/datatools/punctuation/main.cc
new file mode 100644
index 00000000..bd4f4107
--- /dev/null
+++ b/kbabel/datatools/punctuation/main.cc
@@ -0,0 +1,157 @@
+/* This file is part of KBabel
+ based Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ 2003 Stanislav Visnovsky <visnovsky@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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#include <resources.h>
+#include "catalogitem.h"
+#include "catalogsettings.h"
+#include "main.h"
+
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <klocale.h>
+
+/***************************************************
+ *
+ * Factory
+ *
+ ***************************************************/
+
+K_EXPORT_COMPONENT_FACTORY( kbabel_punctuationtool, KGenericFactory<PunctuationTool> ( "kbabeldatatool" ) )
+
+using namespace KBabel;
+
+PunctuationTool::PunctuationTool( QObject* parent, const char* name, const QStringList & )
+ : KDataTool( parent, name )
+{
+ // bogus translation just for allowing the translation
+ i18n("what check found errors","punctuation");
+}
+
+bool PunctuationTool::run( const QString& command, void* data, const QString& datatype, const QString& mimetype )
+{
+ if ( command != "validate" )
+ {
+ kdDebug(KBABEL) << "Punctuation Tool does only accept the command 'validate'" << endl;
+ kdDebug(KBABEL) << " The commands " << command << " is not accepted" << endl;
+ return FALSE;
+ }
+
+ // Check wether we can accept the data
+ if ( datatype != "CatalogItem" )
+ {
+ kdDebug(KBABEL) << "Punctuation Tool only accepts datatype CatalogItem" << endl;
+ return FALSE;
+ }
+
+ if ( mimetype != "application/x-kbabel-catalogitem" )
+ {
+ kdDebug(KBABEL) << "Punctuation Tool only accepts mimetype application/x-kbabel-catalogitem" << endl;
+ return FALSE;
+ }
+
+ if( command == "validate" )
+ {
+ CatalogItem* item = (CatalogItem*)(data);
+
+ bool hasError = false;
+
+ if(!item->isUntranslated())
+ {
+ QString lineid=item->msgid().first();
+
+ // lookup punctuation in original text
+ QRegExp punc("[\\.!\\?:]+$");
+ int i = lineid.find(punc);
+
+ QString t("");
+
+ if( i != -1 ) t = lineid.right(lineid.length()-i);
+
+ if( item->pluralForm() != NoPluralForm )
+ {
+ // check, that both plural forms contain the same punctuation
+ QString pl = *(item->msgid().at(1));
+ int j = pl.find(punc);
+
+ QString tp("");
+ if( j != -1 ) tp = pl.right(pl.length()-j);
+
+ if( tp != t )
+ {
+ kdWarning() << "Singular and plural form do not have the same punctuation" << endl;
+ }
+ }
+
+ QStringList forms = item->msgstr(true);
+ if( item->pluralForm() == KDESpecific ) {
+ forms = QStringList::split("\\n",*item->msgstr(true).at(0));
+ }
+
+ for( QStringList::Iterator form = forms.begin() ; form != forms.end(); form++ )
+ {
+ QString linestr=(*form);
+
+ int j = linestr.find(punc);
+
+ // there is no punctuation in original, but one in the translation
+ if( i == -1 && j != i )
+ {
+ hasError = true;
+ break;
+ }
+
+ // there is punctuation in original, but not same as in the translation
+ if( i != -1 && linestr.right(linestr.length()-j) != t )
+ {
+ hasError = true;
+ break;
+ }
+ }
+ }
+
+ if(hasError)
+ {
+ item->appendError( "punctuation" );
+ }
+ else
+ {
+ item->removeError( "punctuation" );
+ }
+
+ return !hasError;
+ }
+ return FALSE;
+}
+
+#include "main.moc"
diff --git a/kbabel/datatools/punctuation/main.h b/kbabel/datatools/punctuation/main.h
new file mode 100644
index 00000000..c0c68518
--- /dev/null
+++ b/kbabel/datatools/punctuation/main.h
@@ -0,0 +1,47 @@
+/* This file is part of KBabel
+ based on Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ 2003 Stanislav Visnovsky <visnovsky@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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#ifndef __main_h__
+#define __main_h__
+
+#include <kdatatool.h>
+
+class PunctuationTool : public KDataTool
+{
+ Q_OBJECT
+
+public:
+ PunctuationTool( QObject* parent, const char* name, const QStringList & );
+ virtual bool run( const QString& command, void* data, const QString& datatype, const QString& mimetype);
+};
+
+#endif
diff --git a/kbabel/datatools/regexp/Makefile.am b/kbabel/datatools/regexp/Makefile.am
new file mode 100644
index 00000000..e727ca25
--- /dev/null
+++ b/kbabel/datatools/regexp/Makefile.am
@@ -0,0 +1,21 @@
+
+INCLUDES = -I$(srcdir)/../../common -I../../common $(all_includes)
+kbabel_regexptool_la_LIBADD = $(LIB_KIO) ../../common/libkbabelcommon.la
+
+####### Files
+
+kde_module_LTLIBRARIES = kbabel_regexptool.la
+
+kbabel_regexptool_la_SOURCES = main.cc
+
+kbabel_regexptool_la_LDFLAGS = $(all_libraries) -avoid-version -module -no-undefined
+
+noinst_HEADERS = main.h
+
+kbabel_regexptool_la_METASOURCES = AUTO
+
+service_DATA = kbabel_regexptool.desktop
+servicedir = $(kde_servicesdir)
+
+regexp_DATA = regexplist.xml
+regexpdir = $(kde_datadir)/kbabel
diff --git a/kbabel/datatools/regexp/kbabel_regexptool.desktop b/kbabel/datatools/regexp/kbabel_regexptool.desktop
new file mode 100644
index 00000000..dbd84491
--- /dev/null
+++ b/kbabel/datatools/regexp/kbabel_regexptool.desktop
@@ -0,0 +1,92 @@
+[Desktop Entry]
+Name=Catalan Grammar
+Name[br]=Yezhadur gatalaneg
+Name[ca]=Gramàtica catalana
+Name[cs]=Katalánská gramatika
+Name[da]=Katalansk grammatik
+Name[de]=Katalanische Grammatik
+Name[el]=ΓÏαμματική καταλανικών
+Name[eo]=Kataluna Gramatiko
+Name[es]=Gramática catalana
+Name[et]=Katalaani grammatika
+Name[eu]=Katalanaren gramatika
+Name[fa]=دستور زبان کاتالان
+Name[fi]=Katalaanin kielioppi
+Name[fr]=Grammaire du catalan
+Name[ga]=Gramadach na Catalóinise
+Name[gl]=Gramática catalá
+Name[he]=תחברי קט×לני
+Name[hu]=Katalán nyelvtan
+Name[is]=Katalónsk málfræði
+Name[it]=Grammatica catalana
+Name[ja]=カタロニア文節
+Name[ka]=კáƒáƒ¢áƒáƒšáƒáƒœáƒ£áƒ áƒ˜ გრáƒáƒ›áƒáƒ¢áƒ˜áƒ™áƒ
+Name[kk]=Каталон грамматикаÑÑ‹
+Name[lt]=Katalonų gramatika
+Name[nb]=Katalansk grammatikk
+Name[nds]=Katalaansch Grammatik
+Name[ne]=कà¥à¤¯à¤¾à¤Ÿà¤¾à¤²à¤¾à¤¨ बà¥à¤¯à¤¾à¤•à¤°à¤£
+Name[nl]=Catalaanse grammatica
+Name[nn]=Katalansk grammatikk
+Name[pa]=ਕਾਟਾਲਾਨ ਗਰਾਮਰ
+Name[pl]=Gramatyka katalońska
+Name[pt]=Gramática Catalã
+Name[pt_BR]=Gramática Catalã
+Name[ru]=КаталонÑÐºÐ°Ñ Ð³Ð°Ð¼Ð¼Ð°Ñ‚Ð¸ÐºÐ°
+Name[sk]=Katalánska gramatika
+Name[sl]=katalonska slovnica
+Name[sr]=КаталонијÑка граматика
+Name[sr@Latn]=Katalonijska gramatika
+Name[sv]=Katalansk grammatik
+Name[tr]=Katalan Dil Bilgisi
+Name[uk]=КаталонÑька граматика
+Name[zh_CN]=Catalan 语法
+Name[zh_TW]=Catalan 文法
+ValidationString=external script checking
+X-KDE-Library=kbabel_regexptool
+Type=Service
+Commands=validate
+Comment=Check Translated Messages with a set of Regular Expressions
+Comment[bg]=Проверка на преведените ÑÑŠÐ¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ñ Ñ€ÐµÐ³ÑƒÐ»Ñрни изрази
+Comment[ca]=Comprova els missatges traduïts amb un conjunt d'expressions regulars
+Comment[cs]=Zkontrolovat přeložené zprávy pomocí sady reg. výrazů
+Comment[da]=Tjek oversat besked med et sæt regulære udtryk
+Comment[de]=Überprüfung übersetzter Meldungen mit einem Satz regulärer Ausdrücke
+Comment[el]=Έλεγχος μεταφÏασμένων μηνυμάτων με ένα σÏνολο κανονικών εκφÏάσεων
+Comment[eo]=Kontroli tradukitajn mesaÄojn per aro da regulesprimoj
+Comment[es]=Comprobar mensajes traducidos mediante un juego de expresiones regulares
+Comment[et]=Tõlgitud teate kontroll regulaaravaldistega
+Comment[eu]=Egiaztatu itzulitako mezuak espresio erregular sorta batekin
+Comment[fa]=بررسی پیامهای ترجمه‌شده توسط مجموعه‌ای از عبارتهای منظم
+Comment[fi]=Tarkista käännetyt viestit säännöllisten lausekkeiden avulla
+Comment[fr]=Vérifie les messages traduits avec un jeu d'expressions rationnelles
+Comment[gl]=Verificación das mensaxes traducidas cun conxunto de expresións regulares
+Comment[hu]=A lefordított üzenetek ellenőrzése reguláris kifejezésekkel
+Comment[is]=Athuga þýdd skilaboð með reglulegum segðum
+Comment[it]=Controlla i messaggi tradotti con un insieme di espressioni regolari
+Comment[ja]=æ­£è¦è¡¨ç¾ã‚’用ã„ã¦ç¿»è¨³ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’検証
+Comment[ka]=რეგულáƒáƒ áƒ£áƒšáƒ˜ გáƒáƒ›áƒáƒ¡áƒáƒ®áƒ£áƒšáƒ”ბების შეცველი ნáƒáƒ—áƒáƒ áƒ’მნი შეტყáƒáƒ‘ინებების შემáƒáƒ¬áƒ›áƒ”ბáƒ
+Comment[kk]=Ðударылған жазуларды үлгі өрнегімен текÑеру
+Comment[lt]=Tikrinti išverstus pranešimus panaudojant įprastųjų išraiškų rinkinį
+Comment[nb]=Sjekk oversatte strenger med et sett regulære uttrykk
+Comment[nds]=Översett Mellen mit en Sett vun regulere Utdrück pröven
+Comment[ne]=नियमित अभिवà¥à¤¯à¤•à¥à¤¤à¤¿à¤•à¤¾ सेट भà¤à¤•à¤¾ अनà¥à¤¬à¤¾à¤¦ गरिà¤à¤•à¤¾ सनà¥à¤¦à¥‡à¤¶à¤•à¥‹ जाà¤à¤š गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥
+Comment[nl]=Vertaalde tekst controleren met behulp van reguliere expressies
+Comment[nn]=Sjekk omsette strengar med eit sett regulære uttrykk
+Comment[pl]=Sprawdzenie przetłumaczonych komunikatów za pomocą zestawu wyrażeń regularnych
+Comment[pt]=Verificação das Mensagens Traduzidas com um Conjunto de Expressões Regulares
+Comment[pt_BR]=Verificação das Mensagens Traduzidas com um Conjunto de Expressões Regulares
+Comment[ru]=Проверить переведенных ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¿Ð¾ регулÑрному выражению
+Comment[sk]=Kontrola preložených textov pomocou sady regulárnych výrazov
+Comment[sl]=Preveri prevedena sporoÄila z naborom regularnih izrazov
+Comment[sr]=Провери преведене поруке Ñкупом регуларних израза
+Comment[sr@Latn]=Proveri prevedene poruke skupom regularnih izraza
+Comment[sv]=Kontrollera översatta meddelanden med en uppsättning reguljära uttryck
+Comment[tr]=Bir Düzgün Anlatım grubu ile birlikte çevrilen mesajları denetle
+Comment[uk]=Перевірити перекладені фрази за допомогою набору формальних виразів
+Comment[zh_CN]=用一组正则表达å¼æ£€æŸ¥å·²ç¿»è¯‘消æ¯
+Comment[zh_TW]=利用正è¦è¡¨ç¤ºå¼æª¢æŸ¥å·²ç¿»è­¯è¨Šæ¯
+ServiceTypes=KDataTool,KBabelValidator
+DataType=CatalogItem
+DataMimeTypes=application/x-kbabel-catalogitem
+ReadOnly=true
diff --git a/kbabel/datatools/regexp/main.cc b/kbabel/datatools/regexp/main.cc
new file mode 100644
index 00000000..4464170d
--- /dev/null
+++ b/kbabel/datatools/regexp/main.cc
@@ -0,0 +1,181 @@
+/* Copyright (C) 2005 Albert Cervera i Areny <albertca at hotpop dot com>
+
+ Based on Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ 2002 Stanislav Visnovsky <visnovsky@kde.org>
+ 2003 Dwayne Bailey <dwayne@translate.org.za>
+
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <resources.h>
+#include "catalog.h"
+#include "catalogitem.h"
+#include "catalogsettings.h"
+#include "main.h"
+#include <math.h>
+
+#include <qdir.h>
+#include <qfile.h>
+#include <qdom.h>
+#include <qstringlist.h>
+#include <qregexp.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+/***************************************************
+ *
+ * Factory
+ *
+ ***************************************************/
+
+K_EXPORT_COMPONENT_FACTORY( kbabel_regexptool, KGenericFactory<RegExpTool> ( "kbabeldatatool" ) )
+
+using namespace KBabel;
+
+RegExpTool::RegExpTool( QObject* parent, const char* name, const QStringList & )
+ : KDataTool( parent, name )
+{
+ i18n("which check found errors","translation has inconsistent length");
+ loadExpressions();
+ if ( ! _error.isNull() )
+ KMessageBox::error( (QWidget*)parent, i18n( "Error loading data (%1)" ).arg( _error ) );
+}
+
+bool RegExpTool::run( const QString& command, void* data, const QString& datatype, const QString& mimetype )
+{
+ if ( command != "validate" )
+ {
+ kdDebug(KBABEL) << "RegExpTool only accepts the 'validate' command" << endl;
+ kdDebug(KBABEL) << " The command " << command << " is not accepted" << endl;
+ return false;
+ }
+ // Check wether we can accept the data
+ if ( datatype != "CatalogItem" )
+ {
+ kdDebug(KBABEL) << "RegExpTool only accepts the CatalogItem datatype" << endl;
+ return false;
+ }
+ if ( mimetype != "application/x-kbabel-catalogitem" )
+ {
+ kdDebug(KBABEL) << "RegExpTool only accepts the 'application/x-kbabel-catalogitem' mimetype" << endl;
+ return false;
+ }
+
+ bool hasError = false;
+ if( command == "validate" )
+ {
+ CatalogItem* item = (CatalogItem*)(data);
+
+ if(!item->isUntranslated()) {
+ ExpressionList::Iterator it( _list.begin() );
+ ExpressionList::Iterator end( _list.end() );
+ QStringList msgs = item->msgstr();
+ QStringList results;
+ for ( ; it != end; ++it ) {
+ results.clear();
+ results = msgs.grep( (*it).regExp() );
+ if ( results.size() > 0 ) {
+ hasError = true;
+ break;
+ }
+ }
+ }
+ if(hasError) {
+ item->appendError( "regexp" );
+ } else {
+ item->removeError( "regexp" );
+ }
+ }
+ return !hasError;
+}
+
+
+void RegExpTool::loadExpressions()
+{
+ // TODO: Change file path
+ QFile file( QDir::homeDirPath() + "/.kde/share/apps/kbabel/regexplist.xml" );
+ QDomDocument doc;
+
+ if ( ! file.open( IO_ReadOnly ) ) {
+ kdDebug() << "File not found" << endl;
+ _error = i18n( "File not found" );
+ return;
+ }
+ if ( ! doc.setContent( &file ) ) {
+ kdDebug() << "Could not set content of xml file" << endl;
+ _error = i18n( "The file is not a XML" );
+ return;
+ }
+ file.close();
+
+ QDomElement docElem = doc.documentElement();
+ QDomNode n = docElem.firstChild();
+ while( !n.isNull() ) {
+ QDomElement e = n.toElement();
+ if( !e.isNull() )
+ elementToExpression( e );
+ if ( ! _error.isNull() )
+ break;
+ n = n.nextSibling();
+ }
+}
+
+void RegExpTool::elementToExpression( const QDomElement& e )
+{
+ QString name;
+ QString exp;
+ bool cs = false; //Expressions are case insensitive by default
+
+ if ( e.tagName().compare( "item" ) != 0 ) {
+ _error = i18n( "Expected tag 'item'" );
+ return;
+ }
+
+ QDomNode n = e.firstChild();
+ if ( n.isNull() ) {
+ _error = i18n( "First child of 'item' is not a node" );
+ return;
+ }
+
+ QDomElement el = n.toElement();
+ if ( el.isNull() || el.tagName().compare( "name" ) != 0 ) {
+ _error = i18n( "Expected tag 'name'" );
+ return;
+ }
+ name = el.text();
+
+ n = n.nextSibling();
+ el = n.toElement();
+ if ( el.isNull() || el.tagName().compare( "exp" ) != 0 ) {
+ _error = i18n( "Expected tag 'exp'" );
+ return;
+ }
+ exp = el.text();
+
+ n = n.nextSibling();
+ el = n.toElement();
+ if ( ! el.isNull() )
+ cs = true;
+
+ kdDebug(KBABEL) << "RegExpTool: Adding expression: " << name << endl;
+ _list.append( Expression( name, QRegExp( exp, cs ) ) );
+}
+
+#include "main.moc"
diff --git a/kbabel/datatools/regexp/main.h b/kbabel/datatools/regexp/main.h
new file mode 100644
index 00000000..690c5769
--- /dev/null
+++ b/kbabel/datatools/regexp/main.h
@@ -0,0 +1,73 @@
+/*
+ Copyright (C) 2005 Albert Cervera i Areny <albertca at hotpop dot com>
+
+ Based on Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ 2002 Stanislav Visnovsky <visnovsky@kde.org>
+ 2003 Dwayne Bailey <dwayne@translate.org.za>
+
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __main_h__
+#define __main_h__
+
+#include <kdatatool.h>
+#include <qvaluelist.h>
+
+class QDomElement;
+
+class Expression
+{
+public:
+ Expression() {};
+ Expression( const QString& name, const QRegExp& regExp )
+ {
+ _name = name;
+ _regExp = regExp;
+ }
+ const QString& name() const
+ {
+ return _name;
+ }
+ const QRegExp& regExp() const
+ {
+ return _regExp;
+ }
+
+private:
+ QString _name;
+ QRegExp _regExp;
+};
+
+typedef QValueList<Expression> ExpressionList;
+
+class RegExpTool : public KDataTool
+{
+ Q_OBJECT
+
+public:
+ RegExpTool( QObject* parent, const char* name, const QStringList & );
+ virtual bool run( const QString& command, void* data, const QString& datatype, const QString& mimetype);
+
+private:
+ void loadExpressions();
+ void elementToExpression( const QDomElement& e );
+
+ ExpressionList _list;
+ QString _error;
+};
+
+#endif
diff --git a/kbabel/datatools/regexp/regexplist.xml b/kbabel/datatools/regexp/regexplist.xml
new file mode 100644
index 00000000..1cd0b23d
--- /dev/null
+++ b/kbabel/datatools/regexp/regexplist.xml
@@ -0,0 +1,303 @@
+<!--
+ This file contains the list of regular expressions the plugin should check for.
+ Please, follow this syntax:
+ <regexplist>
+ <item>
+ <name></name>
+ <exp></exp>
+ <cs/> (only when the expression needs to be case sensitive)
+ </item>
+ ...
+ </regexplist>
+
+ Right now the file should be copied to ~/.kde/share/apps/kbabel/regexplist.xml. I'm sorry this cannot be configured but hope it will in the future. By the time if you need another location you have to modify the source code (main.cc)
+
+ You'll see in the example that most expressions start with '(^| |\\t)+' and then a word. This is to ensure it _is_ a word. Using the usual expressions to ensure we pick up a whole word doesn't work for the catalan language. Anyway, if you need to match a tab be sure you use the '\\t' expression.
+
+ Right now names in expressions aren't much useful, but I aim to modify kbabel in order to give more information about the error found. And I will probably add a description tag to enable long explanations of the mistake.
+
+ Also note the syntax of the file is quite strict. Mmmmm... too many words without a joke, this really doesn't seem to be open source :(
+ -->
+
+<regexplist>
+ <item>
+ <name>_el_ seguit de vocal</name>
+ <exp>(^| |\\t)+el +[a,e,i,o,u][a-z]+</exp>
+ </item>
+ <item>
+ <name>_la_ seguit de a,e,o</name>
+ <exp>(^| |\\t)+la +[a,e,o][a-z]+</exp>
+ </item>
+ <item>
+ <name>_per el_</name>
+ <exp>(^| |\\t)+per +el( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>_per els_</name>
+ <exp>(^| |\\t)+per +els( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>_de el_</name>
+ <exp>(^| |\\t)+de +el( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>_de els_</name>
+ <exp>(^| |\\t)+de +els( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>_a el_</name>
+ <exp>(^| |\\t)+a +el( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>_a els_</name>
+ <exp>(^| |\\t)+a +els( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>_al_ seguit de vocal</name>
+ <exp>(^| |\\t)+al +[a,e,i,o,u][a-z]+</exp>
+ </item>
+ <item>
+ <name>m'els</name>
+ <exp>(^| |\\t)m'els( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>mels</name>
+ <exp>(^| |\\t)mels( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>s'el</name>
+ <exp>(^| |\\t)s'el( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>sel</name>
+ <exp>(^| |\\t)sel( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>s'els</name>
+ <exp>(^| |\\t)s'els( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>sels</name>
+ <exp>(^| |\\t)sels( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>s'em</name>
+ <exp>(^| |\\t)s'em( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>sem</name>
+ <exp>(^| |\\t)sem( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>s'hem</name>
+ <exp>(^| |\\t)s'hem( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>s'ens</name>
+ <exp>(^| |\\t)s'ens( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>s'et</name>
+ <exp>(^| |\\t)s'et( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>susa</name>
+ <exp>(^| |\\t)susa( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>s'us</name>
+ <exp>(^| |\\t)s'us( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>su's</name>
+ <exp>(^| |\\t)su's( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>t'els</name>
+ <exp>(^| |\\t)t'els( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>t'el</name>
+ <exp>(^| |\\t)t'el( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>t'em</name>
+ <exp>(^| |\\t)t'em( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>t'ens</name>
+ <exp>(^| |\\t)t'ens( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>t'en</name>
+ <exp>(^| |\\t)t'en( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>ten</name>
+ <exp>(^| |\\t)ten( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>t'ens</name>
+ <exp>(^| |\\t)t'ens( |\\t|$)+</exp>
+ </item>
+ <item>
+ <name>vos sense accent</name>
+ <exp>(^| |\\t)vos( |\\t|$)</exp>
+ </item>
+ <item>
+ <name>Terminal és masculí (si es tracta d'informàtica): el terminal</name>
+ <exp>(^| |\\t)la +terminal( |\\t|$)</exp>
+ </item>
+ <item>
+ <name>Terminal és masculí (si es tracta d'informàtica): un terminal</name>
+ <exp>(^| |\\t)una +terminal( |\\t|$)</exp>
+ </item>
+ <item>
+ <name></name>
+ <exp>(^| |\\t)a +que( |\\t|$)</exp>
+ </item>
+ <item>
+ <name></name>
+ <exp>(^| |\\t)de +que( |\\t|$)</exp>
+ </item>
+ <item>
+ <name></name>
+ <exp>(^| |\\t)en +que( |\\t|$)</exp>
+ </item>
+ <item>
+ <name></name>
+ <exp>(^| |\\t)amb +que( |\\t|$)</exp>
+ </item>
+ <item>
+ <name></name>
+ <exp>(^| |\\t)per +que( |\\t|$)</exp>
+ </item>
+ <!-- En fase de test, últimes propostes d'en David -->
+
+ <!--
+ Abans de "aquest", "aquell", "algun", "un" i les seues variants no posarem
+ "a", sinó "en" (per a moviment i situació):
+ Voleu desar el fitxer en aquesta carpeta?
+ Tanmateix, per a la resta de casos cal posar "a"!
+
+ Probablement comprovar "a un" donaria massa falsos positius.
+ -->
+ <!--
+ <item>
+ <name></name>
+ <exp>(^| |\\t)a +(aquest|aquell|algun)( |\\t|$)</exp>
+ </item>
+ -->
+ <!--
+ El pronom es, davant d'un mot començat per sa-, se-, si-, so-, su-, ce- o
+ ci-, s'escriurà sempre en la forma plena (se):
+
+ Se sap que algunes característiques...
+ Les propietats d'aquest programa se sumen a les de...
+ -->
+ <item>
+ <name></name>
+ <exp>(^| |\\t)es +(sa|se|si|so|su|ce|ci)</exp>
+ </item>
+
+ <!--
+ En frases negatives, les partícules mai, cap, res, gens i ningú han de dur
+ no sempre:
+
+ No tragueu mai el disquet abans d'hora.
+ Cap ordre no s'ha d'escriure en majúscules.
+ Sense la contrasenya, ningú no està autoritzat a accedir a la informació.
+ -->
+ <!--
+ <item>
+ <name></name>
+ <exp>(((^| |\\t)(mai|cap|res|gens|ningú)( |\\t|$))(?!.*(^| |\\t)no( |\\t|$)))|(((^| |\\t)(mai|cap|res|gens|ningú)( |\\t|$))(?!.*(^| |\\t)no( |\\t|$)))</exp>
+ </item>
+ -->
+ <!--
+ 3.3. Construccions incorrectes
+ Podríem buscar "donat que" per a substituir-ho per "atès que".
+ "tals com" -> "com ara"
+ "tal i com" -> "tal com"
+ "teniu que" -> "heu de"/"heu d'"
+ "en quant a" -> "pel que fa a", "quant a"
+ -->
+ <!--
+ <item>
+ <name></name>
+ <exp>(^| |\\t)donat +que( |\\t|$)</exp>
+ </item>
+ -->
+ <item>
+ <name></name>
+ <exp>(^| |\\t)tals +com( |\\t|$)</exp>
+ </item>
+ <item>
+ <name></name>
+ <exp>(^| |\\t)tal +i +com( |\\t|$)</exp>
+ </item>
+ <item>
+ <name></name>
+ <exp>(^| |\\t)teniu +que( |\\t|$)</exp>
+ </item>
+ <item>
+ <name></name>
+ <exp>(^| |\\t)en +quant +a( |\\t|$)</exp>
+ </item>
+
+ <!--
+ Softcatalà:
+ * Hi han: El verb haver-hi és impersonal, per això no té plural en català central, atès que no té subjecte. Per tant, no es diu hi han, hi havien, hi hauran, sinó hi ha, hi havia, hi haurà, encara que el complement que el segueixi sigui plural.
+ -->
+ <item>
+ <name></name>
+ <exp>(^| |\\t)hi +han( |\\t|$)</exp>
+ </item>
+ <item>
+ <name></name>
+ <exp>(^| |\\t)hi +havien( |\\t|$)</exp>
+ </item>
+ <item>
+ <name></name>
+ <exp>(^| |\\t)hi +hauran( |\\t|$)</exp>
+ </item>
+
+ <!--
+ Softcatalà:
+ * Tenir que: És la traducció incorrecta al català de l'expressió castellana tener que. La forma correcta és haver de; també es pot utilitzar el verb impersonal caldre.
+ -->
+ <item>
+ <name></name>
+ <exp>(^| |\\t)teniu +que( |\\t|$)</exp>
+ </item>
+ <item>
+ <name></name>
+ <exp>(^| |\\t)tenim +que( |\\t|$)</exp>
+ </item>
+ <item>
+ <name></name>
+ <exp>(^| |\\t)tenen +que( |\\t|$)</exp>
+ </item>
+ <item>
+ <name></name>
+ <exp>(^| |\\t)en +quant +a( |\\t|$)</exp>
+ </item>
+ <item>
+ <name></name>
+ <exp>(^| |\\t)en +quant +a( |\\t|$)</exp>
+ </item>
+ <item>
+ <name></name>
+ <exp>(^| |\\t)en +quant +a( |\\t|$)</exp>
+ </item>
+ <item>
+ <name></name>
+ <exp>(^| |\\t)en +quant +a( |\\t|$)</exp>
+ </item>
+ <item>
+ <name></name>
+ <exp>(^| |\\t)en +quant +a( |\\t|$)</exp>
+ </item>
+
+
+</regexplist> \ No newline at end of file
diff --git a/kbabel/datatools/setfuzzy/Makefile.am b/kbabel/datatools/setfuzzy/Makefile.am
new file mode 100644
index 00000000..f1a5b8bc
--- /dev/null
+++ b/kbabel/datatools/setfuzzy/Makefile.am
@@ -0,0 +1,19 @@
+
+INCLUDES = -I$(srcdir)/../../common -I../../common $(all_includes)
+kbabel_setfuzzytool_la_LIBADD = ../../common/libkbabelcommon.la
+
+####### Files
+
+kde_module_LTLIBRARIES = kbabel_setfuzzytool.la
+
+kbabel_setfuzzytool_la_SOURCES = main.cc
+
+kbabel_setfuzzytool_la_LDFLAGS = $(all_libraries) -avoid-version -module -no-undefined
+
+noinst_HEADERS = main.h
+
+kbabel_setfuzzytool_la_METASOURCES = AUTO
+
+service_DATA = kbabel_setfuzzytool.desktop
+servicedir = $(kde_servicesdir)
+
diff --git a/kbabel/datatools/setfuzzy/kbabel_setfuzzytool.desktop b/kbabel/datatools/setfuzzy/kbabel_setfuzzytool.desktop
new file mode 100644
index 00000000..ead62f13
--- /dev/null
+++ b/kbabel/datatools/setfuzzy/kbabel_setfuzzytool.desktop
@@ -0,0 +1,98 @@
+[Desktop Entry]
+Name=Toggle Fuzzy Tool for KBabel
+Name[bs]=Fuzzy prekidaÄ - alat za KBabel
+Name[ca]=Eina per a KBabel que des/marca entrades inexactes
+Name[cs]=Nástroj pro přepínání fuzzy položek
+Name[cy]=Erfyn Newid i Bras i KBabel
+Name[da]=Slå fuzzy-værktøj til og fra for KBabel
+Name[de]=Umschalter für fragwürdige Einträge für KBabel
+Name[el]=ΕÏγαλείο εναλλαγής ασάφειας για το KBabel
+Name[es]=Herramienta de conmutación de entradas dudosas para KBabel
+Name[et]=KBabeli kahtlaste teadete lülitamise tööriist
+Name[eu]=Zalantzazko sarreren aldaketa tresna KBabel-entzat
+Name[fa]=زدن ضامن ابزار مبهم برای KBabel
+Name[fi]=KBabel-työkalu sumean tilan vaihtamiseksi
+Name[fr]=Outil d'inversion de fuzzy pour KBabel
+Name[gl]=Ferramenta de comutación da marca de dubida para KBabel
+Name[hu]=Ellenőrzési eszköz a KBabelhez
+Name[is]=Víxla loðnu tól fyrir KBabel
+Name[it]=Strumento di KBabel per commutare le voci fuzzy
+Name[ja]=KBabel ã‚ã„ã¾ã„状態切り替ãˆãƒ„ール
+Name[ka]=დáƒáƒ£áƒ–უსტებელის გáƒáƒ“áƒáƒ áƒ—ვის ხელსáƒáƒ¬áƒ§áƒ KBabel-სთვის
+Name[kk]=KBabel-дың жазу дүмбілездік күйін теріÑтеу құралы
+Name[lt]=KBabel įrankis, visus pranešimus pažymintis „neaiškiais“
+Name[ms]=Alat Togol Kabur untuk KBabel
+Name[nb]=Slå av/på uklar-statusen i KBabel
+Name[nds]=Twiefelhaftig-Status ümschalten för KBabel
+Name[ne]=केबà¥à¤¯à¤¾à¤¬à¤²à¤•à¤¾ लागि फजी उपकरण टगल गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥
+Name[nl]=Fuzzystatusomschakeling voor KBabel
+Name[nn]=Slå av/på uklar-statusen i KBabel
+Name[pa]=ਕੇਬਬੇਲ ਲਈ ਤਬਦੀਲੀ ਅਸਪਸ਼ਟ ਸੰਦ
+Name[pl]=Narzędzie do przełączania statusu wątpliwego komunikatu w KBabel
+Name[pt]=Classificação Global Aproximada para o KBabel
+Name[pt_BR]=Ferramenta para Alternar Aproximado para o KBabel
+Name[ru]=Изменение ÑтатуÑа черновой запиÑи Ð´Ð»Ñ KBabel
+Name[sk]=Nástroje pre prepnutie nepresného stavu per KBabel
+Name[sl]=Preklopi vse v ohlapno; za KBabel
+Name[sr]=Укључи/иÑкључи алат за нејаÑне поруке за KBabel
+Name[sr@Latn]=UkljuÄi/iskljuÄi alat za nejasne poruke za KBabel
+Name[sv]=Verktyg för att ändra inexakta för Kbabel
+Name[ta]= Kபாபேலà¯à®•à¯à®•à¯ நிலைமாறà¯à®±à®¿ இடைநிலை கரà¯à®µà®¿
+Name[tg]=Утилита барои ÑиёҳнавиÑÓ£ дар KBabel
+Name[tr]=KBabel için Geçiş Bulanık Aracı
+Name[uk]=ЗаÑіб Ð¿ÐµÑ€ÐµÐ¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð½ÐµÑ‚Ð¾Ñ‡Ð½Ð¸Ñ… фраз Ð´Ð»Ñ KBabel
+Name[zh_CN]=KBabel 切æ¢æ¨¡ç³Šå·¥å…·
+Name[zh_TW]=KBabel 切æ›æ¨¡ç³Šç‹€æ…‹å·¥å…·
+X-KDE-Library=kbabel_setfuzzytool
+Type=Service
+Commands=allfuzzy
+Comment=Set All Fuzzy
+Comment[bg]=Маркиране на вÑички като неÑÑни
+Comment[bs]=Podesi sve kao fuzzy
+Comment[ca]=Estableix totes les entrades a inexacta
+Comment[cs]=Nastavit vše jako fuzzy
+Comment[cy]=Gosod Popeth i Fras
+Comment[da]=Sæt alle til fuzzy
+Comment[de]=Alle auf fragwürdig setzen
+Comment[el]=ΟÏισμός όλων ως ασαφή
+Comment[es]=Cambiar todo a dudoso
+Comment[et]=Kõigi teadete määramine kahtlaseks
+Comment[eu]=Ezarri denak zalantzazko bezala
+Comment[fa]=تنظیم همۀ مبهمها
+Comment[fi]=Aseta kaikki sumeiksi
+Comment[fr]=Mettre tout en fuzzy
+Comment[gl]=Marce todas as mensaxes como dúbidas
+Comment[hi]=सभी फजी नियत करें
+Comment[hu]=Az összes üzenet ellenőrzendővé alakítása
+Comment[is]=Setja öll loðin
+Comment[it]=Imposta tutte le voci come fuzzy
+Comment[ja]=ã™ã¹ã¦ã‚ã„ã¾ã„ã¨ã—ã¦ãƒžãƒ¼ã‚¯
+Comment[ka]=ყველáƒáƒ¡áƒ—ვის დáƒáƒ£áƒ–უსტებელის დáƒáƒ§áƒ”ნებáƒ
+Comment[kk]=Барлығын дүмбілез деп кою
+Comment[lt]=Žymėti visus neaiškiais
+Comment[ms]=Tetapkan Semua Kabur
+Comment[nb]=Sett alle strengene som uklare
+Comment[nds]=All op "twiefelhaftig" setten
+Comment[ne]=सबै फजी सेट गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥
+Comment[nl]=Alles fuzzy markeren
+Comment[nn]=Set alle strengane som uklare
+Comment[pa]= ਸਭ ਅਸਪਸ਼ਟ ਕਰੋ
+Comment[pl]=Ustawia wszystkie komunikaty jako wÄ…tpliwe
+Comment[pt]=Coloca todas as mensagens como aproximadas
+Comment[pt_BR]=Configura Todos Aproximados
+Comment[ru]=УÑтановить ÑÑ‚Ð°Ñ‚ÑƒÑ "черновые" Ð´Ð»Ñ Ð²Ñех запиÑей
+Comment[sk]=Nastaviť všetky ako nepresné
+Comment[sl]=Nastavi vse ohlapno
+Comment[sr]=ПоÑтави Ñве на нејаÑно
+Comment[sr@Latn]=Postavi sve na nejasno
+Comment[sv]=Gör alla inexakta
+Comment[ta]= எலà¯à®²à®¾ இடைநிலையையà¯à®®à¯ அமை
+Comment[tg]=Барқарор кардани ҳолати "ÑиёҳнавиÑҳо" барои ҳамаи Ñабтҳо
+Comment[tr]=Tümünü Bulanık Ata
+Comment[uk]=Ð’Ñтановити вÑÑ– фрази Ñк "неточні"
+Comment[zh_CN]=全部设为模糊
+Comment[zh_TW]=全部設為模糊
+ServiceTypes=KDataTool,KBabelTool
+DataType=Catalog
+DataMimeTypes=application/x-kbabel-catalog
+ReadOnly=false
diff --git a/kbabel/datatools/setfuzzy/main.cc b/kbabel/datatools/setfuzzy/main.cc
new file mode 100644
index 00000000..077004d8
--- /dev/null
+++ b/kbabel/datatools/setfuzzy/main.cc
@@ -0,0 +1,98 @@
+/* This file is part of KBabel
+ based Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ 2003 Stanislav Visnovsky <visnovsky@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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#include <resources.h>
+#include "catalog.h"
+#include "main.h"
+
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <klocale.h>
+
+/***************************************************
+ *
+ * Factory
+ *
+ ***************************************************/
+
+K_EXPORT_COMPONENT_FACTORY( kbabel_setfuzzytool, KGenericFactory<SetFuzzyTool> ( "kbabeldatatool" ) )
+
+using namespace KBabel;
+
+SetFuzzyTool::SetFuzzyTool( QObject* parent, const char* name, const QStringList & )
+ : KDataTool( parent, name )
+{
+}
+
+bool SetFuzzyTool::run( const QString& command, void* data, const QString& datatype, const QString& mimetype )
+{
+ if ( command != "allfuzzy" )
+ {
+ kdDebug(KBABEL) << "Fuzzy Toggling Tool does only accept the command 'allfuzzy'" << endl;
+ kdDebug(KBABEL) << " The commands " << command << " is not accepted" << endl;
+ return FALSE;
+ }
+
+ // Check wether we can accept the data
+ if ( datatype != "Catalog" )
+ {
+ kdDebug(KBABEL) << "Fuzzy Toggling Tool only accepts datatype Catalog" << endl;
+ return FALSE;
+ }
+
+ if ( mimetype != "application/x-kbabel-catalog" )
+ {
+ kdDebug(KBABEL) << "Plural Forms Tool only accepts mimetype application/x-kbabel-catalog" << endl;
+ return FALSE;
+ }
+
+ if( command == "allfuzzy" )
+ {
+ Catalog* catalog = (Catalog*)(data);
+
+ catalog->applyBeginCommand(0,Msgstr,0);
+
+ for( uint index=0; index < catalog->numberOfEntries(); index++ )
+ {
+ if( !catalog->isUntranslated(index) )
+ {
+ catalog->setFuzzy(index,true);
+ }
+ }
+
+ catalog->applyEndCommand(0,Msgstr,0);
+ }
+ return TRUE;
+}
+
+#include "main.moc"
diff --git a/kbabel/datatools/setfuzzy/main.h b/kbabel/datatools/setfuzzy/main.h
new file mode 100644
index 00000000..da28a9d1
--- /dev/null
+++ b/kbabel/datatools/setfuzzy/main.h
@@ -0,0 +1,47 @@
+/* This file is part of KBabel
+ based on Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ 2003 Stanislav Visnovsky <visnovsky@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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#ifndef __main_h__
+#define __main_h__
+
+#include <kdatatool.h>
+
+class SetFuzzyTool : public KDataTool
+{
+ Q_OBJECT
+
+public:
+ SetFuzzyTool( QObject* parent, const char* name, const QStringList & );
+ virtual bool run( const QString& command, void* data, const QString& datatype, const QString& mimetype);
+};
+
+#endif
diff --git a/kbabel/datatools/whitespace/Makefile.am b/kbabel/datatools/whitespace/Makefile.am
new file mode 100644
index 00000000..f0987b4f
--- /dev/null
+++ b/kbabel/datatools/whitespace/Makefile.am
@@ -0,0 +1,19 @@
+
+INCLUDES = -I$(srcdir)/../../common -I../../common $(all_includes)
+kbabel_whitespacetool_la_LIBADD = $(LIB_KIO) ../../common/libkbabelcommon.la
+
+####### Files
+
+kde_module_LTLIBRARIES = kbabel_whitespacetool.la
+
+kbabel_whitespacetool_la_SOURCES = main.cc
+
+kbabel_whitespacetool_la_LDFLAGS = $(all_libraries) -avoid-version -module -no-undefined
+
+noinst_HEADERS = main.h
+
+kbabel_whitespacetool_la_METASOURCES = AUTO
+
+service_DATA = kbabel_whitespacetool.desktop
+servicedir = $(kde_servicesdir)
+
diff --git a/kbabel/datatools/whitespace/kbabel_whitespacetool.desktop b/kbabel/datatools/whitespace/kbabel_whitespacetool.desktop
new file mode 100644
index 00000000..74de2bc4
--- /dev/null
+++ b/kbabel/datatools/whitespace/kbabel_whitespacetool.desktop
@@ -0,0 +1,98 @@
+[Desktop Entry]
+Name=String Translated as Whitespace Validator for KBabel
+Name[bg]=ВалидноÑÑ‚ на низовете, преведени като интервали - KBabel
+Name[bs]=Provjera stringova prevedenih kao blanko znaci za KBabel
+Name[ca]=Validació de cadenes traduïdes com un espai en blanc per a KBabel
+Name[cs]=Validátor překladů bílých mezer
+Name[cy]=Dilysydd Llinyn wedi'i Gyfieithu fel Gofodnod ar gyfer KBabel
+Name[da]=Streng oversat som blanke tegn-validering for KBabel
+Name[de]=Prüfung auf Leerzeichenübersetzungen für KBabel
+Name[el]=Ελεγκτής εγκυÏότητας συμβολοσειÏών μεταφÏασμένα ως κενό για το KBabel
+Name[es]=Validador de cadenas traducidas como espacios en blanco.para KBabel
+Name[et]=KBabeli tühimärgiks tõlgitud teadete kontrollija
+Name[eu]=Zurigune bezala itzulitako kateen balidatzailea KBabel-entzat
+Name[fa]=رشتۀ ترجمه‌شده به عنوان اعتبارسنج Ùاصلۀ سÙید برای KBabel
+Name[fi]=Tyhjeinä käännettyjen merkkijonojen tarkistaja KBabelissa
+Name[fr]=Validateur de chaînes traduites comme des espaces pour KBabel
+Name[gl]=Validación de texto traducido como espazo para KBabel
+Name[hu]=Csak üres karaktereket tartalmazó fordítások kiszűrése a KBabelben
+Name[is]=Staðfestir fyrir KBabel fyrir strengi þýdda sem bil
+Name[it]=Convalidatore delle stringhe tradotte con spazi bianchi per KBabel
+Name[ja]=KBabel 空白ã¨ã—ã¦ç¿»è¨³ã•ã‚ŒãŸæ–‡å­—列を検索
+Name[ka]=სტრიქáƒáƒœáƒ˜ ნáƒáƒ—áƒáƒ áƒ’მნირრáƒáƒ’áƒáƒ áƒª Whitespace დáƒáƒ›áƒ›áƒáƒ¬áƒ›áƒ”ბელი KBabel-სთვის
+Name[kk]=KBabel-дың Ð±Ð¾Ñ Ð¾Ñ€Ñ‹Ð½ аудармаларын текÑеруі
+Name[lt]=KBabel eiluÄių, iÅ¡verstų tuÅ¡Äiais tarpais, patikros įrankis
+Name[nb]=Se etter tomme strenger i KBabel
+Name[nds]=Leertekenöversetten-Prööv för KBabel
+Name[ne]=कà¥à¤¯à¤¾à¤¬à¥‡à¤²à¤•à¤¾ लागि सेतो रिकà¥à¤¤à¤¸à¥à¤¥à¤¾à¤¨ पà¥à¤°à¤®à¤¾à¤£à¥€à¤¤à¤•à¤°à¥à¤¤à¤¾ अनà¥à¤°à¥à¤ª अनà¥à¤¬à¤¾à¤¦ गरिà¤à¤•à¤¾ सà¥à¤Ÿà¥à¤°à¤¿à¤™
+Name[nl]=Tekst-vertaald-als-witruimte-validatie voor KBabel
+Name[nn]=Sjå etter tomme strengar i KBabel
+Name[pl]=Sprawdzenie czy napis jest przetłumaczony jako białe znaki w KBabel
+Name[pt]=Validação de Texto Traduzido como Espaço para o KBabel
+Name[pt_BR]=Validador de String Traduzidos com Espaços em Branco para o KBabel
+Name[ru]=Проверка Ñтрок, переведённых как пробел Ð´Ð»Ñ KBabel
+Name[sk]=Kontrola textu preloženého ako prázdny pre KBabel
+Name[sl]=Potrjevalnik nizov, prevedenih kot presledki, za KBabel
+Name[sr]=Оверивач за низове знакова преведене као празан проÑтор за KBabel
+Name[sr@Latn]=OverivaÄ za nizove znakova prevedene kao prazan prostor za KBabel
+Name[sv]=Validering av sträng översatt som blanktecken för Kbabel
+Name[ta]=Kபாபேலà¯à®•à¯à®•à¯ சரம௠மொழிபெயரà¯à®ªà¯à®ªà¯ இடைவேலை மதிபà¯à®ªà¯€à®Ÿà¯à®Ÿà®¾à®³à®°à¯
+Name[tg]=Тафтиши Ñатр, ки миÑли фоÑила барои KBabel, тарҷума шудааÑÑ‚
+Name[tr]=KBabel için Ayırma Boşluğu gibi Çevrilen Dizge Denetimi
+Name[uk]=Перевірка фраз, перекладених Ñк пропуÑки, Ð´Ð»Ñ KBabel
+Name[zh_CN]=KBabel 的字符串译为空格的检查器
+Name[zh_TW]=KBabel 翻譯為空白字串檢查器
+ValidationString=whitespace checking
+X-KDE-Library=kbabel_whitespacetool
+Type=Service
+Commands=validate
+Comment=Whitespace Translations
+Comment[bg]=Ðизове, преведени като интервали
+Comment[bs]=Blanko prijevodi
+Comment[ca]=Traduccions amb espai en blanc
+Comment[cs]=Překlady mezer
+Comment[cy]=Cyfieithiadau Gofodnod
+Comment[da]=Oversatte blanke tegn
+Comment[de]=Leerzeichen-Ãœbersetzungen
+Comment[el]=ΜεταφÏάσεις με κενό
+Comment[es]=Traducciones de espacios en blanco
+Comment[et]=Tühimärkidest koosnevad tõlked
+Comment[eu]=Zurigune itzulpenak
+Comment[fa]=ترجمۀ Ùاصله‌های سÙید
+Comment[fi]=Tyhjeiden käännökset
+Comment[fr]=Traductions en espaces
+Comment[gl]=Traducións de espazos en branco
+Comment[he]=×ª×¨×’×•×ž×™× ×©×œ ×ª×•×•×™× × ×§×™×™×
+Comment[hi]=वà¥à¤¹à¤¾à¤‡à¤Ÿ-सà¥à¤ªà¥‡à¤¸ अनà¥à¤µà¤¾à¤¦
+Comment[hu]=Az üres fordítások kiszűrése
+Comment[is]=Þýðingar bila
+Comment[it]=Traduzioni con spazi bianchi
+Comment[ja]=空白翻訳文字列を検索
+Comment[ka]=Whitespace მთáƒáƒ áƒ’მნელები
+Comment[kk]=Ð‘Ð¾Ñ Ð¾Ñ€Ñ‹Ð½ аудармалары
+Comment[lt]=TuÅ¡Äių eiluÄių patikra
+Comment[ms]=Terjemahan Ruang Kosong
+Comment[nb]=Tomme strenger
+Comment[nds]=Leertekenöversetten pröven
+Comment[ne]=सेतो रिकà¥à¤¤à¤¸à¥à¤¥à¤¾à¤¨ अनà¥à¤¬à¤¾à¤¦
+Comment[nl]=Lege vertalingen
+Comment[nn]=Tomme strengar
+Comment[pl]=Tłumaczenia w postaci białych znaków
+Comment[pt]=Traduções de Espaços em Branco
+Comment[pt_BR]=Traduções com espaços em branco
+Comment[ru]=ПуÑтые переводы
+Comment[sk]=Prázdne preklady
+Comment[sl]=Prevodi presledkov
+Comment[sr]=Преводи као празан проÑтор
+Comment[sr@Latn]=Prevodi kao prazan prostor
+Comment[sv]=Översättning med blanktecken
+Comment[ta]= இடைவேலை பெயரà¯à®ªà¯à®ªà¯
+Comment[tg]=Тарҷумаҳои холӣ
+Comment[tr]=Ayırma Boşluğu Çevirileri
+Comment[uk]=Порожні переклади
+Comment[zh_CN]=空白翻译
+Comment[zh_TW]=空白翻譯
+ServiceTypes=KDataTool,KBabelValidator
+DataType=CatalogItem
+DataMimeTypes=application/x-kbabel-catalogitem
+ReadOnly=true
diff --git a/kbabel/datatools/whitespace/main.cc b/kbabel/datatools/whitespace/main.cc
new file mode 100644
index 00000000..9987c465
--- /dev/null
+++ b/kbabel/datatools/whitespace/main.cc
@@ -0,0 +1,144 @@
+/* This file is part of KBabel
+ based Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ 2002 Stanislav Visnovsky <visnovsky@kde.org>
+ 2003 Dwayne Bailey <dwayne@translate.org.za>
+
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#include <resources.h>
+#include "catalog.h"
+#include "catalogitem.h"
+#include "catalogsettings.h"
+#include "main.h"
+
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+/***************************************************
+ *
+ * Factory
+ *
+ ***************************************************/
+
+K_EXPORT_COMPONENT_FACTORY( kbabel_whitespacetool, KGenericFactory<WhitespaceTool> ( "kbabeldatatool" ) )
+
+using namespace KBabel;
+
+WhitespaceTool::WhitespaceTool( QObject* parent, const char* name, const QStringList & )
+ : KDataTool( parent, name ), _cache_origin( 0 ), _equation("^[a-zA-Z0-9]+=")
+{
+ i18n("which check found errors","whitespace only translation");
+}
+
+bool WhitespaceTool::run( const QString& command, void* data, const QString& datatype, const QString& mimetype )
+{
+
+ if ( command != "validate" )
+ {
+ kdDebug(KBABEL) << "Whitespace Tool only accepts the 'validate' command" << endl;
+ kdDebug(KBABEL) << " The command " << command << " is not accepted" << endl;
+ return false;
+ }
+
+ // Check wether we can accept the data
+ if ( datatype != "CatalogItem" )
+ {
+ kdDebug(KBABEL) << "Whitespace Tool only accept the CatalogItem datatype" << endl;
+ return false;
+ }
+
+ if ( mimetype != "application/x-kbabel-catalogitem" )
+ {
+ kdDebug(KBABEL) << "Whitespace Tool only accept the 'application/x-kbabel-catalogitem' mimetype" << endl;
+ return false;
+ }
+
+ if( command == "validate" )
+ {
+
+ CatalogItem* item = (CatalogItem*)(data);
+ bool hasIdError = false;
+ bool hasStrError = false;
+ QRegExp _whitespace("^\\s+$");
+ QStringList str, id;
+
+ if(!item->isUntranslated()) {
+ if( _cache_origin != item->project() )
+ {
+ _plurals = item->project()->miscSettings().singularPlural;
+ _cache_origin = item->project();
+ }
+
+ //Ensure KDE plural forms are in a StringList
+ //FIXME Eliminate context information and this could become a generic message splitter
+ if( item->pluralForm() == KDESpecific ) {
+ str = QStringList::split( "\\n", item->msgstr().first(), true );
+ id = QStringList::split( "\\n",
+ item->msgid().first().replace( QRegExp(_plurals), ""), true );
+ } else {
+ str = item->msgstr();
+ id = item->msgid();
+ }
+
+ //Strip equations
+ id.first().replace( QRegExp(_equation), "");
+ str.first().replace( QRegExp(_equation), "");
+
+ //Ignore Messages with blank msgid components
+ for( QStringList::Iterator it = id.begin() ; it != id.end() ; it++ ) {
+ QString resultstring = (*it);
+ hasIdError = hasIdError || resultstring.contains(_whitespace);
+ }
+ if( hasIdError ) return true;
+
+ //Check each QString in the List is not whitespace
+ for( QStringList::Iterator it = str.begin() ; it != str.end() ; it++ ) {
+ QString resultstring = (*it);
+ hasStrError = hasStrError || resultstring.contains(_whitespace);
+ }
+
+ }
+
+ if(hasStrError) {
+ item->appendError( "whitespace translation" );
+ return false;
+ } else {
+ item->removeError( "whitespace translation" );
+ return true;
+ }
+
+ }
+ return false;
+}
+
+#include "main.moc"
diff --git a/kbabel/datatools/whitespace/main.h b/kbabel/datatools/whitespace/main.h
new file mode 100644
index 00000000..9a0545cc
--- /dev/null
+++ b/kbabel/datatools/whitespace/main.h
@@ -0,0 +1,55 @@
+/* This file is part of KBabel
+ based on Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ 2002 Stanislav Visnovsky <visnovsky@kde.org>
+ 2003 Dwayne Bailey <dwayne@translate.org.za>
+
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#ifndef __main_h__
+#define __main_h__
+
+#include "kbproject.h"
+
+#include <qregexp.h>
+#include <kdatatool.h>
+
+class WhitespaceTool : public KDataTool
+{
+ Q_OBJECT
+
+public:
+ WhitespaceTool( QObject* parent, const char* name, const QStringList & );
+ virtual bool run( const QString& command, void* data, const QString& datatype, const QString& mimetype);
+private:
+ KBabel::Project::Ptr _cache_origin;
+ QRegExp _plurals;
+ QRegExp _equation;
+};
+
+#endif
diff --git a/kbabel/datatools/whitespace/test.po b/kbabel/datatools/whitespace/test.po
new file mode 100644
index 00000000..96fb59d7
--- /dev/null
+++ b/kbabel/datatools/whitespace/test.po
@@ -0,0 +1,92 @@
+# Test file to validate the whitespace checking tool
+# Dwayne Bailey <dwayne@translate.org.za>, 2003
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: test\n"
+"Last-Translator: Dwayne Bailey <dwayne@translate.org.za>\n"
+"PO-Revision-Date: 2003-01-09 09:35+0200\n"
+"Language-Team: <english@translate.org.za>\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.2\n"
+
+# msgstr incorrectly translated with whitespace - 2*<sp>
+# Expected Result = error
+msgid "Some translation string"
+msgstr " "
+
+# msgid with 3*<sp> translated to 2*<sp> This should be valid
+# Expected Result = valid
+msgid " "
+msgstr " "
+
+# plural checks for KDE with a blank msgstr
+# Expected Result = error
+msgid ""
+"_n: Plural translation\n"
+"Second form %n"
+msgstr ""
+"First fine second wrong\n"
+" "
+
+# plural checks for KDE with everything correct
+# Expected Result = valid
+msgid ""
+"_n: Plural translation\n"
+"Second form %n"
+msgstr ""
+"First fine\n"
+"Second fine"
+
+# plural checks for KDE with bad msgid
+# Expected Result = valid
+msgid ""
+"_n: \n"
+"First form missing"
+msgstr ""
+"\n"
+"Second fine"
+
+# plural checks for KDE with bad msgid
+# Expected Result = valid
+msgid ""
+"_n: Second is missing\n"
+""
+msgstr ""
+"First fine\n"
+""
+
+# Plural check on GNU format with a missing plural
+# Expected Result = error
+msgid "Plural translation"
+msgid_plural "The second form %n"
+msgstr[0] "First fine second wrong"
+msgstr[1] " "
+
+# Plural check on GNU format in order
+# Expected Result = valid
+msgid "Plural translation"
+msgid_plural "The second form %n"
+msgstr[0] "First fine"
+msgstr[1] "Second fine"
+
+# Plural check on GNU format with singular missing
+# Expected Result = valid
+msgid ""
+msgid_plural "Singluar is missing"
+msgstr[0] ""
+msgstr[1] "Plural was translated"
+
+# Plural check on GNU format with plural missing
+# Expected Result = valid
+msgid "Plural is missing"
+msgid_plural ""
+msgstr[0] "Singular is translated"
+msgstr[1] ""
+
+# KDE specific: desktop file contains whitespace transaltion
+# Expected Result = error
+msgid "Name=No Spaces"
+msgstr "Name= "
+
diff --git a/kbabel/datatools/xml/Makefile.am b/kbabel/datatools/xml/Makefile.am
new file mode 100644
index 00000000..dbba4740
--- /dev/null
+++ b/kbabel/datatools/xml/Makefile.am
@@ -0,0 +1,19 @@
+
+INCLUDES = -I$(srcdir)/../../common -I../../common $(all_includes)
+kbabel_xmltool_la_LIBADD = $(LIB_KIO) ../../common/libkbabelcommon.la
+
+####### Files
+
+kde_module_LTLIBRARIES = kbabel_xmltool.la
+
+kbabel_xmltool_la_SOURCES = main.cc
+
+kbabel_xmltool_la_LDFLAGS = $(all_libraries) -avoid-version -module -no-undefined
+
+noinst_HEADERS = main.h
+
+kbabel_xmltool_la_METASOURCES = AUTO
+
+service_DATA = kbabel_xmltool.desktop
+servicedir = $(kde_servicesdir)
+
diff --git a/kbabel/datatools/xml/kbabel_xmltool.desktop b/kbabel/datatools/xml/kbabel_xmltool.desktop
new file mode 100644
index 00000000..2b03bef9
--- /dev/null
+++ b/kbabel/datatools/xml/kbabel_xmltool.desktop
@@ -0,0 +1,105 @@
+[Desktop Entry]
+Name=XML Validation for KBabel
+Name[bg]=XML валидноÑÑ‚ - KBabel
+Name[bs]=XML provjera za KBabel
+Name[ca]=Validació XML per a KBabel
+Name[cs]=Validace XML pro KBabel
+Name[cy]=Dilysiant XML i KBabel
+Name[da]=XML-validering for KBabel
+Name[de]=XML-Überprüfung für KBabel
+Name[el]=Έλεγχος εγκυÏότητας XML για το KBabel
+Name[es]=Validación XML para KBabel
+Name[et]=KBabeli XML-i kontrollija
+Name[eu]=XML balidazioa KBabel-entzat
+Name[fa]=اعتبارسنجی XML برای KBabel
+Name[fi]=XML-validointi KBabelissa
+Name[fr]=Validation XML pour KBabel
+Name[ga]=Bailíochtú XML le haghaidh KBabel
+Name[gl]=Validación de XML para KBabel
+Name[hi]=के-बेबल के लिठà¤à¤•à¥à¤¸à¤à¤®à¤à¤² वेलिडेशन
+Name[hu]=XML-ellenőrzés a KBabelben
+Name[is]=XML staðfesting fyrir KBabel
+Name[it]=Convalidatore di XML per KBabel
+Name[ja]=KBabel XML 検証
+Name[ka]=XML დáƒáƒ›áƒáƒ¬áƒ›áƒ”ბრKBabel-თვის
+Name[kk]=KBabel-дың XML-ды текÑеруі
+Name[lt]=KBabel XML patikros įrankis
+Name[ms]=Pengesah XML untuk KBabel
+Name[nb]=XML-sjekk i KBabel
+Name[nds]=XML-Prööv för KBabel
+Name[ne]=केबà¥à¤¯à¤¾à¤¬à¤²à¤•à¤¾ लागि à¤à¤•à¥à¤¸à¤à¤®à¤à¤² पà¥à¤°à¤®à¤¾à¤£à¥€à¤•à¤°à¤£
+Name[nl]=XML-validatie voor KBabel
+Name[nn]=XML-sjekk i KBabel
+Name[pa]=ਕੇਬਬੇਲ ਲਈ XML ਪਰਮਾਣਕ
+Name[pl]=Sprawdzenie XML w KBabel
+Name[pt]=Validação de XML para o KBabel
+Name[pt_BR]=Validação XML para o KBabel
+Name[ru]=Проверка XML Ð´Ð»Ñ KBabel
+Name[sk]=Kontrola XML pre KBabel
+Name[sl]=Potrjevanje XML za KBabel
+Name[sr]=Овера XML-а за KBabel
+Name[sr@Latn]=Overa XML-a za KBabel
+Name[sv]=Validering av XML för Kbabel
+Name[ta]= Kபாபேலà¯à®•à¯à®•à¯ XML செலà¯à®²à¯à®ªà®Ÿà®¿ சோதனை
+Name[tg]=Тафтиши XML барои KBabel
+Name[tr]=KBabel için XML Onaylama
+Name[uk]=Перевірка XML Ð´Ð»Ñ KBabel
+Name[zh_CN]=KBabel 的 XML 检查器
+Name[zh_TW]=KBabel XML 檢查器
+ValidationString=XML tags
+X-KDE-Library=kbabel_xmltool
+Type=Service
+Commands=validate
+Comment=Check Tags
+Comment[bg]=Проверка на таговете
+Comment[br]=Gwiriekaat al liketennoù
+Comment[bs]=Provjeri tagove
+Comment[ca]=Comprova les etiquetes
+Comment[cs]=Zkontrolovat znaÄky
+Comment[cy]=Dilysu tagiau
+Comment[da]=Tjek mærker
+Comment[de]=Prüfung der Tags in Übersetzungen
+Comment[el]=Έλεγχος ετικετών
+Comment[es]=Comprobar etiquetas
+Comment[et]=Siltide kontroll
+Comment[eu]=Egiaztatu etiketak
+Comment[fa]=بررسی برچسبها
+Comment[fi]=Tarkista merkintäkoodit
+Comment[fr]=Vérifier les balises
+Comment[ga]=Seiceáil Clibeanna
+Comment[gl]=Verificación das marcas XML/HTML
+Comment[he]=בודק תגיות
+Comment[hi]=टैगà¥à¤¸ जांच करें
+Comment[hu]=A tag-ek ellenőrzése
+Comment[is]=Athuga tög
+Comment[it]=Controlla i tag
+Comment[ja]=タグを検証
+Comment[ka]=ჭდეების შემáƒáƒ¬áƒ›áƒ”ბáƒ
+Comment[kk]=Тегтерді текÑеру
+Comment[lt]=Tikrinti gaires
+Comment[ms]=Periksa Tag
+Comment[nb]=Sjekk tagger
+Comment[nds]=XML-Betekers pröven
+Comment[ne]=टà¥à¤¯à¤¾à¤— जाà¤à¤š गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥
+Comment[nl]=Tags controleren
+Comment[nn]=Sjekk taggar
+Comment[pa]=ਟੈਗ ਜਾਂਚ
+Comment[pl]=Sprawdzenie znaczników XML
+Comment[pt]=Verificação das Marcas
+Comment[pt_BR]=Verifica Tags
+Comment[ru]=Проверить теги
+Comment[sk]=Kontrola znaÄiek
+Comment[sl]=Preveri znaÄke
+Comment[sr]=Провери ознаке
+Comment[sr@Latn]=Proveri oznake
+Comment[sv]=Kontrollera taggar
+Comment[ta]= ஒடà¯à®Ÿà¯ சரிபாரà¯à®ªà¯à®ªà¯
+Comment[tg]=Тафтиш кардани тегҳо
+Comment[tr]=Biçim İmlerini Sına
+Comment[uk]=Перевірити мітки
+Comment[zh_CN]=检查标签
+Comment[zh_TW]=檢查標籤
+ServiceTypes=KDataTool,KBabelValidator
+DataType=CatalogItem
+DataMimeTypes=application/x-kbabel-catalogitem
+ReadOnly=true
diff --git a/kbabel/datatools/xml/main.cc b/kbabel/datatools/xml/main.cc
new file mode 100644
index 00000000..d9549014
--- /dev/null
+++ b/kbabel/datatools/xml/main.cc
@@ -0,0 +1,206 @@
+/* This file is part of KBabel
+ based Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ 2002-2003 Stanislav Visnovsky <visnovsky@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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#include <resources.h>
+#include "catalogitem.h"
+#include "catalogsettings.h"
+#include "main.h"
+
+#include <qdom.h>
+
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+
+/***************************************************
+ *
+ * Factory
+ *
+ ***************************************************/
+
+K_EXPORT_COMPONENT_FACTORY( kbabel_xmltool, KGenericFactory<XMLTool> ( "kbabeldatatool" ) )
+
+using namespace KBabel;
+
+XMLTool::XMLTool( QObject* parent, const char* name, const QStringList & )
+ : KDataTool( parent, name ), _cache_origin( 0 )
+{
+ i18n( "what check found errors", "XML tags" );
+}
+
+bool XMLTool::run( const QString& command, void* data, const QString& datatype, const QString& mimetype )
+{
+ if ( command != "validate" )
+ {
+ kdDebug(KBABEL) << "XML Tool does only accept the command 'validate' and 'shortcut'" << endl;
+ kdDebug(KBABEL) << " The commands " << command << " is not accepted" << endl;
+ return FALSE;
+ }
+
+ // Check wether we can accept the data
+ if ( datatype != "CatalogItem" )
+ {
+ kdDebug(KBABEL) << "XML Tool only accepts datatype CatalogItem" << endl;
+ return FALSE;
+ }
+
+ if ( mimetype != "application/x-kbabel-catalogitem" )
+ {
+ kdDebug(KBABEL) << "XML Tool only accepts mimetype application/x-kbabel-catalogitem" << endl;
+ return FALSE;
+ }
+
+ if( command == "validate" )
+ {
+ CatalogItem* item = (CatalogItem*)(data);
+
+ if( _cache_origin != item->project() )
+ {
+ _context = item->project()->miscSettings().contextInfo;
+ _cache_origin = item->project();
+ }
+
+ uint correctnessLevel = 0;
+ QString msgid = item->msgid().first();
+ msgid.replace( "\\\"", "\"" ); // Change '\"' to '"'
+ msgid.replace( QRegExp( "&(?![a-zA-Z0-9]+;)" ), "&amp;" );
+ msgid.replace( _context, "" );
+ msgid.replace("\n",""); // delete newlines
+
+ if( _levelCache.contains(msgid) )
+ {
+ correctnessLevel = _levelCache[msgid];
+ }
+ else
+ {
+ // identify the level of correctness
+ if( isFullyCompliant(msgid) )
+ {
+ correctnessLevel = 0;
+ }
+ else if( isNonCaseCompliant(msgid) )
+ {
+ correctnessLevel = 1;
+ }
+ else if( isNonCaseWithoutCommonCompliant(msgid) )
+ {
+ correctnessLevel = 2;
+ }
+ else
+ {
+ correctnessLevel = 3;
+ }
+
+ _levelCache[msgid] = correctnessLevel;
+ }
+
+ bool hasError = false;
+
+ if(!item->isUntranslated())
+ {
+ QStringList str = item->msgstr(true);
+ for( QStringList::Iterator form = str.begin() ; form != str.end() ; form++ )
+ {
+ QString text=(*form);
+ text.replace( "\\\"", "\"" ); // Change '\"' to '"'
+ text.replace( QRegExp( "&(?![a-zA-Z0-9]+;)" ), "&amp;" );
+
+ // isNonCaseWithoutCommonCompliant can fail
+ // even though higher level checks works
+ // see case 2.
+ switch( correctnessLevel )
+ {
+ case 0: hasError = !isFullyCompliant(text); break;
+ case 1: hasError = !isNonCaseCompliant(text); break;
+ case 2: hasError = !isNonCaseWithoutCommonCompliant(text);
+ if (hasError)
+ {
+ hasError = !isNonCaseCompliant(text) ||
+ !isFullyCompliant(text);
+ }
+ break;
+ case 3: hasError = false; break; // the original is broken
+ default: kdWarning() << "No compliance level, this should not happen" << endl;
+ }
+ }
+ }
+
+ if(hasError)
+ {
+ item->appendError( "XML tags" );
+ }
+ else
+ {
+ item->removeError( "XML tags" );
+ }
+
+ return !hasError;
+ }
+ return FALSE;
+}
+
+bool XMLTool::isFullyCompliant( const QString& text)
+{
+ QDomDocument doc;
+ return doc.setContent("<para>" + text + "</para>" );
+}
+
+bool XMLTool::isNonCaseCompliant( const QString& text)
+{
+ QDomDocument doc;
+ QString test = text.lower();
+ return doc.setContent("<para>" + test + "</para>" );
+}
+
+bool XMLTool::isNonCaseWithoutCommonCompliant( const QString& text)
+{
+ QDomDocument doc;
+ QString test = text.lower();
+ QRegExp rx( "(<br>)|(<hr>)|(<p>)||(<\\w+@(\\w+.)*\\w+>)" );
+ test.replace( rx, "" );
+
+ QString a;
+ do
+ {
+ a = test;
+ test.replace( QRegExp("<[^_:A-Za-z/]"), "" );
+ } while( a!=test);
+
+ test.replace( QRegExp("<$"), "" );
+
+ return doc.setContent("<para>" + test + "</para>" );
+}
+
+#include "main.moc"
diff --git a/kbabel/datatools/xml/main.h b/kbabel/datatools/xml/main.h
new file mode 100644
index 00000000..65b231e8
--- /dev/null
+++ b/kbabel/datatools/xml/main.h
@@ -0,0 +1,59 @@
+/* This file is part of KBabel
+ based on Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
+ 2002-2003 Stanislav Visnovsky <visnovsky@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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+*/
+
+#ifndef __main_h__
+#define __main_h__
+
+#include "kbproject.h"
+
+#include <qmap.h>
+#include <kdatatool.h>
+
+class XMLTool : public KDataTool
+{
+ Q_OBJECT
+
+public:
+ XMLTool( QObject* parent, const char* name, const QStringList & );
+ virtual bool run( const QString& command, void* data, const QString& datatype, const QString& mimetype);
+private:
+ bool isFullyCompliant( const QString& text);
+ bool isNonCaseCompliant( const QString& text);
+ bool isNonCaseWithoutCommonCompliant( const QString& text);
+
+ QMap<QString,int> _levelCache;
+
+ KBabel::Project::Ptr _cache_origin;
+ QRegExp _context;
+};
+
+#endif
diff --git a/kbabel/filters/Makefile.am b/kbabel/filters/Makefile.am
new file mode 100644
index 00000000..ed8a0b63
--- /dev/null
+++ b/kbabel/filters/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS = gettext linguist xliff
+
+
diff --git a/kbabel/filters/gettext/Makefile.am b/kbabel/filters/gettext/Makefile.am
new file mode 100644
index 00000000..58186306
--- /dev/null
+++ b/kbabel/filters/gettext/Makefile.am
@@ -0,0 +1,20 @@
+####### General stuff
+
+INCLUDES= -I../../common -I$(srcdir)/../../common $(all_includes)
+
+kde_module_LTLIBRARIES = kbabel_gettextimport.la kbabel_gettextexport.la
+
+kbabel_gettextimport_la_SOURCES = gettextimport.cpp
+kbabel_gettextimport_la_LIBADD = ../../common/libkbabelcommon.la
+kbabel_gettextimport_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+
+kbabel_gettextexport_la_SOURCES = gettextexport.cpp
+kbabel_gettextexport_la_LIBADD = ../../common/libkbabelcommon.la
+kbabel_gettextexport_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+
+METASOURCES = AUTO
+
+service_DATA = kbabel_gettext_import.desktop kbabel_gettext_export.desktop
+servicedir = $(kde_servicesdir)
+
+gettextexport.lo: ../../common/kbprojectsettings.h
diff --git a/kbabel/filters/gettext/gettextexport.cpp b/kbabel/filters/gettext/gettextexport.cpp
new file mode 100644
index 00000000..e951847b
--- /dev/null
+++ b/kbabel/filters/gettext/gettextexport.cpp
@@ -0,0 +1,352 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer <matthias.kiefer@gmx.de>
+ 2001-2002 by Stanislav Visnovsky <visnovsky@kde.org>
+ Copyright (C) 2005,2006 by Nicolas GOUTTE <goutte@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#include "gettextexport.h"
+
+#include <resources.h>
+#include "catalog.h"
+#include "catalogitem.h"
+#include "catalogsettings.h"
+#include "kbprojectsettings.h"
+
+#include <qfile.h>
+#include <qtextcodec.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+K_EXPORT_COMPONENT_FACTORY( kbabel_gettextexport, KGenericFactory<GettextExportPlugin> ( "kbabelgettextexportfilter" ) )
+
+using namespace KBabel;
+
+GettextExportPlugin::GettextExportPlugin(QObject* parent, const char* name, const QStringList &) :
+ CatalogExportPlugin(parent,name), m_wrapWidth( -1 )
+{
+}
+
+ConversionStatus GettextExportPlugin::save(const QString& localFile , const QString& mimetype, const Catalog* catalog)
+{
+ // check, whether we know how to handle the extra data
+ if( catalog->importPluginID() != "GNU gettext")
+ return UNSUPPORTED_TYPE;
+
+ // we support on the application/x-gettext MIME type
+ if( mimetype != "application/x-gettext")
+ return UNSUPPORTED_TYPE;
+
+ QFile file(localFile);
+
+ if(file.open(IO_WriteOnly))
+ {
+ int progressRatio = QMAX(100/ QMAX(catalog->numberOfEntries(),1), 1);
+ emit signalResetProgressBar(i18n("saving file"),100);
+
+ QTextStream stream(&file);
+
+ SaveSettings _saveSettings = catalog->saveSettings();
+
+ if(_saveSettings.useOldEncoding && catalog->fileCodec())
+ {
+ stream.setCodec(catalog->fileCodec());
+ }
+ else
+ {
+ switch(_saveSettings.encoding)
+ {
+ case ProjectSettingsBase::UTF8:
+ stream.setCodec(QTextCodec::codecForName("utf-8"));
+ break;
+ case ProjectSettingsBase::UTF16:
+ stream.setCodec(QTextCodec::codecForName("utf-16"));
+ break;
+ default:
+ stream.setCodec(QTextCodec::codecForLocale());
+ break;
+ }
+ }
+
+ // only save header if it is not empty
+ const QString headerComment( catalog->header().comment() );
+ // ### TODO: why is this useful to have a header with an empty msgstr?
+ if( !headerComment.isEmpty() || !catalog->header().msgstr().isEmpty() )
+ {
+ // write header
+ writeComment( stream, headerComment );
+
+ const QString headerMsgid = catalog->header().msgid().first();
+
+ // Gettext PO files should have an empty msgid as header
+ if ( !headerMsgid.isEmpty() )
+ {
+ // ### TODO: perhaps it is grave enough for a user message
+ kdWarning() << "Non-empty msgid for the header, assuming empty msgid!" << endl << headerMsgid << "---" << endl;
+ }
+
+ // ### FIXME: if it is the header, then the msgid should be empty! (Even if KBabel has made something out of a non-header first entry!)
+ stream << "msgid \"\"\n";
+
+ writeKeyword( stream, "msgstr", catalog->header().msgstr().first() );
+
+ stream << "\n";
+ }
+
+ QStringList list;
+ for( uint counter = 0; counter < catalog->numberOfEntries() ; counter++ )
+ {
+ if(counter%10==0) {
+ emit signalProgress(counter/progressRatio);
+ }
+
+ // write entry
+ writeComment( stream, catalog->comment(counter) );
+
+ const QString msgctxt = catalog->msgctxt(counter);
+ if (! msgctxt.isEmpty() )
+ {
+ writeKeyword( stream, "msgctxt", msgctxt );
+ }
+
+ writeKeyword( stream, "msgid", catalog->msgid( counter ).first() );
+ if( catalog->pluralForm( counter ) == Gettext )
+ {
+ writeKeyword( stream, "msgid_plural", catalog->msgid( counter ).last() );
+ }
+
+ if( catalog->pluralForm(counter) != Gettext)
+ {
+ writeKeyword( stream, "msgstr", catalog->msgstr( counter ).first() );
+ }
+ else
+ {
+ kdDebug(KBABEL) << "Saving gettext plural form" << endl;
+ const int forms = catalog->msgstr( counter ).count();
+ for ( int i = 0; i < forms; ++i )
+ {
+ QString keyword ( "msgstr[" );
+ keyword += QString::number( i );
+ keyword += ']';
+
+ writeKeyword( stream, keyword, *( catalog->msgstr( counter ).at( i ) ) );
+ }
+ }
+
+ stream << "\n";
+
+ kapp->processEvents(10);
+ if( isStopped() )
+ {
+ return STOPPED;
+ }
+ }
+
+ if( _saveSettings.saveObsolete )
+ {
+ QValueList<QString>::ConstIterator oit;
+
+ QStringList _obsolete = catalog->catalogExtraData();
+
+ for( oit = _obsolete.begin(); oit != _obsolete.end(); ++oit )
+ {
+ stream << (*oit) << "\n\n";
+
+ kapp->processEvents(10);
+ if( isStopped() )
+ {
+ return STOPPED;
+ }
+ }
+ }
+
+ emit signalProgress(100);
+ file.close();
+
+ emit signalClearProgressBar();
+ }
+ else
+ {
+ //emit signalError(i18n("Wasn't able to open file %1").arg(filename.ascii()));
+ return OS_ERROR;
+ }
+
+ return OK;
+}
+
+void GettextExportPlugin::writeComment( QTextStream& stream, const QString& comment ) const
+{
+ if( !comment.isEmpty() )
+ {
+ // We must check that each comment line really starts with a #, to avoid syntax errors
+ int pos = 0;
+ for(;;)
+ {
+ const int newpos = comment.find( '\n', pos, false );
+ if ( newpos == pos )
+ {
+ ++pos;
+ stream << "\n";
+ continue;
+ }
+ const QString span ( ( newpos == -1 ) ? comment.mid( pos ) : comment.mid( pos, newpos-pos ) );
+
+ const int len = span.length();
+ QString spaces; // Stored leading spaces
+ for ( int i = 0 ; i < len ; ++i )
+ {
+ const QChar& ch = span[ i ];
+ if ( ch == '#' )
+ {
+ stream << spaces << span.mid( i );
+ break;
+ }
+ else if ( ch == ' ' || ch == '\t' )
+ {
+ // We have a leading white space character, so store it temporary
+ spaces += ch;
+ }
+ else
+ {
+ // Not leading white space and not a # character. so consider that the # character was missing at first position.
+ stream << "# " << spaces << span.mid( i );
+ break;
+ }
+ }
+ stream << "\n";
+
+ if ( newpos == -1 )
+ break;
+ else
+ pos = newpos + 1;
+ }
+ }
+}
+
+void GettextExportPlugin::writeKeyword( QTextStream& stream, const QString& keyword, const QString& text ) const
+{
+ if ( text.isEmpty() )
+ {
+ // Whatever the wrapping mode, an empty line is an empty line
+ stream << keyword << " \"\"\n";
+ return;
+ }
+ else if ( m_wrapWidth == -1 )
+ {
+ // Traditional KBabel wrapping
+ QStringList list = QStringList::split( '\n', text );
+
+ if ( text.startsWith( "\n" ) )
+ list.prepend( QString() );
+
+ if(list.isEmpty())
+ list.append( QString() );
+
+ if( list.count() > 1 )
+ list.prepend( QString() );
+
+ stream << keyword << " ";
+
+ QStringList::const_iterator it;
+ for( it = list.constBegin(); it != list.constEnd(); ++it )
+ {
+ stream << "\"" << (*it) << "\"\n";
+ }
+ return;
+ }
+ else if ( ( !m_wrapWidth )
+ || ( m_wrapWidth < 0 ) // Unknown special wrapping, so assume "no wrap" instead
+ )
+ {
+ // No wrapping (like Gettext's --no.wrap or -w0 )
+
+ // we need to remove the \n characters, as they are extra characters
+ QString realText( text );
+ realText.remove( '\n' );
+ stream << keyword << " \"" << realText << "\"\n";
+ return;
+ }
+
+ // ### TODO: test!
+ // Normal wrapping like Gettext's -w parameter with a value bigger than 0
+ // From here on, we assume that we have an non-empty text and a positive non-null m_wrapWidth
+
+ // we need to remove the \n characters, as they are extra characters
+ QString realText( text );
+ realText.remove( '\n' );
+
+ bool needFirstEmptyLine = false;
+ if ( realText.find( "\\n" ) != -1 )
+ {
+ // We have more than one (logical) line, so write the extra empty line
+ needFirstEmptyLine = true;
+ }
+ else
+ {
+ // We must see if the text would fit in one line, including the keyword, a space and two quote characters.
+ const int rest = text.length() + keyword.length() + 3 - m_wrapWidth;
+ if ( rest > 0 )
+ {
+ needFirstEmptyLine = true;
+ }
+ }
+ int availableWidth = m_wrapWidth;
+ if ( needFirstEmptyLine )
+ {
+ stream << keyword << " \"\"\n";
+ }
+ else
+ {
+ stream << keyword << " ";
+ availableWidth -= keyword.length();
+ availableWidth--; // The space after the keyword
+ }
+
+ const int spanLength = realText.length();
+ for ( int pos = 0; pos < spanLength; )
+ {
+ availableWidth -= 2; // Count the quote characters
+ if ( availableWidth < 2 )
+ {
+ // Be sure that at least two useful characters are written, even if the wrap width is too small
+ availableWidth = 2;
+ }
+ const int newlinePos = realText.find ( "\\n", pos );
+ if ( ( newlinePos >= 0 ) && ( newlinePos - pos + 2 < availableWidth ) )
+ {
+ // The newline is near than the maximum available numbers of characters
+ availableWidth = newlinePos - pos + 2;
+ }
+ stream << '\"' << realText.mid( pos, availableWidth ) << "\"\n";
+ pos += availableWidth;
+ }
+}
diff --git a/kbabel/filters/gettext/gettextexport.h b/kbabel/filters/gettext/gettextexport.h
new file mode 100644
index 00000000..81cbe9c4
--- /dev/null
+++ b/kbabel/filters/gettext/gettextexport.h
@@ -0,0 +1,88 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002 by Stanislav Visnovsky <visnovsky@kde.org>
+ Copyright (C) 2006 by Nicolas GOUTTE <goutte@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef GETTEXTEXPORTPLUGIN_H
+#define GETTEXTEXPORTPLUGIN_H
+
+#include <catalogfileplugin.h>
+
+#include <qstringlist.h>
+
+namespace KBabel {
+class Catalog;
+}
+class KURL;
+class QFile;
+class QTextCodec;
+
+/**
+ * @brief The class for exporting GNU gettext PO files.
+ *
+ * As an extra information, it stores the list of all obsolete entries.
+ */
+
+class GettextExportPlugin: public KBabel::CatalogExportPlugin
+{
+public:
+ GettextExportPlugin(QObject* parent, const char* name, const QStringList &);
+ virtual KBabel::ConversionStatus save(const QString& file, const QString& mimetype, const KBabel::Catalog* catalog);
+
+private:
+ /**
+ * Write a PO comment to @p stream and take care that each comment lines start with a # character
+ */
+ void writeComment( QTextStream& stream, const QString& comment ) const;
+
+ /**
+ * Write a PO keyword (msgctxt, msgid, msgstr, msgstr_plural, msgstr[0]) and the corresponding text.
+ * This includes wrapping the text.
+ */
+ void writeKeyword( QTextStream& stream, const QString& keyword, const QString& text ) const;
+
+public:
+ /**
+ * @brief Width of the wrap
+ *
+ * This is the width of the wrap in characters (not bytes), including everything
+ * (e.g. keyword, quote characters, spaces).
+ *
+ * - A value of 0 means no wrap
+ * - A value of -1 means the traditional KBabel wrapping
+ * - Other negative values are reserved for future extensions (by default: no wrap)
+ * @note
+ * - Gettext's default value is 78 characters
+ * - Too small values might not be correctly supported.
+ */
+ int m_wrapWidth;
+};
+
+#endif
diff --git a/kbabel/filters/gettext/gettextimport.cpp b/kbabel/filters/gettext/gettextimport.cpp
new file mode 100644
index 00000000..3f54301d
--- /dev/null
+++ b/kbabel/filters/gettext/gettextimport.cpp
@@ -0,0 +1,821 @@
+// kate: space-indent on; indent-width 3; replace-tabs on;
+
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer <matthias.kiefer@gmx.de>
+ 2001-2003 by Stanislav Visnovsky <visnovsky@kde.org>
+ Copyright (C) 2006 by Nicolas GOUTTE <nicolasg@snafu.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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#include "gettextimport.h"
+
+#include <catalogitem.h>
+#include <resources.h>
+
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qregexp.h>
+#include <qtextcodec.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <klocale.h>
+
+K_EXPORT_COMPONENT_FACTORY( kbabel_gettextimport, KGenericFactory<GettextImportPlugin> ( "kbabelgettextimportfilter" ) )
+
+using namespace KBabel;
+
+GettextImportPlugin::GettextImportPlugin(QObject* parent, const char* name, const QStringList &) : CatalogImportPlugin(parent,name)
+{
+}
+
+ConversionStatus GettextImportPlugin::load(const QString& filename, const QString&)
+{
+ kdDebug( KBABEL ) << k_funcinfo << endl;
+
+ if ( filename.isEmpty() ) {
+ kdDebug(KBABEL) << "fatal error: empty filename to open" << endl;
+ return NO_FILE;
+ }
+
+ QFileInfo info(filename);
+
+ if(!info.exists() || info.isDir())
+ return NO_FILE;
+
+ if(!info.isReadable())
+ return NO_PERMISSIONS;
+
+ QFile file(filename);
+
+ if ( !file.open( IO_ReadOnly ) )
+ return NO_PERMISSIONS;
+
+ uint oldPercent = 0;
+ emit signalResetProgressBar(i18n("loading file"),100);
+
+ QByteArray ba = file.readAll();
+ file.close();
+
+ // find codec for file
+ bool hadCodec;
+ QTextCodec* codec=codecForArray( ba, &hadCodec );
+
+ bool recoveredErrorInHeader = false;
+
+ QTextStream stream(ba,IO_ReadOnly);
+
+ if(codec)
+ stream.setCodec(codec);
+ else
+ {
+ kdWarning() << "No encoding declared or found, using UTF-8" << endl;
+ stream.setEncoding( QTextStream::UnicodeUTF8 );
+#ifdef __GNUC__
+# warning Default UTF-8 encoding needs to be improved
+#endif
+ // Templates define CHARSET, so if e make it a recoverable error, the template is not loadable anymore, as for templates recoverable errors are disqualifying.
+ //recoveredErrorInHeader = true;
+ }
+
+ QIODevice *dev = stream.device();
+ int fileSize = dev->size();
+
+ // if somethings goes wrong with the parsing, we don't have deleted the old contents
+ CatalogItem tempHeader;
+ QStringList tempObsolete;
+
+
+ kdDebug(KBABEL) << "start parsing..." << endl;
+
+ // first read header
+ const ConversionStatus status = readHeader(stream);
+
+
+ if ( status == RECOVERED_PARSE_ERROR )
+ {
+ kdDebug( KBABEL ) << "Recovered error in header entry" << endl;
+ recoveredErrorInHeader = true;
+ }
+ else if ( status != OK )
+ {
+ emit signalClearProgressBar();
+
+ kdDebug( KBABEL ) << "Parse error in header entry" << endl;
+ return status;
+ }
+
+ kdDebug() << "HEADER MSGID: " << _msgid << endl;
+ kdDebug() << "HEADER MSGSTR: " << _msgstr << endl;
+ if ( !_msgid.isEmpty() && !_msgid.first().isEmpty() )
+ {
+ // The header must have an empty msgid
+ kdWarning(KBABEL) << "Header entry has non-empty msgid. Creating a temporary header! " << _msgid << endl;
+ tempHeader.setMsgid( QStringList() );
+ QStringList tmp;
+ tmp.append(
+ "Content-Type: text/plain; charset=UTF-8\\n" // Unknown charset
+ "Content-Transfer-Encoding: 8bit\\n"
+ "Mime-Version: 1.0" );
+ tempHeader.setMsgstr( tmp );
+ // We keep the comment of the first entry, as it might really be a header comment (at least partially)
+ const QString comment( "# Header entry was created by KBabel!\n#\n" + _comment );
+ tempHeader.setComment( comment );
+ recoveredErrorInHeader = true;
+ }
+ else
+ {
+ tempHeader.setMsgid( _msgid );
+ tempHeader.setMsgstr( _msgstr );
+ tempHeader.setComment( _comment );
+ }
+ if(tempHeader.isFuzzy())
+ {
+ tempHeader.removeFuzzy();
+ }
+
+ // check if header seems to indicate docbook content generated by xml2pot
+ const bool docbookContent = (tempHeader.msgstr().find("application/x-xml2pot") != tempHeader.msgstr().end());
+
+ // now parse the rest of the file
+ uint counter=0;
+ QValueList<uint> errorIndex;
+ bool recoveredError=false;
+ bool docbookFile=false;
+
+ while( !stream.eof() )
+ {
+ kapp->processEvents(10);
+ if( isStopped() )
+ {
+ return STOPPED;
+ }
+
+ const ConversionStatus success=readEntry(stream);
+
+ if(success==OK)
+ {
+ if( _obsolete )
+ {
+ tempObsolete.append(_comment);
+ }
+ else
+ {
+ CatalogItem tempCatItem;
+ tempCatItem.setMsgctxt( _msgctxt );
+ tempCatItem.setMsgid( _msgid );
+ tempCatItem.setMsgstr( _msgstr );
+ tempCatItem.setComment( _comment );
+ tempCatItem.setGettextPluralForm( _gettextPluralForm );
+
+ // add new entry to the list of entries
+ appendCatalogItem(tempCatItem);
+ // check if first comment seems to indicate a docbook source file
+ if(counter==0)
+ docbookFile = ( tempCatItem.comment().find(".docbook") != -1 );
+ }
+ }
+ else if(success==RECOVERED_PARSE_ERROR)
+ {
+ kdDebug( KBABEL ) << "Recovered parse error in entry: " << counter << endl;
+ recoveredError=true;
+ errorIndex.append(counter);
+
+ CatalogItem tempCatItem;
+ tempCatItem.setMsgctxt( _msgctxt );
+ tempCatItem.setMsgid( _msgid );
+ tempCatItem.setMsgstr( _msgstr );
+ tempCatItem.setComment( _comment );
+ tempCatItem.setGettextPluralForm( _gettextPluralForm );
+
+ // add new entry to the list of entries
+ appendCatalogItem(tempCatItem);
+ }
+ else if ( success == PARSE_ERROR )
+ {
+ kdDebug( KBABEL ) << "Parse error in entry: " << counter << endl;
+ return PARSE_ERROR;
+ }
+ else
+ {
+ kdWarning( KBABEL ) << "Unknown success status, assumig parse error " << success << endl;
+ return PARSE_ERROR;
+ }
+ counter++;
+
+ const uint newPercent = (100*dev->at())/fileSize;
+ if(newPercent > oldPercent)
+ {
+ oldPercent = newPercent;
+ emit signalProgress(oldPercent);
+ }
+ }
+
+
+ // to be sure it is set to 100, if someone don't connect to
+ // signalClearProgressBar()
+ emit signalProgress(100);
+
+ emit signalClearProgressBar();
+
+
+ // ### TODO: can we check that there is no useful entry?
+ if ( !counter )
+ {
+ // Empty file? (Otherwise, there would be a try of getting an entry and the count would be 1 !)
+ kdDebug( KBABEL ) << k_funcinfo << " Empty file?" << endl;
+ return PARSE_ERROR;
+ }
+
+ kdDebug(KBABEL) << k_funcinfo << " ready" << endl;
+
+ // We have succesfully loaded the file (perhaps with recovered errors)
+
+ setGeneratedFromDocbook(docbookContent || docbookFile);
+
+ setHeader(tempHeader);
+ setCatalogExtraData(tempObsolete);
+ setErrorIndex(errorIndex);
+
+ if(hadCodec)
+ setFileCodec(codec);
+ else
+ setFileCodec(0);
+
+ setMimeTypes( "application/x-gettext" );
+
+ if ( recoveredErrorInHeader )
+ {
+ kdDebug( KBABEL ) << k_funcinfo << " Returning: header error" << endl;
+ return RECOVERED_HEADER_ERROR;
+ }
+ else if ( recoveredError )
+ {
+ kdDebug( KBABEL ) << k_funcinfo << " Returning: recovered parse error" << endl;
+ return RECOVERED_PARSE_ERROR;
+ }
+ else
+ {
+ kdDebug( KBABEL ) << k_funcinfo << " Returning: OK! :-)" << endl;
+ return OK;
+ }
+}
+
+QTextCodec* GettextImportPlugin::codecForArray(QByteArray& array, bool* hadCodec)
+{
+ if(hadCodec)
+ {
+ *hadCodec=false;
+ }
+
+ QTextStream stream( array, IO_ReadOnly );
+ // ### TODO Qt4: see if it can be done with QByteArray alone, in an encoding-neutral way.
+ // Set ISO-8859-1 as it is a relatively neutral encoding when reading (compared to UTF-8 or a random locale encoing)
+ stream.setEncoding( QTextStream::Latin1 );
+
+ // first read header
+ ConversionStatus status = readHeader(stream);
+ if(status!=OK && status != RECOVERED_PARSE_ERROR)
+ {
+ kdDebug(KBABEL) << "wasn't able to read header" << endl;
+ return 0;
+ }
+
+ const QString head = _msgstr.first();
+
+ QRegExp regexp("Content-Type:\\s*\\w+/[-\\w]+;?\\s*charset\\s*=\\s*(\\S+)\\s*\\\\n");
+ if( regexp.search( head ) == -1 )
+ {
+ kdDebug(KBABEL) << "no charset entry found" << endl;
+ return 0;
+ }
+
+ const QString charset = regexp.cap(1);
+ kdDebug(KBABEL) << "charset: " << charset << endl;
+
+ QTextCodec* codec=0;
+
+ if(!charset.isEmpty())
+ {
+ // "CHARSET" is the default charset entry in a template (pot).
+ // characters in a template should be either pure ascii or
+ // at least utf8, so utf8-codec can be used for both.
+ if( charset == "CHARSET")
+ {
+ if(hadCodec)
+ *hadCodec=false;
+
+ codec=QTextCodec::codecForName("utf8");
+ kdDebug(KBABEL)
+ << QString("file seems to be a template: using utf-8 encoding.")
+ << endl;
+ }
+ else
+ {
+ codec=QTextCodec::codecForName(charset.latin1());
+ if(hadCodec)
+ *hadCodec=true;
+ }
+
+ if(!codec)
+ {
+ kdWarning(KBABEL) << "charset found, but no codec available, using UTF-8 instead" << endl;
+ }
+ }
+ else
+ {
+ // No charset? So it is probably ASCII, therefore UTF-8
+ kdWarning(KBABEL) << "No charset defined! Assuming UTF-8!" << endl;
+ }
+
+
+ return codec;
+}
+
+ConversionStatus GettextImportPlugin::readHeader(QTextStream& stream)
+{
+ CatalogItem temp;
+ int filePos=stream.device()->at();
+ ConversionStatus status=readEntry(stream);
+
+ if(status==OK || status==RECOVERED_PARSE_ERROR)
+ {
+ // test if this is the header
+ if(!_msgid.first().isEmpty())
+ {
+ stream.device()->at(filePos);
+ }
+
+ return status;
+ }
+
+ return PARSE_ERROR;
+}
+
+ConversionStatus GettextImportPlugin::readEntry(QTextStream& stream)
+{
+ //kdDebug( KBABEL ) << k_funcinfo << " START" << endl;
+ enum {Begin,Comment,Msgctxt,Msgid,Msgstr} part=Begin;
+
+ QString line;
+ bool error=false;
+ bool recoverableError=false;
+ bool seenMsgctxt=false;
+ _msgstr.clear();
+ _msgstr.append(QString());
+ _msgid.clear();
+ _msgid.append(QString());
+ _msgctxt=QString();
+ _comment=QString();
+ _gettextPluralForm=false;
+ _obsolete=false;
+
+ QStringList::Iterator msgstrIt=_msgstr.begin();
+
+ while( !stream.eof() )
+ {
+ const int pos=stream.device()->at();
+
+ line=stream.readLine();
+
+ //kdDebug() << "Parsing line: " << line << endl;
+
+ // ### Qt4: no need of a such a check
+ if(line.isNull()) // file end
+ break;
+ else if ( line.startsWith( "<<<<<<<" ) || line.startsWith( "=======" ) || line.startsWith( ">>>>>>>" ) )
+ {
+ // We have found a CVS/SVN conflict marker. Abort.
+ // (It cannot be any useful data of the PO file, as otherwise the line would start with at least a quote)
+ kdError(KBABEL) << "CVS/SVN conflict marker found! Aborting!" << endl << line << endl;
+ return PARSE_ERROR;
+ }
+
+ // remove whitespaces from beginning and end of line
+ line=line.stripWhiteSpace();
+
+ if(part==Begin)
+ {
+ // ignore trailing newlines
+ if(line.isEmpty())
+ continue;
+
+ if(line.startsWith("#~"))
+ {
+ _obsolete=true;
+ part=Comment;
+ _comment=line;
+ }
+ else if(line.startsWith("#"))
+ {
+ part=Comment;
+ _comment=line;
+ }
+ else if(line.find(QRegExp("^msgctxt\\s*\".*\"$")) != -1)
+ {
+ part=Msgctxt;
+
+ // remove quotes at beginning and the end of the lines
+ line.remove(QRegExp("^msgctxt\\s*\""));
+ line.remove(QRegExp("\"$"));
+ _msgctxt=line;
+ seenMsgctxt=true;
+ }
+ else if(line.find(QRegExp("^msgid\\s*\".*\"$")) != -1)
+ {
+ part=Msgid;
+
+ // remove quotes at beginning and the end of the lines
+ line.remove(QRegExp("^msgid\\s*\""));
+ line.remove(QRegExp("\"$"));
+
+ (*(_msgid).begin())=line;
+ }
+ // one of the quotation marks is missing
+ else if(line.find(QRegExp("^msgid\\s*\"?.*\"?$")) != -1)
+ {
+ part=Msgid;
+
+ // remove quotes at beginning and the end of the lines
+ line.remove(QRegExp("^msgid\\s*\"?"));
+ line.remove(QRegExp("\"$"));
+
+ (*(_msgid).begin())=line;
+
+ if(!line.isEmpty())
+ recoverableError=true;
+ }
+ else
+ {
+ kdDebug(KBABEL) << "no comment, msgctxt or msgid found after a comment: " << line << endl;
+ error=true;
+ break;
+ }
+ }
+ else if(part==Comment)
+ {
+ if(line.isEmpty() && _obsolete ) return OK;
+ if(line.isEmpty() )
+ continue;
+ else if(line.startsWith("#~"))
+ {
+ _comment+=("\n"+line);
+ _obsolete=true;
+ }
+ else if(line.startsWith("#"))
+ {
+ _comment+=("\n"+line);
+ }
+ else if(line.find(QRegExp("^msgctxt\\s*\".*\"$")) != -1)
+ {
+ part=Msgctxt;
+
+ // remove quotes at beginning and the end of the lines
+ line.remove(QRegExp("^msgctxt\\s*\""));
+ line.remove(QRegExp("\"$"));
+ _msgctxt=line;
+ seenMsgctxt=true;
+ }
+ else if(line.find(QRegExp("^msgid\\s*\".*\"$")) != -1)
+ {
+ part=Msgid;
+
+ // remove quotes at beginning and the end of the lines
+ line.remove(QRegExp("^msgid\\s*\""));
+ line.remove(QRegExp("\"$"));
+
+ (*(_msgid).begin())=line;
+ }
+ // one of the quotation marks is missing
+ else if(line.find(QRegExp("^msgid\\s*\"?.*\"?$")) != -1)
+ {
+ part=Msgid;
+
+ // remove quotes at beginning and the end of the lines
+ line.remove(QRegExp("^msgid\\s*\"?"));
+ line.remove(QRegExp("\"$"));
+
+ (*(_msgid).begin())=line;
+
+ if(!line.isEmpty())
+ recoverableError=true;
+ }
+ else
+ {
+ kdDebug(KBABEL) << "no comment or msgid found after a comment while parsing: " << _comment << endl;
+ error=true;
+ break;
+ }
+ }
+ else if(part==Msgctxt)
+ {
+ if(line.isEmpty())
+ continue;
+ else if(line.find(QRegExp("^\".*\\n?\"$")) != -1)
+ {
+ // remove quotes at beginning and the end of the lines
+ line.remove(QRegExp("^\""));
+ line.remove(QRegExp("\"$"));
+
+ // add Msgctxt line to item
+ if(_msgctxt.isEmpty())
+ _msgctxt=line;
+ else
+ _msgctxt+=("\n"+line);
+ }
+ else if(line.find(QRegExp("^msgid\\s*\".*\"$")) != -1)
+ {
+ part=Msgid;
+
+ // remove quotes at beginning and the end of the lines
+ line.remove(QRegExp("^msgid\\s*\""));
+ line.remove(QRegExp("\"$"));
+
+ (*(_msgid).begin())=line;
+ }
+ // one of the quotation marks is missing
+ else if(line.find(QRegExp("^msgid\\s*\"?.*\"?$")) != -1)
+ {
+ part=Msgid;
+
+ // remove quotes at beginning and the end of the lines
+ line.remove(QRegExp("^msgid\\s*\"?"));
+ line.remove(QRegExp("\"$"));
+
+ (*(_msgid).begin())=line;
+
+ if(!line.isEmpty())
+ recoverableError=true;
+ }
+ else
+ {
+ kdDebug(KBABEL) << "no msgid found after a msgctxt while parsing: " << _msgctxt << endl;
+ error=true;
+ break;
+ }
+ }
+ else if(part==Msgid)
+ {
+ if(line.isEmpty())
+ continue;
+ else if(line.find(QRegExp("^\".*\\n?\"$")) != -1)
+ {
+ // remove quotes at beginning and the end of the lines
+ line.remove(QRegExp("^\""));
+ line.remove(QRegExp("\"$"));
+
+ QStringList::Iterator it;
+ if(_gettextPluralForm)
+ it = _msgid.fromLast();
+ else
+ it = _msgid.begin();
+
+ // add Msgid line to item
+ if((*it).isEmpty())
+ (*it)=line;
+ else
+ (*it)+=("\n"+line);
+ }
+ else if(line.find(QRegExp("^msgid_plural\\s*\".*\"$")) != -1)
+ {
+ part=Msgid;
+ _gettextPluralForm = true;
+
+ // remove quotes at beginning and the end of the lines
+ line.remove(QRegExp("^msgid_plural\\s*\""));
+ line.remove(QRegExp("\"$"));
+
+ _msgid.append(line);
+ }
+ // one of the quotation marks is missing
+ else if(line.find(QRegExp("^msgid_plural\\s*\"?.*\"?$")) != -1)
+ {
+ part=Msgid;
+ _gettextPluralForm = true;
+
+ // remove quotes at beginning and the end of the lines
+ line.remove(QRegExp("^msgid_plural\\s*\"?"));
+ line.remove(QRegExp("\"$"));
+
+ _msgid.append(line);
+
+ if(!line.isEmpty())
+ recoverableError=true;
+ }
+ else if(!_gettextPluralForm
+ && (line.find(QRegExp("^msgstr\\s*\".*\\n?\"$")) != -1))
+ {
+ part=Msgstr;
+
+ // remove quotes at beginning and the end of the lines
+ line.remove(QRegExp("^msgstr\\s*\"?"));
+ line.remove(QRegExp("\"$"));
+
+ (*msgstrIt)=line;
+ }
+ else if(!_gettextPluralForm
+ && line.find(QRegExp("^msgstr\\s*\"?.*\\n?\"?$")) != -1)
+ {
+ part=Msgstr;
+
+ // remove quotes at beginning and the end of the lines
+ line.remove(QRegExp("^msgstr\\s*\"?"));
+ line.remove(QRegExp("\"$"));
+
+ (*msgstrIt)=line;
+
+ if(!line.isEmpty())
+ recoverableError=true;
+ }
+ else if( _gettextPluralForm
+ && (line.find(QRegExp("^msgstr\\[0\\]\\s*\".*\\n?\"$")) != -1))
+ {
+ part=Msgstr;
+
+ // remove quotes at beginning and the end of the lines
+ line.remove(QRegExp("^msgstr\\[0\\]\\s*\"?"));
+ line.remove(QRegExp("\"$"));
+
+ (*msgstrIt)=line;
+ }
+ else if( _gettextPluralForm
+ && (line.find(QRegExp("^msgstr\\[0\\]\\s*\"?.*\\n?\"?$")) != -1))
+ {
+ part=Msgstr;
+
+ // remove quotes at beginning and the end of the lines
+ line.remove(QRegExp("^msgstr\\[0\\]\\s*\"?"));
+ line.remove(QRegExp("\"$"));
+
+ (*msgstrIt)=line;
+
+ if(!line.isEmpty())
+ recoverableError=true;
+ }
+ else if ( line.startsWith( "#" ) )
+ {
+ // ### TODO: could this be considered recoverable?
+ kdDebug(KBABEL) << "comment found after a msgid while parsing: " << _msgid.first() << endl;
+ error=true;
+ break;
+ }
+ else if ( line.startsWith( "msgid" ) )
+ {
+ kdDebug(KBABEL) << "Another msgid found after a msgid while parsing: " << _msgid.first() << endl;
+ error=true;
+ break;
+ }
+ // a line of the msgid with a missing quotation mark
+ else if(line.find(QRegExp("^\"?.+\\n?\"?$")) != -1)
+ {
+ recoverableError=true;
+
+ // remove quotes at beginning and the end of the lines
+ line.remove(QRegExp("^\""));
+ line.remove(QRegExp("\"$"));
+
+ QStringList::Iterator it;
+ if( _gettextPluralForm )
+ it = _msgid.fromLast();
+ else
+ it = _msgid.begin();
+
+ // add Msgid line to item
+ if((*it).isEmpty())
+ (*it)=line;
+ else
+ (*it)+=("\n"+line);
+ }
+ else
+ {
+ kdDebug(KBABEL) << "no msgstr found after a msgid while parsing: " << _msgid.first() << endl;
+ error=true;
+ break;
+ }
+ }
+ else if(part==Msgstr)
+ {
+ if(line.isEmpty())
+ continue;
+ // another line of the msgstr
+ else if(line.find(QRegExp("^\".*\\n?\"$")) != -1)
+ {
+ // remove quotes at beginning and the end of the lines
+ line.remove(QRegExp("^\""));
+ line.remove(QRegExp("\"$"));
+
+ if((*msgstrIt).isEmpty())
+ (*msgstrIt)=line;
+ else
+ (*msgstrIt)+=("\n"+line);
+ }
+ else if( _gettextPluralForm
+ && (line.find(QRegExp("^msgstr\\[[0-9]+\\]\\s*\".*\\n?\"$")) != -1))
+ {
+ // remove quotes at beginning and the end of the lines
+ line.remove(QRegExp("^msgstr\\[[0-9]+\\]\\s*\"?"));
+ line.remove(QRegExp("\"$"));
+
+ msgstrIt=_msgstr.append(line);
+ }
+ else if( _gettextPluralForm
+ && (line.find(QRegExp("^msgstr\\[[0-9]\\]\\s*\"?.*\\n?\"?$")) != -1))
+ {
+ // remove quotes at beginning and the end of the lines
+ line.remove(QRegExp("^msgstr\\[[0-9]\\]\\s*\"?"));
+ line.remove(QRegExp("\"$"));
+
+ msgstrIt=_msgstr.append(line);
+
+ if(!line.isEmpty())
+ recoverableError=true;
+ }
+ else if((line.find(QRegExp("^\\s*msgid")) != -1) || (line.find(QRegExp("^\\s*#")) != -1))
+ {
+ // We have read successfully one entry, so end loop.
+ stream.device()->at(pos);// reset position in stream to beginning of this line
+ break;
+ }
+ else if(line.startsWith("msgstr"))
+ {
+ kdDebug(KBABEL) << "Another msgstr found after a msgstr while parsing: " << _msgstr.last() << endl;
+ error=true;
+ break;
+ }
+ // another line of the msgstr with a missing quotation mark
+ else if(line.find(QRegExp("^\"?.+\\n?\"?$")) != -1)
+ {
+ recoverableError=true;
+
+ // remove quotes at beginning and the end of the lines
+ line.remove(QRegExp("^\""));
+ line.remove(QRegExp("\"$"));
+
+ if((*msgstrIt).isEmpty())
+ (*msgstrIt)=line;
+ else
+ (*msgstrIt)+=("\n"+line);
+ }
+ else
+ {
+ kdDebug(KBABEL) << "no msgid or comment found after a msgstr while parsing: " << _msgstr.last() << endl;
+ error=true;
+ break;
+ }
+ }
+ }
+
+/*
+ if(_gettextPluralForm)
+ {
+ kdDebug(KBABEL) << "gettext plural form:\n"
+ << "msgid:\n" << _msgid.first() << "\n"
+ << "msgid_plural:\n" << _msgid.last() << "\n" << endl;
+ int counter=0;
+ for(QStringList::Iterator it = _msgstr.begin(); it != _msgstr.end(); ++it)
+ {
+ kdDebug(KBABEL) << "msgstr[" << counter << "]:\n"
+ << (*it) << endl;
+ counter++;
+ }
+ }
+ */
+
+ //kdDebug( KBABEL ) << k_funcinfo << " NEAR RETURN" << endl;
+ if(error)
+ return PARSE_ERROR;
+ else if(recoverableError)
+ return RECOVERED_PARSE_ERROR;
+ else
+ {
+ return OK;
+ }
+}
diff --git a/kbabel/filters/gettext/gettextimport.h b/kbabel/filters/gettext/gettextimport.h
new file mode 100644
index 00000000..e28ec790
--- /dev/null
+++ b/kbabel/filters/gettext/gettextimport.h
@@ -0,0 +1,70 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef GETTEXTIMPORTPLUGIN_H
+#define GETTEXTIMPORTPLUGIN_H
+
+#include <catalogfileplugin.h>
+
+#include <qstringlist.h>
+
+class KURL;
+class QFile;
+class QTextCodec;
+
+/* ****************************************************************************
+ The class for importing GNU gettext PO files. As an extra information,
+ it stores the list of all obsolete entries.
+**************************************************************************** */
+
+class GettextImportPlugin: public KBabel::CatalogImportPlugin
+{
+public:
+ GettextImportPlugin(QObject* parent, const char* name, const QStringList &);
+ virtual KBabel::ConversionStatus load(const QString& file, const QString& mimetype);
+ virtual const QString id() { return "GNU gettext"; }
+
+private:
+ QTextCodec* codecForArray(QByteArray& arary, bool* hadCodec);
+ KBabel::ConversionStatus readHeader(QTextStream& stream);
+ KBabel::ConversionStatus readEntry(QTextStream& stream);
+
+ // description of the last read entry
+ QString _msgctxt;
+ QStringList _msgid;
+ QStringList _msgstr;
+ QString _comment;
+ bool _gettextPluralForm;
+ bool _obsolete;
+};
+
+#endif
diff --git a/kbabel/filters/gettext/kbabel_gettext_export.desktop b/kbabel/filters/gettext/kbabel_gettext_export.desktop
new file mode 100644
index 00000000..30cf0df5
--- /dev/null
+++ b/kbabel/filters/gettext/kbabel_gettext_export.desktop
@@ -0,0 +1,53 @@
+[Desktop Entry]
+Type=Service
+Name=KBabel GNU Gettext Export Filter
+Name[bg]=Филтър за екÑпортиране на GNU Gettext - KBabel
+Name[br]=Sil ezporzh GNU Gettext evit KBabel
+Name[bs]=KBabel GNU Gettext filter za izvoz
+Name[ca]=Filtre KBabel per exportar Gettext de GNU
+Name[cs]=Exportní filtr do formátu Gettext pro KBabel
+Name[cy]=Hidl Allforio GNU Gettext KBabel
+Name[da]=KBabel GNU Gettext eksportfilter
+Name[de]=GNU Gettext-Exportfilter für KBabel
+Name[el]=ΦίλτÏο εξαγωγής GNU Gettext του KBabel
+Name[es]=Filtro de exportación KBabel GNU Gettext
+Name[et]=KBabeli GNU Gettexti ekspordifilter
+Name[eu]=KBabel GNU gettext esportazio iragazkia
+Name[fa]=پالایۀ صادرات KBabel GNU Gettext
+Name[fi]=KBabel GNU Gettext -vientisuodatin
+Name[fr]=filtre d'exportation GNU Gettext pour KBabel
+Name[ga]=Scagaire Easpórtála Gettext GNU le haghaidh KBabel
+Name[gl]=Filtro de exportación de GNU/gettext para KBabel
+Name[hi]=के-बेबल गà¥à¤¨à¥‚ गेट-टेकà¥à¤¸à¥à¤Ÿ निरà¥à¤¯à¤¾à¤¤ फ़िलà¥à¤Ÿà¤°
+Name[hu]=KBabel GNU Gettext exportszűrő
+Name[is]=KBabel GNU Gettext útflutningssía
+Name[it]=Filtro di esportazione di GNU Gettext per KBabel
+Name[ja]=KBabel GNU Gettext エクスãƒãƒ¼ãƒˆãƒ•ã‚£ãƒ«ã‚¿
+Name[ka]=KBabel GNU Gettext ექსპáƒáƒ áƒ¢áƒ˜áƒ¡ ფილტრი
+Name[kk]=KBabel GNU Gettext ÑкÑпорттау ÑүзгіÑÑ–
+Name[lt]=KBabel GNU Gettext eksportavimo filtras
+Name[ms]=Penapis Eksport KBabel GNU Gettext
+Name[nb]=GNU Gettext-eksportfilter for KBabel
+Name[nds]=KBabel-Exportfilter för GNU Gettext
+Name[ne]=केबà¥à¤¯à¤¾à¤¬à¤² जीà¤à¤¨à¤¯à¥‚ गेटटेकà¥à¤¸à¥à¤Ÿ निरà¥à¤¯à¤¾à¤¤ फिलà¥à¤Ÿà¤°
+Name[nl]=KBabel GNU Gettext Exportfilter
+Name[nn]=GNU Gettext-eksportfilter for KBabel
+Name[pa]=KBabel GNU Gettext ਨਿਰਯਾਤ ਫਿਲਟਰ
+Name[pl]=Filtr KBabel do eksportu do formatu GNU Gettext
+Name[pt]=Filtro de Exportação do Gettext da GNU para o KBabel
+Name[pt_BR]=Filtro de Exportação GNU Gettext do KBabel
+Name[ru]=Фильтр ÑкÑпорта Ñообщений GNU Gettext
+Name[sk]=Exportný filter GNU gettext pre KBabel
+Name[sl]=Izvozni filter GNU Gettext za KBabel
+Name[sr]=KBabel-ов филтер за извоз у GNU Gettext
+Name[sr@Latn]=KBabel-ov filter za izvoz u GNU Gettext
+Name[sv]=Kbabel exportfilter för GNU Gettext
+Name[ta]=Kபாபேல௠GNU உரை எட௠à®à®±à¯à®±à¯à®®à®¤à®¿ வடிகடà¯à®Ÿà®¿
+Name[tg]=Филтри Ñодироти хабарҳо GNU Gettext
+Name[tr]=KBabel GNU Gettext Dışa Aktarma Süzgeci
+Name[uk]=Фільтр екÑпорту GNU Gettext Ð´Ð»Ñ KBabel
+Name[zh_CN]=KBabel GNU Gettext 导出过滤器
+Name[zh_TW]=KBabel GNU Gettext 匯出éŽæ¿¾å™¨
+X-KDE-Library=kbabel_gettextexport
+X-KDE-Export=application/x-gettext
+ServiceTypes=KBabelFilter
diff --git a/kbabel/filters/gettext/kbabel_gettext_import.desktop b/kbabel/filters/gettext/kbabel_gettext_import.desktop
new file mode 100644
index 00000000..c6b1b293
--- /dev/null
+++ b/kbabel/filters/gettext/kbabel_gettext_import.desktop
@@ -0,0 +1,53 @@
+[Desktop Entry]
+Type=Service
+Name=KBabel GNU Gettext Import Filter
+Name[bg]=Филтър за импортиране на GNU Gettext - KBabel
+Name[br]=Sil enporzh GNU Gettext evit KBabel
+Name[bs]=KBabel GNU Gettext filter za uvoz
+Name[ca]=Filtre KBabel per importar Gettext de GNU
+Name[cs]=Importní filtr Gettext pro KBabel
+Name[cy]=Hidl Mewnforio GNU Gettext KBabel
+Name[da]=KBabel GNU Gettext Import-filter
+Name[de]=GNU Gettext-Importfilter für KBabel
+Name[el]=ΦίλτÏο εισαγωγής GNU Gettext του KBabel
+Name[es]=Filtro de importación KBabel GNU Gettext
+Name[et]=KBabeli GNU Gettexti impordifilter
+Name[eu]=KBabel GNU gettext inportazio iragazkia
+Name[fa]=پالایۀ واردات KBabel GNU Gettext
+Name[fi]=KBabel GNU Gettext -tuontisuodatin
+Name[fr]=Filtre d'importation GNU Gettext pour KBabel
+Name[ga]=Scagaire Iompórtála Gettext GNU le haghaidh KBabel
+Name[gl]=Filtro de importación de GNU/gettext para KBabel
+Name[hi]=के-बेबल गà¥à¤¨à¥‚ गेट-टेकà¥à¤¸à¥à¤Ÿ आयात फ़िलà¥à¤Ÿà¤°
+Name[hu]=KBabel GNU Gettext importszűrő
+Name[is]=KBabel GNU Gettext innflutningssía
+Name[it]=Filtro di importazione di GNU Gettext per KBabel
+Name[ja]=KBabel GNU Gettext インãƒãƒ¼ãƒˆãƒ•ã‚£ãƒ«ã‚¿
+Name[ka]=KBabel GNU Gettext იმპáƒáƒ áƒ˜áƒ¡ ფილტრი
+Name[kk]=KBabel GNU Gettext импорттау ÑүзгіÑÑ–
+Name[lt]=KBabel GNU Gettext importavimo filtras
+Name[ms]=Penapis Import KBabel GNU Gettext
+Name[nb]=GNU Gettext-importfilter for KBabel
+Name[nds]=KBabel-Importfilter för GNU Gettext
+Name[ne]=केबà¥à¤¯à¤¾à¤¬à¤² जीà¤à¤¨à¤¯à¥‚ गेटटेकà¥à¤¸à¥à¤Ÿ आयात फिलà¥à¤Ÿà¤°
+Name[nl]=KBabel GNU Gettext Importfilter
+Name[nn]=GNU Gettext-importfilter for KBabel
+Name[pa]=KBabel GNU Gettext ਅਯਾਤ ਫਿਲਟਰ
+Name[pl]=Filtr KBabel do importu z formatu GNU Gettext
+Name[pt]=Filtro de Importação de Gettext da GNU para o KBabel
+Name[pt_BR]=Filtro de Importação GNU Gettext para o KBabel
+Name[ru]=Фильтр импорта Ñообщений GNU Gettext
+Name[sk]=Importný filter GNU gettext pre KBabel
+Name[sl]=Uvozni filter GNU Gettext za KBabel
+Name[sr]=KBabel-ов филтер за увоз из GNU Gettext-а
+Name[sr@Latn]=KBabel-ov filter za uvoz iz GNU Gettext-a
+Name[sv]=Kbabel importfilter för GNU Gettext
+Name[ta]=Kபாபேல௠GNU உரை எட௠இறகà¯à®•à¯à®®à®¤à®¿ வடிகடà¯à®Ÿà®¿
+Name[tg]=Филтри воридоти хабарҳо GNU Gettext
+Name[tr]=KBabel GNU Gettext İçe Aktarma Süzgeci
+Name[uk]=Фільтр імпорту GNU Gettext Ð´Ð»Ñ KBabel
+Name[zh_CN]=KBabel GNU Gettext 导入过滤器
+Name[zh_TW]=KBabel GNU Gettext 匯入éŽæ¿¾å™¨
+X-KDE-Library=kbabel_gettextimport
+X-KDE-Import=application/x-gettext
+ServiceTypes=KBabelFilter
diff --git a/kbabel/filters/linguist/Makefile.am b/kbabel/filters/linguist/Makefile.am
new file mode 100644
index 00000000..479c8052
--- /dev/null
+++ b/kbabel/filters/linguist/Makefile.am
@@ -0,0 +1,18 @@
+####### General stuff
+
+INCLUDES = -I../../common -I$(srcdir)/../../common $(all_includes)
+
+kde_module_LTLIBRARIES = kbabel_linguistexport.la kbabel_linguistimport.la
+
+kbabel_linguistexport_la_SOURCES = linguistexport.cpp
+kbabel_linguistexport_la_LIBADD = ../../common/libkbabelcommon.la
+kbabel_linguistexport_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+
+kbabel_linguistimport_la_SOURCES = linguistimport.cpp
+kbabel_linguistimport_la_LIBADD = ../../common/libkbabelcommon.la
+kbabel_linguistimport_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+
+METASOURCES = AUTO
+
+service_DATA = kbabel_linguist_export.desktop kbabel_linguist_import.desktop
+servicedir = $(kde_servicesdir)
diff --git a/kbabel/filters/linguist/kbabel_linguist_export.desktop b/kbabel/filters/linguist/kbabel_linguist_export.desktop
new file mode 100644
index 00000000..400abd26
--- /dev/null
+++ b/kbabel/filters/linguist/kbabel_linguist_export.desktop
@@ -0,0 +1,53 @@
+[Desktop Entry]
+Type=Service
+Name=KBabel Linguist Export Filter
+Name[bg]=ЛингвиÑтичен филтър за екÑпортиране - KBabel
+Name[br]=Sil ezporzh Linguist evit KBabel
+Name[bs]=KBabel Linguist filter za izvoz
+Name[ca]=Filtre KBabel per exportar Linguist
+Name[cs]=Exportní filtr do formátu Linguist pro KBabel
+Name[cy]=Hidl Allforio Ieithydd KBabel
+Name[da]=KBabel Linguist eksportfilter
+Name[de]=Linguist Export-Filter für KBabel
+Name[el]=ΦίλτÏο εξαγωγής Linguist του KBabel
+Name[es]=Filtro de exportación lingüístico de KBabel
+Name[et]=KBabeli Linguisti ekspordifilter
+Name[eu]=KBabel Linguist esportazio iragazkia
+Name[fa]=پالایۀ صادرات زبان‌شناس KBabel
+Name[fi]=KBabel Linguist -vientisuodatin
+Name[fr]=Filtre d'exportation Linguist pour KBabel
+Name[ga]=Scagaire Easpórtála Linguist le haghaidh KBabel
+Name[gl]=Filtro de exportación a Linguist para KBabel
+Name[hi]=के-बेबल लिंगà¥à¤µà¤¿à¤¸à¥à¤Ÿ निरà¥à¤¯à¤¾à¤¤ फ़िलà¥à¤Ÿà¤°
+Name[hu]=KBabel Linguist exportszűrő
+Name[is]=KBabel Linguist útflutningssía
+Name[it]=Filtro di esportazione di Linguist per KBabel
+Name[ja]=KBabel Linguist エクスãƒãƒ¼ãƒˆãƒ•ã‚£ãƒ«ã‚¿
+Name[ka]=KBabel Linguist ექსპáƒáƒ áƒ¢áƒ˜áƒ¡ ფილტრი
+Name[kk]=KBabel лингвиÑтік ÑкÑпорттау ÑүзгіÑÑ–
+Name[lt]=KBabel Linguist eksportavimo filtras
+Name[ms]=Penapis Eksport KBabel Linguist
+Name[nb]=Linguist-eksportfilter for KBabel
+Name[nds]=KBabel-Exportfilter för Linguist
+Name[ne]=केबà¥à¤¯à¤¾à¤¬à¤² बहà¥à¤­à¤¾à¤·à¥€ निरà¥à¤¯à¤¾à¤¤ फिलà¥à¤Ÿà¤°
+Name[nl]=KBabel Linguïst Exportfilter
+Name[nn]=Linguist-eksportfilter for KBabel
+Name[pa]=ਕੇਬਬੇਲ ਬੋਲੀ ਨਿਰਯਾਤ ਫਿਲਟਰ
+Name[pl]=Filtr KBabel do eksportu do formatu Linguist
+Name[pt]=Filtro de Exportação para Linguist para o KBabel
+Name[pt_BR]=Filtro de Exportação Linguist do KBabel
+Name[ru]=Фильтр ÑкÑпорта лингвиÑтичеÑких Ñообщений
+Name[sk]=Exportný filter Qt Linguist pre KBabel
+Name[sl]=Izvozni filter Linguist za KBabel
+Name[sr]=KBabel-ов филтер за извоз у Linguist
+Name[sr@Latn]=KBabel-ov filter za izvoz u Linguist
+Name[sv]=Kbabel exportfilter för Linguist
+Name[ta]=Kபாபேல௠மொழியியல௠à®à®±à¯à®±à¯à®®à®¤à®¿ வடிகடà¯à®Ÿà®¿
+Name[tg]=Филтри Ñодироти хабарҳои лингвиÑÑ‚Ó£
+Name[tr]=KBabel Linguist Dışa Aktarma Süzgeci
+Name[uk]=Фільтр екÑпорту Linguist Ð´Ð»Ñ KBabel
+Name[zh_CN]=KBabel Linguist 导出过滤器
+Name[zh_TW]=KBabel 語言匯出éŽæ¿¾å™¨
+X-KDE-Library=kbabel_linguistexport
+X-KDE-Export=application/x-linguist
+ServiceTypes=KBabelFilter
diff --git a/kbabel/filters/linguist/kbabel_linguist_import.desktop b/kbabel/filters/linguist/kbabel_linguist_import.desktop
new file mode 100644
index 00000000..ae8bd364
--- /dev/null
+++ b/kbabel/filters/linguist/kbabel_linguist_import.desktop
@@ -0,0 +1,53 @@
+[Desktop Entry]
+Type=Service
+Name=KBabel Linguist Import Filter
+Name[bg]=ЛингвиÑтичен филтър за импортиране - KBabel
+Name[br]=Sil enporzh Linguist evit KBabel
+Name[bs]=KBabel Linguist filter za izvoz
+Name[ca]=Filtre KBabel per importar Linguist
+Name[cs]=Importní filtr Linguist pro KBabel
+Name[cy]=Hidl Mewnforio Ieithydd KBabel
+Name[da]=KBabel Linguist importfilter
+Name[de]=Linguist Import-Filter für KBabel
+Name[el]=ΦίλτÏο εισαγωγής Linguist του KBabel
+Name[es]=Filtro de importación de lengua KBabel
+Name[et]=KBabeli Linguisti impordifilter
+Name[eu]=KBabel Linguist esportazio iragazkia
+Name[fa]=پالایۀ واردات زبان‌شناس KBabel
+Name[fi]=KBabel Linguist -tuontisuodatin
+Name[fr]=Filtre d'importation Linguist pour KBabel
+Name[ga]=Scagaire Iompórtála Linguist le haghaidh KBabel
+Name[gl]=Filtro de importación de Linguist para KBabel
+Name[hi]=के-बेबल लिंगà¥à¤µà¤¿à¤¸à¥à¤Ÿ आयात फ़िलà¥à¤Ÿà¤°
+Name[hu]=KBabel Linguist importszűrő
+Name[is]=KBabel Linguist innflutningssía
+Name[it]=Filtro di importazione di Linguist per KBabel
+Name[ja]=KBabel Linguist インãƒãƒ¼ãƒˆãƒ•ã‚£ãƒ«ã‚¿
+Name[ka]=KBabel Linguist იმპáƒáƒ áƒ˜áƒ¡ ფილტრი
+Name[kk]=KBabel лингвиÑтік импорттау ÑүзгіÑÑ–
+Name[lt]=KBabel Linguist importavimo filtras
+Name[ms]=Penapis Import KBabel Linguist
+Name[nb]=Linguist-importfilter for KBabel
+Name[nds]=KBabel-Importfilter för Linguist
+Name[ne]=केबà¥à¤¯à¤¾à¤¬à¤² बहà¥à¤­à¤¾à¤·à¥€ आयात फिलà¥à¤Ÿà¤°
+Name[nl]=KBabel Linguïst importfilter
+Name[nn]=Linguist-importfilter for KBabel
+Name[pa]=ਕੇਬਬੇਲ ਬੋਲੀ ਅਯਾਤ ਫਿਲਟਰ
+Name[pl]=Filtr KBabel do importu z formatu Linguist
+Name[pt]=Filtro de Importação de Linguist para o KBabel
+Name[pt_BR]=Filtro de Importação Linguist para o KBabel
+Name[ru]=Фильтр импорта лингвиÑтичеÑких Ñообщений
+Name[sk]=Importný filter Qt Linguist pre KBabel
+Name[sl]=Uvozni filter Linguist za KBabel
+Name[sr]=KBabel-ов филтер за увоз из Linguist-а
+Name[sr@Latn]=KBabel-ov filter za uvoz iz Linguist-a
+Name[sv]=Kbabel importfilter för Linguist
+Name[ta]=Kபாபேல௠மொழியியல௠இறகà¯à®•à¯à®®à®¤à®¿ வடிகடà¯à®Ÿà®¿
+Name[tg]=Филтри воридоти хабарҳои лингвиÑÑ‚Ó£
+Name[tr]=KBabel Linguist İçe Aktarma Süzgeci
+Name[uk]=Фільтр імпорту Linguist Ð´Ð»Ñ KBabel
+Name[zh_CN]=KBabel Linguist 导入过滤器
+Name[zh_TW]=KBabel 語言匯入éŽæ¿¾å™¨
+X-KDE-Library=kbabel_linguistimport
+X-KDE-Import=application/x-linguist
+ServiceTypes=KBabelFilter
diff --git a/kbabel/filters/linguist/linguistexport.cpp b/kbabel/filters/linguist/linguistexport.cpp
new file mode 100644
index 00000000..3b69e20a
--- /dev/null
+++ b/kbabel/filters/linguist/linguistexport.cpp
@@ -0,0 +1,214 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2001-2002 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+ 2002-2003 by Marco Wegner
+ <mail@marcowegner.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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#include <qfile.h>
+#include "qregexp.h"
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qtextstream.h>
+
+#include <kgenericfactory.h>
+
+#include "catalog.h"
+#include "catalogitem.h"
+#include "catalogsettings.h"
+#include "linguistexport.h"
+
+K_EXPORT_COMPONENT_FACTORY( kbabel_linguistexport, KGenericFactory<LinguistExportPlugin> ( "kbabellinguistexportfilter" ) )
+
+using namespace KBabel;
+
+LinguistExportPlugin::LinguistExportPlugin( QObject * parent, const char * name, const QStringList& )
+ : CatalogExportPlugin( parent, name )
+{
+}
+
+ConversionStatus LinguistExportPlugin::save( const QString& filename, const QString&, const Catalog * catalog )
+{
+ // Check whether we know how to handle the extra data.
+ if ( catalog->importPluginID( ) != "Qt translation source" )
+ return UNSUPPORTED_TYPE;
+
+ QFile file( filename );
+ if ( !file.open( IO_WriteOnly ) )
+ return OS_ERROR;
+
+ SaveSettings settings = catalog->saveSettings( );
+
+ // New DOM document.
+ QDomDocument doc( "TS" );
+ // Create the root element.
+ doc.appendChild( doc.createElement( "TS" ) );
+
+ // Create a default context just in case none is given in the messages.
+ context = "Default"; // ### FIXME: Qt's default seems named "@default"
+
+ bool fuzzy;
+
+ // Regular messages.
+ for ( uint i = 0; i < catalog->numberOfEntries( ); i++ ) {
+ QString comment( extractComment( doc, catalog->comment( i ), fuzzy ) );
+ createMessage( doc, catalog->msgid( i ).join( "" ), catalog->msgstr( i ).join( "" ),
+ comment, false, fuzzy );
+ }
+
+ // Obsolete messages.
+ if ( settings.saveObsolete ) {
+ QValueList<CatalogItem> obsMessages = catalog->obsoleteEntries( );
+ QValueList<CatalogItem>::Iterator it;
+ for ( it = obsMessages.begin( ); it != obsMessages.end( ); ++it ) {
+ QString comment( extractComment( doc, (*it).comment( ), fuzzy ) );
+ createMessage( doc, (*it).msgid( true ).join( "" ), (*it).msgstr( true ).join( "" ),
+ comment, true, fuzzy );
+ }
+ }
+
+ QTextStream stream( &file );
+ doc.save( stream, 2 );
+ file.close( );
+
+ return OK;
+}
+
+const QString LinguistExportPlugin::extractComment( QDomDocument& doc, const QString& s, bool& fuzzy )
+{
+ fuzzy = false;
+ QString comment( s );
+ if ( !comment.isEmpty( ) ) {
+ // Extract the context and the actual comment.
+ comment.remove( QRegExp( "^Context:[\\s]*" ) );
+ /*
+ * HACK
+ *
+ * KBabel has not any flag to tell "this entry is fuzzy!"
+ * but it uses the corresponding Gettext comment instead.
+ *
+ * Therefore we have little choice, but to use "#, fuzzy" in the comment,
+ * even if it is very Linguist-unlike. So the "#, fuzzy" must be removed before
+ * writing the comment for Linguist
+ */
+
+ int pos = comment.find("#, fuzzy");
+ if ( pos >= 0) {
+ fuzzy = true;
+ comment.remove("#, fuzzy");
+ }
+
+ QString newContext;
+ pos = comment.find( '\n' );
+ if ( pos >= 0 ) {
+ newContext = comment.left( pos );
+ comment.replace( 0, pos + 1, "" ); // ### TODO: use QString::remove
+ } else {
+ newContext = comment;
+ comment = ""; // ### TODO: use QString() instead of ""
+ }
+ setContext( doc, newContext );
+ }
+ return comment;
+}
+
+void LinguistExportPlugin::createMessage( QDomDocument& doc, const QString& msgid,
+ const QString& msgstr, const QString& comment,
+ const bool obsolete, const bool fuzzy )
+{
+ QDomElement elem;
+ QDomText text;
+
+ QDomElement messageElement = doc.createElement( "message" );
+
+ elem = doc.createElement( "source" );
+ text = doc.createTextNode( msgid );
+ elem.appendChild( text );
+ messageElement.appendChild( elem );
+
+ if ( !comment.isEmpty( ) ) {
+ elem = doc.createElement( "comment" );
+ text = doc.createTextNode( comment );
+ elem.appendChild( text );
+ messageElement.appendChild( elem );
+ }
+
+ elem = doc.createElement( "translation" );
+ if ( obsolete )
+ elem.setAttribute( "type", "obsolete" );
+ else if ( msgstr.isEmpty( ) || fuzzy ) {
+ elem.setAttribute( "type", "unfinished" );
+ }
+ if ( !msgstr.isEmpty())
+ {
+ text = doc.createTextNode( msgstr );
+ elem.appendChild( text );
+ }
+ messageElement.appendChild( elem );
+ contextElement.appendChild( messageElement );
+}
+
+void LinguistExportPlugin::setContext( QDomDocument& doc, QString newContext )
+{
+ // Nothing to do here.
+ if ( newContext == context )
+ return;
+
+ // Find out whether there is already such a context in the QDomDocument.
+ QDomNode node = doc.documentElement( ).firstChild( );
+ while ( !node.isNull( ) ) {
+ if ( node.isElement( ) ) {
+ QDomElement elem = node.firstChild( ).toElement( );
+ if ( elem.isElement( ) && elem.tagName( ) == "name" && elem.text( ) == newContext ) {
+ // We found the context.
+ context = newContext;
+ contextElement = node.toElement( );
+ // Nothing more to do.
+ return;
+ }
+ }
+ node = node.nextSibling( );
+ }
+
+ // Create new context element.
+ contextElement = doc.createElement( "context" );
+ doc.documentElement( ).appendChild( contextElement );
+ // Appropriate name element.
+ QDomElement nameElement = doc.createElement( "name" );
+ QDomText text = doc.createTextNode( newContext );
+ nameElement.appendChild( text );
+ contextElement.appendChild( nameElement );
+ // Store new context.
+ context = newContext;
+}
diff --git a/kbabel/filters/linguist/linguistexport.h b/kbabel/filters/linguist/linguistexport.h
new file mode 100644
index 00000000..3201f95f
--- /dev/null
+++ b/kbabel/filters/linguist/linguistexport.h
@@ -0,0 +1,68 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+ 2002-2003 by Marco Wegner
+ <mail@marcowegner.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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#ifndef LINGUISTEXPORT_H
+#define LINGUISTEXPORT_H
+
+#include <qdom.h>
+
+#include "catalogfileplugin.h"
+
+class QString;
+class QStringList;
+
+namespace KBabel {
+class Catalog;
+}
+
+class LinguistExportPlugin : public KBabel::CatalogExportPlugin
+{
+ public:
+ LinguistExportPlugin( QObject * parent, const char * name, const QStringList& );
+ virtual KBabel::ConversionStatus save( const QString& filename, const QString& mimetype, const KBabel::Catalog * catalog );
+
+ private:
+ const QString extractComment( QDomDocument& doc, const QString& s, bool& fuzzy );
+ void createMessage( QDomDocument& doc, const QString& msgid, const QString& msgstr,
+ const QString& comment, const bool obsolete, const bool fuzzy );
+ void setContext( QDomDocument& doc, QString newContext );
+
+ private:
+ QString context;
+ QDomElement contextElement;
+};
+
+#endif // LINGUISTEXPORT_H
diff --git a/kbabel/filters/linguist/linguistimport.cpp b/kbabel/filters/linguist/linguistimport.cpp
new file mode 100644
index 00000000..220c0634
--- /dev/null
+++ b/kbabel/filters/linguist/linguistimport.cpp
@@ -0,0 +1,193 @@
+// kate: space-indent on; indent-width 2; replace-tabs on;
+
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2001-2002 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+ 2002-2003 by Marco Wegner
+ <mail@marcowegner.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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+// Qt include files
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qobject.h>
+#include <qregexp.h>
+#include <qstring.h>
+#include <qstringlist.h>
+// KDE include files
+#include <kdebug.h>
+#include <kgenericfactory.h>
+// Project specific include files
+#include "catalogitem.h"
+#include "linguistimport.h"
+
+K_EXPORT_COMPONENT_FACTORY( kbabel_linguistimport, KGenericFactory<LinguistImportPlugin> ( "kbabellinguistimportfilter" ) )
+
+using namespace KBabel;
+
+LinguistImportPlugin::LinguistImportPlugin( QObject * parent, const char * name, const QStringList& )
+ : CatalogImportPlugin( parent, name )
+{
+}
+
+ConversionStatus LinguistImportPlugin::load( const QString& filename, const QString& )
+{
+ if ( filename.isEmpty( ) ) {
+ kdDebug( ) << "fatal error: empty filename to open" << endl;
+ return NO_FILE;
+ }
+
+ QFileInfo info( filename );
+
+ if ( !info.exists( ) || info.isDir( ) )
+ return NO_FILE;
+
+ if ( !info.isReadable( ) )
+ return NO_PERMISSIONS;
+
+ QFile file( filename );
+ if ( !file.open( IO_ReadOnly ) )
+ return NO_PERMISSIONS;
+
+ QString errorMsg;
+ int errorLine, errorColumn;
+
+ QDomDocument doc;
+ if ( !doc.setContent( &file, &errorMsg, &errorLine, &errorColumn ) ) {
+ file.close( );
+ kdError() << "Parsing error at line " << errorLine << ", column " << errorColumn << ", error " << errorMsg << endl;
+ return PARSE_ERROR;
+ }
+ file.close( );
+
+ const QDomElement documentElement( doc.documentElement() );
+ // Count the number of messages in this file. This is needed for updating
+ // the progress bar correctly.
+ msgcnt = documentElement.elementsByTagName( "message" ).count();
+
+ if ( documentElement.tagName() != "TS" )
+ return UNSUPPORTED_TYPE;
+
+ cnt = 0;
+ emit signalClearProgressBar( );
+ kdDebug( ) << "start parsing..." << endl;
+
+ parse( documentElement );
+ //setCatalogExtraData( obsMessages );
+
+ emit signalProgress( 100 );
+ kdDebug( ) << "finished parsing..." << endl;
+
+ setMimeTypes( "application/x-linguist" );
+
+ return OK;
+}
+
+void LinguistImportPlugin::parse( const QDomElement& parentElement )
+{
+ QDomNode node = parentElement.firstChild( );
+
+ while ( !node.isNull( ) ) {
+ if ( node.isElement( ) ) {
+ QDomElement elem = node.toElement( );
+
+ if ( elem.tagName( ) == "context" ) {
+ // nothing to do here
+ } else if ( elem.tagName( ) == "name" ) {
+ context = elem.text( );
+ } else if ( elem.tagName( ) == "message" ) {
+ CatalogItem item;
+ QString comment;
+ bool isObsolete = false;
+ bool isFuzzy = false;
+
+ QDomNode childNode = node.firstChild();
+ for ( ; ! childNode.isNull() ; childNode = childNode.nextSibling() )
+ {
+ const QDomElement elem = childNode.toElement();
+
+ if ( elem.isNull() )
+ continue;
+
+ if ( elem.tagName( ) == "source" ) {
+ item.setMsgid( elem.text( ) );
+ } else if ( elem.tagName( ) == "translation" ) {
+ item.setMsgstr( elem.text( ) );
+ if ( elem.attribute( "type" ) == "unfinished" ) {
+ // Only mark as fuzzy if there is a translation
+ isFuzzy = !elem.text().isEmpty();
+ } else if ( elem.attribute( "type" ) == "obsolete" ) {
+ isObsolete = true;
+ }
+ } else if ( elem.tagName( ) == "comment" ) {
+ if ( !elem.text( ).isEmpty( ) )
+ comment = elem.text( );
+ }
+ }
+
+ QString fullComment = "Context: " + context;
+ if ( isFuzzy )
+ {
+ /*
+ * HACK
+ *
+ * KBabel has not any flag to tell "this entry is fuzzy!"
+ * but it uses the corresponding Gettext comment instead.
+ *
+ * Therefore we have little choice, but to add "#, fuzzy" to the comment,
+ * even if it is very Linguist-unlike
+ */
+ fullComment += "\n";
+ fullComment += "#, fuzzy";
+ }
+ if ( !comment.isEmpty() )
+ {
+ fullComment += "\n";
+ fullComment += comment;
+ }
+ item.setComment( fullComment );
+
+ appendCatalogItem( item, isObsolete );
+
+ // Update the progress bar.
+ cnt++;
+ uint prog = 100*cnt/msgcnt;
+ emit signalProgress( prog );
+ }
+ // ### TODO: avoid recursing
+ // recursive parsing
+ parse( elem );
+ }
+ node = node.nextSibling( );
+ }
+}
diff --git a/kbabel/filters/linguist/linguistimport.h b/kbabel/filters/linguist/linguistimport.h
new file mode 100644
index 00000000..3cdbd7e3
--- /dev/null
+++ b/kbabel/filters/linguist/linguistimport.h
@@ -0,0 +1,68 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+ 2002-2003 by Marco Wegner
+ <mail@marcowegner.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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#ifndef LINGUISTIMPORT_H
+#define LINGUISTIMPORT_H
+
+#include <qdom.h>
+
+#include "catalogfileplugin.h"
+
+class QString;
+class QStringList;
+
+/**
+ * The class for importing Qt's translation source files.
+ */
+class LinguistImportPlugin : public KBabel::CatalogImportPlugin
+{
+ public:
+ LinguistImportPlugin( QObject * parent, const char * name, const QStringList& );
+
+ virtual KBabel::ConversionStatus load( const QString& filename, const QString& mimetype );
+ virtual const QString id( ) { return "Qt translation source"; }
+
+ private:
+ void parse( const QDomElement& parentElement );
+
+ private:
+ uint msgcnt;
+ uint cnt;
+ QString context;
+ //QStringList obsMessages;
+};
+
+#endif // LINGUISTIMPORT_H
diff --git a/kbabel/filters/xliff/Makefile.am b/kbabel/filters/xliff/Makefile.am
new file mode 100644
index 00000000..d3f6cab1
--- /dev/null
+++ b/kbabel/filters/xliff/Makefile.am
@@ -0,0 +1,18 @@
+####### General stuff
+
+INCLUDES = -I../../common -I$(srcdir)/../../common $(all_includes)
+
+kde_module_LTLIBRARIES = kbabel_xliffexport.la kbabel_xliffimport.la
+
+kbabel_xliffexport_la_SOURCES = xliffexport.cpp
+kbabel_xliffexport_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+kbabel_xliffexport_la_LIBADD = ../../common/libkbabelcommon.la
+
+kbabel_xliffimport_la_SOURCES = xliffimport.cpp
+kbabel_xliffimport_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+kbabel_xliffimport_la_LIBADD = ../../common/libkbabelcommon.la
+
+METASOURCES = AUTO
+
+service_DATA = kbabel_xliff_export.desktop kbabel_xliff_import.desktop
+servicedir = $(kde_servicesdir)
diff --git a/kbabel/filters/xliff/kbabel_xliff_export.desktop b/kbabel/filters/xliff/kbabel_xliff_export.desktop
new file mode 100644
index 00000000..d4a8036d
--- /dev/null
+++ b/kbabel/filters/xliff/kbabel_xliff_export.desktop
@@ -0,0 +1,47 @@
+[Desktop Entry]
+Type=Service
+Name=KBabel XLIFF Export Filter
+Name[bg]=XLIFF филтър за екÑпортиране - KBabel
+Name[br]=Sil ezporzh XLIFF evit KBabel
+Name[ca]=Filtre KBabel per exportar a XLIFF
+Name[cs]=Exportní filtr do XLIFF pro KBabel
+Name[da]=KBabel XLIFF eksportfilter
+Name[de]=XLIFF-Export-Filter für KBabel
+Name[el]=ΦίλτÏο εξαγωγής XLIFF του KBabel
+Name[es]=Filtro de exportación XLIFF de KBabel
+Name[et]=KBabeli XLIFF ekspordifilter
+Name[eu]=KBabel XLIFF esportazio iragazkia
+Name[fa]=پالایۀ صادرات XLIFF KBabel
+Name[fi]=KBabel XLIFF -vientisuodatin
+Name[fr]=Filtre d'exportation XLIFF pour KBabel
+Name[ga]=Scagaire Easpórtála XLIFF le haghaidh KBabel
+Name[gl]=Filtro de exportación a XLIFF para KBabel
+Name[hu]=KBabel XLIFF exportszűrő
+Name[is]=KBabel XLIFF útfluttningssía
+Name[it]=Filtro di esportazione XLIFF per KBabel
+Name[ja]=KBabel XLIFF エクスãƒãƒ¼ãƒˆãƒ•ã‚£ãƒ«ã‚¿
+Name[ka]=KBabel XLIFF ექსპáƒáƒ áƒ¢áƒ˜áƒ¡ ფილტრი
+Name[kk]=KBabel XLIFF ÑкÑпорттау ÑүзгіÑÑ–
+Name[lt]=KBabel XLIFF eksportavimo filtras
+Name[nb]=XLIFF-eksportfilter for KBabel
+Name[nds]=KBabel-Exportfilter för XLIFF
+Name[ne]=केबà¥à¤¯à¤¾à¤¬à¤² à¤à¤•à¥à¤¸à¤à¤²à¤†à¤ˆà¤à¤«à¤à¤« निरà¥à¤¯à¤¾à¤¤ फिलà¥à¤Ÿà¤°
+Name[nl]=KBabel XLIFF-exportfilter
+Name[nn]=XLIFF-eksportfilter for KBabel
+Name[pa]=ਕੇਬਬੇਲ XLIFF ਨਿਰਯਾਤ ਫਿਲਟਰ
+Name[pl]=Filtr KBabel do eksportu do formatu XLIFF
+Name[pt]=Filtro de Exportação XLIFF para o KBabel
+Name[pt_BR]=Filtro de Exportação XLIFF do KBabel
+Name[ru]=Фильтр ÑкÑпорта XLIFF
+Name[sk]=Exportný filter pre KBabel XLIFF
+Name[sl]=Izvozni filter XLIFF za KBabel
+Name[sr]=KBabel-ов филтер за извоз у XLIFF
+Name[sr@Latn]=KBabel-ov filter za izvoz u XLIFF
+Name[sv]=Kbabel exportfilter för XLIFF
+Name[tr]=KBabel XLIFF Dışa Aktarma Süzgeci
+Name[uk]=Фільтр екÑпорту XLIFF Ð´Ð»Ñ KBabel
+Name[zh_CN]=KBabel XLIFF 导出过滤器
+Name[zh_TW]=KBabel XLIFF 匯出éŽæ¿¾å™¨
+X-KDE-Library=kbabel_xliffexport
+X-KDE-Export=application/x-xliff
+ServiceTypes=KBabelFilter
diff --git a/kbabel/filters/xliff/kbabel_xliff_import.desktop b/kbabel/filters/xliff/kbabel_xliff_import.desktop
new file mode 100644
index 00000000..260a30b4
--- /dev/null
+++ b/kbabel/filters/xliff/kbabel_xliff_import.desktop
@@ -0,0 +1,47 @@
+[Desktop Entry]
+Type=Service
+Name=KBabel XLIFF Import Filter
+Name[bg]=XLIFF филтър за импортиране - KBabel
+Name[br]=Sil enporzh XLIFF evit KBabel
+Name[ca]=Filtre KBabel per importar de XLIFF
+Name[cs]=Importní filtr XLIFF pro KBabel
+Name[da]=KBabel XLIFF importfilter
+Name[de]=XLIFF-Import-Filter für KBabel
+Name[el]=ΦίλτÏο εισαγωγής XLIFF του KBabel
+Name[es]=Filtro de importación de XLIFF de KBabel
+Name[et]=KBabeli XLIFF impordifilter
+Name[eu]=KBabel XLIFF inportazio iragazkia
+Name[fa]=پالایۀ واردات XLIFF KBabel
+Name[fi]=KBabel XLIFF -tuontisuodatin
+Name[fr]=Filtre d'importation XLIFF pour KBabel
+Name[ga]=Scagaire Iompórtála XLIFF le haghaidh KBabel
+Name[gl]=Filtro de importación a XLIFF para KBabel
+Name[hu]=KBabel XLIFF importszűrő
+Name[is]=KBabel XLIFF innfluttningssía
+Name[it]=Filtro di importazione di XLIFF per KBabel
+Name[ja]=KBabel XLIFF インãƒãƒ¼ãƒˆãƒ•ã‚£ãƒ«ã‚¿
+Name[ka]=KBabel XLIFF იმპáƒáƒ áƒ˜áƒ¡ ფილტრი
+Name[kk]=KBabel XLIFF импорттау ÑүзгіÑÑ–
+Name[lt]=KBabel XLIFF importavimo filtras
+Name[nb]=XLIFF-importfilter for KBabel
+Name[nds]=KBabel-Importfilter för XLIFF
+Name[ne]=केबà¥à¤¯à¤¾à¤¬à¤² à¤à¤•à¥à¤¸à¤à¤²à¤†à¤ˆà¤à¤«à¤à¤« आयात फिलà¥à¤Ÿà¤°
+Name[nl]=KBabel XLIFF-importfilter
+Name[nn]=XLIFF-importfilter for KBabel
+Name[pa]=ਕੇਬਬੇਲ XLIFF ਅਯਾਤ ਫਿਲਟਰ
+Name[pl]=Filtr KBabel do importu z formatu XLIFF
+Name[pt]=Filtro de Importação XLIFF para o KBabel
+Name[pt_BR]=Filtro de Importação XLIFF para o KBabel
+Name[ru]=Фильтр импорта XLIFF
+Name[sk]=Importný filter pre KBabel XLIFF
+Name[sl]=Uvozni filter XLIFF za KBabel
+Name[sr]=KBabel-ов филтер за увоз из XLIFF-а
+Name[sr@Latn]=KBabel-ov filter za uvoz iz XLIFF-a
+Name[sv]=Kbabel importfilter för XLIFF
+Name[tr]=KBabel XLIFF İçe Aktarma Süzgeci
+Name[uk]=Фільтр імпорту XLIFF Ð´Ð»Ñ KBabel
+Name[zh_CN]=KBabel XLIFF 导入过滤器
+Name[zh_TW]=KBabel XLIFF 匯入éŽæ¿¾å™¨
+X-KDE-Library=kbabel_xliffimport
+X-KDE-Import=application/x-xliff
+ServiceTypes=KBabelFilter
diff --git a/kbabel/filters/xliff/xliffexport.cpp b/kbabel/filters/xliff/xliffexport.cpp
new file mode 100644
index 00000000..53527f2c
--- /dev/null
+++ b/kbabel/filters/xliff/xliffexport.cpp
@@ -0,0 +1,223 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2001-2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+ 2002-2003 by Marco Wegner
+ <mail@marcowegner.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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#include <qfile.h>
+#include "qregexp.h"
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qtextstream.h>
+
+#include <kgenericfactory.h>
+
+#include "catalog.h"
+#include "catalogitem.h"
+#include "catalogsettings.h"
+#include "xliffexport.h"
+
+K_EXPORT_COMPONENT_FACTORY( kbabel_xliffexport, KGenericFactory<XLIFFExportPlugin> ( "kbabelxliffexportfilter" ) )
+
+using namespace KBabel;
+
+XLIFFExportPlugin::XLIFFExportPlugin( QObject * parent, const char * name, const QStringList& )
+ : CatalogExportPlugin( parent, name )
+{
+}
+
+ConversionStatus XLIFFExportPlugin::save( const QString& filename, const QString&, const Catalog * catalog )
+{
+ // Check whether we know how to handle the extra data.
+ if ( catalog->importPluginID( ) != "XLIFF 1.1" )
+ return UNSUPPORTED_TYPE;
+
+ QFile file( filename );
+ if ( !file.open( IO_WriteOnly ) )
+ return OS_ERROR;
+
+ SaveSettings settings = catalog->saveSettings( );
+
+ // New DOM document.
+ QDomDocument doc( "" );
+
+ extraData = catalog->catalogExtraData();
+ kdDebug () << "Setting the document data: " << extraData.first () << endl;
+ doc.setContent ( extraData.first () );
+
+ // Regular messages.
+ for ( uint i = 0; i < catalog->numberOfEntries( ); i++ ) {
+ QDomElement element = extractComment( doc, *(extraData.at( i+1 )) );
+ createMessage( doc, element, catalog->msgid( i ).join( "" ), catalog->msgstr( i ).join( "" ) );
+ }
+
+ QTextStream stream( &file );
+ doc.save( stream, 2 );
+ file.close( );
+
+ return OK;
+}
+
+QDomElement XLIFFExportPlugin::extractComment( QDomDocument& doc, const QString& s )
+{
+ QString comment( s );
+
+ if ( comment.isEmpty () )
+ {
+ kdError () << "Empty comment, should not happen" << endl;
+ }
+
+ // Extract the context and the actual comment.
+ comment.remove( QRegExp( "^Context:[\\s]*" ) );
+ QString newContext;
+ QStringList commentlines = QStringList::split ( '\n', comment);
+
+ QString file = *(commentlines.at(0));
+ QString id = *(commentlines.at(1));
+
+ kdDebug () << "Looking for file " << file << endl;
+
+ return getContext( doc, file, id );
+}
+
+void XLIFFExportPlugin::createMessage( QDomDocument& doc, QDomElement& translationElement, const QString& msgid,
+ const QString& msgstr )
+{
+ // for empty messages, don't store anything
+ if (msgstr.isEmpty ())
+ return;
+
+ // find the trans element
+ QDomNode node = translationElement.firstChild( );
+ while ( !node.isNull( ) ) {
+ kdDebug () << node.nodeName () << endl;
+ if ( node.isElement() && node.toElement().tagName( ) == "target") {
+ kdDebug () << "Found the target: " <<
+ node.firstChild().nodeName () << endl;
+ // set the new translation
+ node.firstChild().toText().setData (msgstr);
+ break;
+ }
+ node = node.nextSibling( );
+ }
+
+ if ( node.isNull () )
+ {
+ // no target tag, create one
+ node = doc.createElement ("target");
+ translationElement.appendChild (node);
+
+ QDomText data = doc.createTextNode(msgstr );
+ node.appendChild( data );
+ }
+}
+
+QDomElement XLIFFExportPlugin::getContext( QDomDocument& doc, const QString& file, const QString& id )
+{
+ // Find out whether there is already such a context in the QDomDocument.
+ QDomNode parentelem = doc.documentElement();
+ QDomNode elem = doc.documentElement( ).firstChild( );
+ while ( !elem.isNull( ) ) {
+ if ( elem.isElement( ) && elem.toElement().tagName( ) == "file" && elem.toElement().attribute ("original") == file ) {
+ kdDebug () << "We have found the file" << endl;
+ break;
+ }
+ elem = elem.nextSibling( );
+ }
+
+ if (elem.isNull ())
+ {
+ kdError () << "File not found at all, creating" << endl;
+ QDomElement newelem = doc.createElement ("file");
+ newelem.setAttribute ("original", file);
+ parentelem.appendChild (newelem);
+ elem = newelem;
+ }
+
+ // lookup body tag
+ parentelem = elem;
+ elem = elem.firstChild ();
+ while ( !elem.isNull( ) ) {
+ if ( elem.isElement( ) && elem.toElement().tagName( ) == "body" ) {
+ kdDebug () << "We have found the file body" << endl;
+ break;
+ }
+ elem = elem.nextSibling( );
+ }
+
+ if (elem.isNull ())
+ {
+ kdError () << "File body not found at all, creating" << endl;
+ QDomElement newelem = doc.createElement ("body");
+ parentelem.appendChild (newelem);
+ elem = newelem;
+ }
+
+ elem = findTransUnit (elem, id);
+
+ if (elem.isNull ())
+ {
+ kdError () << "Trans-unit not found at all, creating" << endl;
+ QDomElement newelem = doc.createElement ("trans-unit");
+ newelem.setAttribute ("id", id);
+ parentelem.appendChild (newelem);
+ elem = newelem;
+ }
+
+ return elem.toElement ();
+}
+
+QDomElement XLIFFExportPlugin::findTransUnit( QDomNode& group, const QString& id )
+{
+ QDomNode elem = group.firstChild( );
+
+ // lookup correct trans-unit tag
+ while ( !elem.isNull( ) ) {
+ if ( elem.isElement( ) && elem.toElement().tagName() == "group" )
+ {
+ // search recursively
+ QDomElement res = findTransUnit( elem, id );
+ if (! res.isNull () )
+ return res.toElement();
+ }
+ else if ( elem.isElement( ) && elem.toElement().tagName( ) == "trans-unit" && elem.toElement().attribute ("id") == id ) {
+ kdDebug () << "We have found the trans-unit" << endl;
+ return elem.toElement ();
+ }
+ elem = elem.nextSibling( );
+ }
+
+ return elem.toElement ();
+}
diff --git a/kbabel/filters/xliff/xliffexport.h b/kbabel/filters/xliff/xliffexport.h
new file mode 100644
index 00000000..5bf64b25
--- /dev/null
+++ b/kbabel/filters/xliff/xliffexport.h
@@ -0,0 +1,66 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002-2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+ 2002-2003 by Marco Wegner
+ <mail@marcowegner.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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#ifndef XLIFFEXPORT_H
+#define XLIFFEXPORT_H
+
+#include <qdom.h>
+
+#include "catalogfileplugin.h"
+
+class QString;
+class QStringList;
+
+namespace KBabel {
+class Catalog;
+}
+
+class XLIFFExportPlugin : public KBabel::CatalogExportPlugin
+{
+ public:
+ XLIFFExportPlugin( QObject * parent, const char * name, const QStringList& );
+ virtual KBabel::ConversionStatus save( const QString& filename, const QString& mimetype, const KBabel::Catalog * catalog );
+
+ private:
+ QDomElement extractComment( QDomDocument& doc, const QString& s );
+ void createMessage( QDomDocument& doc, QDomElement& context, const QString& msgid, const QString& msgstr );
+ QDomElement getContext( QDomDocument& doc, const QString& file, const QString& id);
+ QDomElement findTransUnit( QDomNode& doc, const QString& id);
+
+ QStringList extraData;
+};
+
+#endif // XLIFFEXPORT_H
diff --git a/kbabel/filters/xliff/xliffimport.cpp b/kbabel/filters/xliff/xliffimport.cpp
new file mode 100644
index 00000000..f7de63ce
--- /dev/null
+++ b/kbabel/filters/xliff/xliffimport.cpp
@@ -0,0 +1,180 @@
+// kate: space-indent on; indent-width 2; replace-tabs on;
+
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2001-2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+ 2002-2003 by Marco Wegner
+ <mail@marcowegner.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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+/*******
+ design:
+
+ the file name and id data are stored in the comment like this:
+ file\n
+ id\n
+ optional comments
+ */
+
+// Qt include files
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qobject.h>
+#include <qregexp.h>
+#include <qstring.h>
+#include <qstringlist.h>
+// KDE include files
+#include <kdebug.h>
+#include <kgenericfactory.h>
+// Project specific include files
+#include "catalogitem.h"
+#include "xliffimport.h"
+
+// ### TODO: what is the kdebug area?
+#define KDEBUG_AREA
+
+K_EXPORT_COMPONENT_FACTORY( kbabel_xliffimport, KGenericFactory<XLIFFImportPlugin> ( "kbabelxliffimportfilter" ) )
+
+using namespace KBabel;
+
+XLIFFImportPlugin::XLIFFImportPlugin( QObject * parent, const char * name, const QStringList& )
+ : CatalogImportPlugin( parent, name )
+{
+}
+
+ConversionStatus XLIFFImportPlugin::load( const QString& filename, const QString& )
+{
+ if ( filename.isEmpty( ) ) {
+ kdDebug( KDEBUG_AREA ) << "fatal error: empty filename to open" << endl;
+ return NO_FILE;
+ }
+
+ QFileInfo info( filename );
+
+ if ( !info.exists( ) || info.isDir( ) )
+ return NO_FILE;
+
+ if ( !info.isReadable( ) )
+ return NO_PERMISSIONS;
+
+ QFile file( filename );
+ if ( !file.open( IO_ReadOnly ) )
+ return NO_PERMISSIONS;
+
+ QString errorMsg;
+ int errorLine, errorColumn;
+
+ QDomDocument doc;
+ if ( !doc.setContent( &file, &errorMsg, &errorLine, &errorColumn ) ) {
+ file.close( );
+ kdError ( KDEBUG_AREA ) << "Parsing error at line " << errorLine << ", column " << errorColumn << ", error " << errorMsg << endl;
+ return PARSE_ERROR;
+ }
+ file.close( );
+
+ extraData.clear();
+
+ const QDomElement documentElement( doc.documentElement() );
+ msgcnt = documentElement.elementsByTagName( "trans-unit" ).count();
+
+ extraData.append( doc.toString() );
+
+ cnt = 0;
+ emit signalClearProgressBar( );
+ kdDebug( KDEBUG_AREA ) << "start parsing..." << endl;
+
+ parse( documentElement );
+
+ // store full document in extra data at index 0, the rest
+ // contains contexts for each entry at(1) for entry 0, at(2) for entry 1 ...
+ setCatalogExtraData( extraData );
+
+ emit signalProgress( 100 );
+ kdDebug( KDEBUG_AREA ) << "finished parsing..." << endl;
+
+ setMimeTypes( "application/x-xliff" );
+
+ return OK;
+}
+
+void XLIFFImportPlugin::parse( const QDomElement& parentElement )
+{
+ QDomNode node = parentElement.firstChild( );
+
+ while ( !node.isNull( ) ) {
+ if ( node.isElement( ) ) {
+ QDomElement elem = node.toElement( );
+
+ if ( elem.tagName( ) == "body" ) {
+ // nothing to do here
+ } else if ( elem.tagName( ) == "file" ) {
+ context = elem.attribute( "original", QString() );
+ kdDebug ( KDEBUG_AREA ) << "Found file: " << context << endl;
+ } else if ( elem.tagName( ) == "trans-unit" ) {
+ CatalogItem item;
+ QString comment;
+ bool isObsolete = false;
+
+ const QString id = elem.attribute ("id");
+
+ QDomNode childNode = node.firstChild();
+ for ( ; ! childNode.isNull() ; childNode = childNode.nextSibling() )
+ {
+ if ( childNode.isElement() )
+ {
+ const QDomElement elem = childNode.toElement( );
+ if ( elem.tagName( ) == "source" ) {
+ item.setMsgid( elem.text( ) );
+ } else if ( elem.tagName( ) == "target" ) {
+ item.setMsgstr( elem.text( ) );
+ }
+ }
+ }
+
+ extraData.append ( context + '\n' + id );
+ item.setComment( "Context: " + context + '\n' + id + "\n" + comment );
+
+ appendCatalogItem( item, isObsolete );
+
+ // Update the progress bar.
+ cnt++;
+ uint prog = 100*cnt/msgcnt;
+ emit signalProgress( prog );
+ }
+ // recursive parsing
+ parse( elem );
+ }
+ node = node.nextSibling( );
+ }
+}
diff --git a/kbabel/filters/xliff/xliffimport.h b/kbabel/filters/xliff/xliffimport.h
new file mode 100644
index 00000000..9cf44835
--- /dev/null
+++ b/kbabel/filters/xliff/xliffimport.h
@@ -0,0 +1,68 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002-2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+ 2002-2003 by Marco Wegner
+ <mail@marcowegner.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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#ifndef XLIFFIMPORT_H
+#define XLIFFIMPORT_H
+
+#include <qdom.h>
+
+#include "catalogfileplugin.h"
+
+class QString;
+class QStringList;
+
+/**
+ * The class for importing XLIFF 1.1 translation source files.
+ */
+class XLIFFImportPlugin : public KBabel::CatalogImportPlugin
+{
+ public:
+ XLIFFImportPlugin( QObject * parent, const char * name, const QStringList& );
+
+ virtual KBabel::ConversionStatus load( const QString& filename, const QString& mimetype );
+ virtual const QString id( ) { return "XLIFF 1.1"; }
+
+ private:
+ void parse( const QDomElement& parentElement );
+
+ private:
+ uint msgcnt;
+ uint cnt;
+ QString context;
+ QStringList extraData;
+};
+
+#endif // XLIFFIMPORT_H
diff --git a/kbabel/kbabel/Makefile.am b/kbabel/kbabel/Makefile.am
new file mode 100644
index 00000000..29c8d576
--- /dev/null
+++ b/kbabel/kbabel/Makefile.am
@@ -0,0 +1,92 @@
+# this has all of the subdirectories that make will recurse into. if
+# there are none, comment this out
+SUBDIRS = pics icons
+
+# this is the program that gets installed. it's name is used for all
+# of the other Makefile.am variables
+noinst_LTLIBRARIES = libkbabel.la
+bin_PROGRAMS = kbabel
+
+# set the include path for X, qt and KDE
+INCLUDES = -I$(srcdir)/../common -I../common -I$(srcdir)/../commonui -I../commonui -I$(srcdir)/../kbabeldict -I../kbabeldict $(all_includes)
+
+
+# which sources should be compiled for kbabel
+libkbabel_la_SOURCES = kbbookmarkhandler.cpp \
+ kbcatalog.cpp headerwidget.ui headereditor.cpp \
+ spelldlgwidget.ui spelldlg.cpp gotodialog.cpp\
+ kbhighlighting.cpp mymultilineedit.cpp \
+ hidingmsgedit.cpp \
+ kbabelpref.cpp \
+ kbcatalogview.cpp \
+ commentview.cpp \
+ contextview.cpp \
+ charselectview.cpp \
+ taglistview.cpp \
+ sourceview.cpp \
+ kbabelview.cpp kbabelview2.cpp \
+ kbabel.cpp kbabeliface.skel kbabelsplash.cpp \
+ kbabelsettings.kcfgc \
+ fontpreferences.ui \
+ editordiffpreferences.ui \
+ editorpreferences.ui \
+ searchpreferences.ui \
+ colorpreferences.ui \
+ kbcataloglistview.cpp kbcataloglistviewitem.cpp \
+ errorlistview.cpp
+
+kde_kcfg_DATA=kbabel.kcfg
+
+libkbabel_la_LIBADD = ../commonui/libkbabelcommonui.la ../kbabeldict/libkbabeldict.la $(LIB_KIO) $(LIB_KSPELL)
+libkbabel_la_LDFLAGS = $(all_libraries)
+
+
+kbabel_SOURCES = main.cpp
+
+# the libraries to link against.
+kbabel_LDADD = libkbabel.la
+kbabel_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+
+# these are the headers for your project
+noinst_HEADERS = kbabel.h kbabelview.h \
+ kbcatalogview.h \
+ commentview.h \
+ contextview.h \
+ charselectview.h \
+ taglistview.h \
+ sourceview.h \
+ kbabeliface.h kbabelpref.h\
+ headereditor.h mymultilineedit.h\
+ gotodialog.h hidingmsgedit.h\
+ kbcatalog.h spelldlg.h\
+ kbabelsplash.h kbbookmarkhandler.h \
+ kbhighlighting.h \
+ kbcataloglistview.h \
+ kbcataloglistviewitem.h \
+ errorlistview.h
+
+# let automoc handle all of the meta source files (moc)
+METASOURCES = AUTO
+
+rcdir = $(kde_datadir)/kbabel
+rc_DATA = kbabelui.rc
+
+update_DATA = kbabel-project.upd kbabel-difftoproject.upd
+updatedir = $(kde_datadir)/kconf_update
+
+api:
+ mkdir -p API && kdoc -d API -u $$PWD/API -p -lkdeui -lkdecore -lqt -ldcop $(noinst_HEADERS)
+
+distclean-local:
+ rm -r -f API
+
+KDE_ICON = kbabel
+
+ # this is where the kdelnk file will go
+xdg_apps_DATA = kbabel.desktop
+
+kbabel.lo: ../common/kbprojectsettings.h ../common/version.h
+kbabelview.lo: ../common/kbprojectsettings.h ../common/version.h
+kbabelview2.lo: ../common/kbprojectsettings.h
+main.o: ../common/version.h
+
diff --git a/kbabel/kbabel/charselectview.cpp b/kbabel/kbabel/charselectview.cpp
new file mode 100644
index 00000000..12cd765f
--- /dev/null
+++ b/kbabel/kbabel/charselectview.cpp
@@ -0,0 +1,115 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#include "charselectview.h"
+
+#include <qlayout.h>
+#include <qwhatsthis.h>
+#include <qlabel.h>
+#include <qspinbox.h>
+#include <qscrollview.h>
+
+#include <kconfig.h>
+#include <kcursor.h>
+#include <kdialog.h>
+#include <klocale.h>
+#include <kcharselect.h>
+
+#include "kbcatalog.h"
+
+using namespace KBabel;
+
+CharacterSelectorView::CharacterSelectorView(KBCatalog* catalog,QWidget *parent, Project::Ptr project)
+ : KBCatalogView(catalog,parent,project)
+{
+ QVBoxLayout* layout = new QVBoxLayout( this );
+ layout->setResizeMode( QLayout::Minimum );
+
+ layout->setSpacing( KDialog::spacingHint() );
+
+ QHBox* bar = new QHBox(this);
+ bar->setSpacing( KDialog::spacingHint() );
+ layout->addWidget (bar);
+
+ QLabel *lTable = new QLabel( i18n( "Table:" ), bar );
+ _tableNum = new QSpinBox( 0, 255, 1, bar );
+ lTable->setBuddy( _tableNum );
+ bar->setStretchFactor( _tableNum, 1 );
+
+ QScrollView* scroll = new QScrollView( this );
+ _table = new KCharSelectTable(scroll,"charselector","helvetica",' ',0);
+ _table->setNumCols(16);
+ _table->setNumRows(16);
+
+ scroll->addChild(_table);
+ layout->addWidget (scroll);
+
+ connect( _table, SIGNAL( doubleClicked() ), this, SLOT( emitChar() ) );
+ connect( _tableNum, SIGNAL( valueChanged(int) ), this, SLOT( setTab(int) ));
+
+ connect( _catalog, SIGNAL( signalFileOpened(bool) ), this, SLOT (setDisabled (bool)));
+ connect( _catalog, SIGNAL( signalFileOpened(bool) ), _table, SLOT (setDisabled (bool)));
+
+ QWhatsThis::add(this,
+ i18n("<qt><p><b>Character Selector</b></p>"
+ "<p>This tool allows to insert special characters using "
+ "double click.</p></qt>"));
+}
+
+void CharacterSelectorView::emitChar()
+{
+ emit characterDoubleClicked( _table->chr() );
+}
+
+void CharacterSelectorView::setTab(int value)
+{
+ _table->setTableNum( value );
+}
+
+void CharacterSelectorView::saveSettings(KConfig* config)
+{
+ KConfigGroupSaver saver(config, "KBCharSelector" );
+
+ config->writeEntry( "TableNum", _tableNum->value() );
+ config->writeEntry( "SelectedChar", QString(_table->chr()) );
+}
+
+void CharacterSelectorView::restoreSettings(KConfig* config)
+{
+ KConfigGroupSaver saver(config, "KBCharSelector" );
+
+ _tableNum->setValue( config->readNumEntry("TableNum", 0 ));
+ _table->setChar( config->readEntry("SelectedChar"," ").at(0));
+}
+
+#include "charselectview.moc"
diff --git a/kbabel/kbabel/charselectview.h b/kbabel/kbabel/charselectview.h
new file mode 100644
index 00000000..76ee19b8
--- /dev/null
+++ b/kbabel/kbabel/charselectview.h
@@ -0,0 +1,71 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef CHARSELECTVIEW_H
+#define CHARSELECTVIEW_H
+
+#include "kbcatalogview.h"
+
+class KCharSelectTable;
+class QSpinBox;
+
+class CharacterSelectorView : public KBCatalogView
+{
+ Q_OBJECT
+public:
+ /**
+ * Default constructor
+ */
+ CharacterSelectorView(KBCatalog* catalog,QWidget *parent, KBabel::Project::Ptr project);
+
+ void saveSettings(KConfig* config);
+ void restoreSettings(KConfig* config);
+
+public slots:
+ // this view does not depend on the current item
+ virtual void updateView() {}
+
+signals:
+ void characterDoubleClicked( QChar ch );
+
+public slots:
+ void emitChar();
+
+private slots:
+ void setTab( int value);
+
+private:
+ KCharSelectTable* _table;
+ QSpinBox* _tableNum;
+};
+
+#endif // CHARSELECTVIEW_H
diff --git a/kbabel/kbabel/colorpreferences.ui b/kbabel/kbabel/colorpreferences.ui
new file mode 100644
index 00000000..97e89df6
--- /dev/null
+++ b/kbabel/kbabel/colorpreferences.ui
@@ -0,0 +1,188 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>ColorPreferences</class>
+<author>Stanislav Visnovsky</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>ColorPreferences</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>627</width>
+ <height>480</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KColorButton" row="1" column="1">
+ <property name="name">
+ <cstring>kcfg_QuotedColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="0" column="1">
+ <property name="name">
+ <cstring>kcfg_BackgroundColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Background color:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_BackgroundColor</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Color for &amp;quoted characters:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_QuotedColor</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Color for &amp;syntax errors:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_ErrorColor</cstring>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="2" column="1">
+ <property name="name">
+ <cstring>kcfg_ErrorColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="3" column="0">
+ <property name="name">
+ <cstring>label</cstring>
+ </property>
+ <property name="text">
+ <string>Color for s&amp;pellcheck errors:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_ErrorColor</cstring>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="3" column="1">
+ <property name="name">
+ <cstring>kcfg_SpellcheckErrorColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Here you can setup a color to display identified &lt;b&gt;mispelled&lt;/b&gt; words and
+phrases.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="5" column="0">
+ <property name="name">
+ <cstring>textLabel5</cstring>
+ </property>
+ <property name="text">
+ <string>Color for &amp;keyboard accelerators:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_AccelColor</cstring>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="6" column="1">
+ <property name="name">
+ <cstring>kcfg_TagColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="5" column="1">
+ <property name="name">
+ <cstring>kcfg_AccelColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="4" column="0">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>Color for c-for&amp;mat characters:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_CformatColor</cstring>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="4" column="1">
+ <property name="name">
+ <cstring>kcfg_CformatColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="6" column="0">
+ <property name="name">
+ <cstring>textLabel6</cstring>
+ </property>
+ <property name="text">
+ <string>Color for &amp;tags:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_TagColor</cstring>
+ </property>
+ </widget>
+ <spacer row="7" column="0">
+ <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>50</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kcolorbutton.h</includehint>
+ <includehint>kcolorbutton.h</includehint>
+ <includehint>kcolorbutton.h</includehint>
+ <includehint>kcolorbutton.h</includehint>
+ <includehint>kcolorbutton.h</includehint>
+ <includehint>kcolorbutton.h</includehint>
+ <includehint>kcolorbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kbabel/kbabel/commentview.cpp b/kbabel/kbabel/commentview.cpp
new file mode 100644
index 00000000..bf2301de
--- /dev/null
+++ b/kbabel/kbabel/commentview.cpp
@@ -0,0 +1,221 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2002-2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#include "commentview.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qwhatsthis.h>
+#include <qdragobject.h>
+#include <qtextview.h>
+
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kcursor.h>
+#include <kdialog.h>
+#include <klocale.h>
+#include <kurl.h>
+#include <kurldrag.h>
+
+#include "resources.h"
+
+#include "editcmd.h"
+#include "hidingmsgedit.h"
+#include "kbcatalog.h"
+
+#define ID_DROP_OPEN 1
+#define ID_DROP_OPEN_TEMPLATE 2
+
+#define MAX_HISTORY 50
+
+using namespace KBabel;
+
+CommentView::CommentView(KBCatalog* catalog,QWidget *parent, Project::Ptr project)
+ : KBCatalogView(catalog,parent, project)
+{
+ setAcceptDrops(true);
+
+ QVBoxLayout* layout=new QVBoxLayout(this);
+
+ commentEdit = new MsgMultiLineEdit(0, 0, this);
+ commentEdit->setMinimumHeight(50);
+ commentEdit->setSpacePoints(false);
+ commentEdit->setHighlightSyntax(false);
+ KCursor::setAutoHideCursor(commentEdit,true);
+
+ QLabel* label=new QLabel(commentEdit,i18n("&Comment:"),this);
+
+ QHBoxLayout* hb=new QHBoxLayout(layout);
+ hb->addSpacing(KDialog::marginHint());
+ hb->addWidget(label);
+
+ layout->addWidget(commentEdit);
+ layout->setStretchFactor(commentEdit,1);
+
+ QWhatsThis::add(this,
+ i18n("<qt><p><b>Comment Editor</b></p>\n\
+This edit window shows you the comments of the currently displayed message.<p>\n\
+<p>The comments normally contain information about where the message is found in the source\n\
+code and status information about this message (fuzzy, c-format).\n\
+Hints from other translators are also sometimes contained in comments.</p>\n\
+<p>You can hide the comment editor by deactivating\n\
+<b>Options->Show Comments</b>.</p></qt>"));
+
+ commentEdit->setReadOnly(true);
+ connect(commentEdit,SIGNAL(signalUndoCmd(KBabel::EditCommand*)),this,SLOT(forwardCommentEditCmd(KBabel::EditCommand*)));
+
+ connect(commentEdit,SIGNAL(cursorPositionChanged(int,int))
+ , this, SIGNAL(signalCursorPosChanged(int,int)));
+
+ connect(_catalog, SIGNAL(signalFileOpened(bool)), this, SLOT(setDisabled(bool)));
+}
+
+void CommentView::update(EditCommand* cmd, bool undo)
+{
+ if((int)_currentIndex==cmd->index())
+ {
+ if(cmd->part()==Comment)
+ {
+ commentEdit->processCommand(cmd,undo);
+ }
+ }
+}
+
+void CommentView::textCut()
+{
+ if(commentEdit->hasFocus())
+ {
+ commentEdit->cut();
+ }
+}
+
+void CommentView::textCopy()
+{
+ if(commentEdit->hasSelectedText())
+ {
+ commentEdit->copy();
+ }
+}
+
+void CommentView::textPaste()
+{
+ if(commentEdit->hasFocus())
+ {
+ commentEdit->paste();
+ }
+}
+
+void CommentView::textSelectAll()
+{
+ if(commentEdit->hasFocus())
+ {
+ commentEdit->selectAll();
+ }
+}
+
+void CommentView::textDeselectAll()
+{
+ commentEdit->selectAll(false);
+}
+
+void CommentView::updateView()
+{
+ commentEdit->setText ( _catalog->comment (_currentIndex) );
+}
+
+void CommentView::forwardCommentEditCmd(EditCommand* cmd)
+{
+ cmd->setPart(Comment);
+ cmd->setIndex(_currentIndex);
+
+ _catalog->applyEditCommand(cmd,this);
+}
+
+void CommentView::setReadOnly(bool on)
+{
+ commentEdit->setReadOnly( on );
+}
+
+void CommentView::setOverwriteMode(bool on)
+{
+ commentEdit->setOverwriteMode( on );
+}
+
+void CommentView::readFileSettings()
+{
+ setReadOnly( _catalog->isReadOnly() );
+}
+
+const QString CommentView::selectText(int from, int to)
+{
+ int line, col, endline, endcol;
+
+ commentEdit->selectAll(false);
+ commentEdit->setFocus();
+ commentEdit->offset2Pos(from,line,col);
+ commentEdit->offset2Pos(to,endline,endcol);
+
+ commentEdit->setSelection(line,col,endline,endcol);
+ commentEdit->setCursorPosition(endline,endcol);
+
+ return commentEdit->selectedText();
+}
+
+bool CommentView::isActiveView ()
+{
+ return hasFocus () || commentEdit->hasFocus ();
+}
+
+int CommentView::currentIndex ()
+{
+ return commentEdit->currentIndex ();
+}
+
+const QString CommentView::selectedText ()
+{
+ return commentEdit->selectedText ();
+}
+
+void CommentView::installEventFilter( const QObject * filterObj )
+{
+ commentEdit->installEventFilter( filterObj );
+}
+
+bool CommentView::hasFocus()
+{
+ return commentEdit->hasFocus();
+}
+
+#include "commentview.moc"
diff --git a/kbabel/kbabel/commentview.h b/kbabel/kbabel/commentview.h
new file mode 100644
index 00000000..1531683b
--- /dev/null
+++ b/kbabel/kbabel/commentview.h
@@ -0,0 +1,96 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef COMMENTVIEW_H
+#define COMMENTVIEW_H
+
+class QTextView;
+
+#include <qwidget.h>
+
+#include "kbcatalogview.h"
+#include "kbcatalog.h"
+#include "kbproject.h"
+#include "projectsettings.h"
+
+class MsgMultiLineEdit;
+
+class CommentView : public KBCatalogView
+{
+ Q_OBJECT
+public:
+ /**
+ * Default constructor
+ */
+ CommentView(KBCatalog* catalog,QWidget *parent, KBabel::Project::Ptr project);
+
+ /**
+ * this is called from the catalog when updating his views.
+ * reimplemented from @ref CatalogView
+ * @param cmd the edit command that has been applied
+ */
+ virtual void update(KBabel::EditCommand* cmd, bool undo=false);
+
+ virtual void updateView();
+ virtual void textCut ();
+ virtual void textCopy ();
+ virtual void textPaste ();
+ virtual void textSelectAll ();
+ virtual void textDeselectAll ();
+
+ const QString selectText( int from, int to );
+ const QString selectedText ();
+ bool isActiveView ();
+ int currentIndex ();
+
+ // this method is not virtual!
+ void installEventFilter( const QObject * filterObj );
+
+ bool hasFocus ();
+
+public slots:
+ virtual void setReadOnly(bool on);
+ virtual void setOverwriteMode(bool on);
+
+ virtual void readFileSettings();
+
+signals:
+ void signalCommentsShown();
+
+private slots:
+ void forwardCommentEditCmd(KBabel::EditCommand*);
+
+private:
+ MsgMultiLineEdit* commentEdit;
+};
+
+#endif // COMMENTVIEW_H
diff --git a/kbabel/kbabel/contextview.cpp b/kbabel/kbabel/contextview.cpp
new file mode 100644
index 00000000..e56e15dc
--- /dev/null
+++ b/kbabel/kbabel/contextview.cpp
@@ -0,0 +1,158 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2002-2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#include "contextview.h"
+
+#include <qlayout.h>
+#include <qtextview.h>
+#include <qwhatsthis.h>
+
+#include <kcursor.h>
+#include <klocale.h>
+
+#include "resources.h"
+#include "kbcatalog.h"
+
+using namespace KBabel;
+
+ContextView::ContextView(KBCatalog* catalog,QWidget *parent, Project::Ptr project)
+ : KBCatalogView(catalog,parent,project)
+{
+ QVBoxLayout* layout = new QVBoxLayout( this );
+ layout->setResizeMode( QLayout::Minimum );
+
+ _textview = new QTextView (this, "context textview");
+ KCursor::setAutoHideCursor(_textview->viewport(),true);
+ _textview->setReadOnly(true);
+
+ layout->addWidget (_textview);
+
+ QWhatsThis::add(this,
+ i18n("<qt><p><b>PO Context</b></p>"
+ "<p>This window shows the context of the current message "
+ "in the PO file. Normally it shows four messages in front "
+ "of the current message and four after it.</p>"
+ "<p>You can hide the tools window by deactivating "
+ "<b>Options->Show Tools</b>.</p></qt></qt>"));
+
+ connect(_catalog, SIGNAL(signalFileOpened(bool)), this, SLOT(setDisabled(bool)));
+}
+
+void ContextView::updateView()
+{
+ uint total = _catalog->numberOfEntries();
+ if(total==0)
+ return;
+
+ QString text;
+ uint startIndex;
+ uint context = 4;
+ if(_currentIndex < context)
+ {
+ startIndex = 0;
+ }
+ else if(_currentIndex > total-2*context-2)
+ {
+ startIndex = total-2*context-1;
+ }
+ else
+ {
+ startIndex = _currentIndex-context;
+ }
+
+ for(uint i=startIndex; i < QMIN(startIndex+(2*context+1), total); i++)
+ {
+ if(i == _currentIndex)
+ {
+ text += "<p><hr/><b>"+i18n("current entry") +"</b><hr/></p>";
+ continue;
+ }
+
+ QString entry;
+ QString temp;
+ temp = _catalog->comment(i);
+ if(!temp.isEmpty())
+ {
+ temp = QStyleSheet::convertFromPlainText(temp);
+ temp.replace(QRegExp("^<p>"),"");
+ temp.replace(QRegExp("</p>$"),"");
+ entry += "<i>"+temp+"</i><br/>";
+ }
+
+ // FIXME: should care about plural forms
+ temp = QStyleSheet::convertFromPlainText(_catalog->msgid(i).first());
+ temp.replace(QRegExp("^<p>"),"");
+ temp.replace(QRegExp("</p>$"),"");
+ entry += temp + "<br/>---<br/>";
+
+ QStringList tempList = _catalog->msgstr(i);
+
+ if(tempList.isEmpty())
+ {
+ entry +="<i><b><font color=\"red\">"
+ +i18n("untranslated")
+ +"</font></b></i><br/>";
+ }
+ else
+ {
+ if( tempList.count() == 1 )
+ {
+ temp = tempList.first();
+ }
+ else
+ {
+ uint counter = 1;
+ temp = "";
+ for( QStringList::Iterator i=tempList.begin() ; i != tempList.end() ; ++i)
+ {
+ temp += i18n("Plural %1: %2\n").arg(counter++).arg(*i);
+ }
+ }
+ temp = QStyleSheet::convertFromPlainText(temp);
+ temp.replace(QRegExp("^<p>"),"");
+ temp.replace(QRegExp("</p>$"),"");
+
+ entry += temp+"<br/>";
+ }
+
+ text += "<p>"+entry+"</p>";
+ }
+ _textview->setText("<qt>"+text+"</qt>");
+
+ int height = _textview->contentsHeight();
+ _textview->setContentsPos(0,height/2);
+}
+
+#include "contextview.moc"
diff --git a/kbabel/kbabel/contextview.h b/kbabel/kbabel/contextview.h
new file mode 100644
index 00000000..18bd0f4e
--- /dev/null
+++ b/kbabel/kbabel/contextview.h
@@ -0,0 +1,56 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef CONTEXTVIEW_H
+#define CONTEXTVIEW_H
+
+#include "kbcatalogview.h"
+
+class QTextView;
+
+class ContextView : public KBCatalogView
+{
+ Q_OBJECT
+public:
+ /**
+ * Default constructor
+ */
+ ContextView(KBCatalog* catalog,QWidget *parent, KBabel::Project::Ptr project);
+
+public slots:
+ virtual void updateView();
+
+private:
+ QTextView* _textview;
+};
+
+#endif // CONTEXTVIEW_H
diff --git a/kbabel/kbabel/editordiffpreferences.ui b/kbabel/kbabel/editordiffpreferences.ui
new file mode 100644
index 00000000..db21bc8e
--- /dev/null
+++ b/kbabel/kbabel/editordiffpreferences.ui
@@ -0,0 +1,192 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>EditorDiffPreferences</class>
+<author>Stanislav Visnovsky</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>EditorDiffPreferences</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>538</width>
+ <height>462</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="title">
+ <string>Appearance</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Added Characters</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Ho&amp;w to display:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_DiffAddUnderline</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>Co&amp;lor:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_DiffAddColor</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="3" column="0">
+ <property name="name">
+ <cstring>textLabel5</cstring>
+ </property>
+ <property name="text">
+ <string>Removed Characters</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="4" column="0">
+ <property name="name">
+ <cstring>textLabel6</cstring>
+ </property>
+ <property name="text">
+ <string>How &amp;to display:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_DiffDelStrikeOut</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="5" column="0">
+ <property name="name">
+ <cstring>textLabel7</cstring>
+ </property>
+ <property name="text">
+ <string>Colo&amp;r:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_DiffDelColor</cstring>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="1" column="1">
+ <item>
+ <property name="text">
+ <string>Highlighted</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Underlined</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>kcfg_DiffAddUnderline</cstring>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="2" column="1">
+ <property name="name">
+ <cstring>kcfg_DiffAddColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="color">
+ <color>
+ <red>192</red>
+ <green>192</green>
+ <blue>255</blue>
+ </color>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="4" column="1">
+ <item>
+ <property name="text">
+ <string>Highlighted</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Stroked Out</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>kcfg_DiffDelStrikeOut</cstring>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="5" column="1">
+ <property name="name">
+ <cstring>kcfg_DiffDelColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="color">
+ <color>
+ <red>255</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ </hbox>
+ </widget>
+ <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>31</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<functions>
+ <function>init()</function>
+</functions>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kcolorbutton.h</includehint>
+ <includehint>kcolorbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kbabel/kbabel/editorpreferences.ui b/kbabel/kbabel/editorpreferences.ui
new file mode 100644
index 00000000..ee8632f9
--- /dev/null
+++ b/kbabel/kbabel/editorpreferences.ui
@@ -0,0 +1,353 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>EditorPreferences</class>
+<author>Stanislav Visnovsky</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>EditorPreferences</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>627</width>
+ <height>480</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QTabWidget">
+ <property name="name">
+ <cstring>tabWidget2</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>&amp;General</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>frame6</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_AutoUnsetFuzzy</cstring>
+ </property>
+ <property name="text">
+ <string>A&amp;utomatically unset fuzzy status</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;&lt;p&gt;&lt;b&gt;Automatically unset fuzzy status&lt;/b&gt;&lt;/p&gt;
+&lt;p&gt;If this is activated and you are editing a fuzzy entry, the fuzzy status is automatically
+unset (this means the string &lt;i&gt;, fuzzy&lt;/i&gt;
+is removed from the entry's comment).&lt;/p&gt;&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_CleverEditing</cstring>
+ </property>
+ <property name="text">
+ <string>Use cle&amp;ver editing</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;&lt;p&gt;&lt;b&gt;Use clever editing&lt;/b&gt;&lt;/p&gt;
+&lt;p&gt;Check this to make typing text more comfortable and let
+KBabel take care of some special characters that have to
+be quoted. For example typing '\"' will result in
+'\\\"', pressing Return will automatically add whitespace
+at the end of the line, pressing Shift+Return will add
+'\\n' at the end of the line.&lt;/p&gt;
+&lt;p&gt;Note that this is just a hint: it is still possible to
+generate syntactically incorrect text.&lt;/p&gt;&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox3</cstring>
+ </property>
+ <property name="title">
+ <string>Automatic Checks</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;&lt;p&gt;&lt;b&gt;Error recognition&lt;/b&gt;&lt;/p&gt;
+&lt;p&gt;Here you can set how to show that an error occurred.
+&lt;b&gt;Beep on error&lt;/b&gt; beeps and &lt;b&gt;Change text color on error
+&lt;/b&gt; changes the color of the translated text. If none is
+activated, you will still see a message in the statusbar.
+&lt;/p&gt;&lt;/qt&gt;</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="ToolSelectionWidget">
+ <property name="name">
+ <cstring>_kcfg_AutoCheckTools</cstring>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_BeepOnError</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Beep on error</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_AutoCheckColorError</cstring>
+ </property>
+ <property name="text">
+ <string>Change te&amp;xt color on error</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer8</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>A&amp;ppearance</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>frame3</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox" row="0" column="0">
+ <property name="name">
+ <cstring>kcfg_HighlightSyntax</cstring>
+ </property>
+ <property name="text">
+ <string>H&amp;ighlight syntax</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="0">
+ <property name="name">
+ <cstring>kcfg_HighlightBackground</cstring>
+ </property>
+ <property name="text">
+ <string>Highlight backgrou&amp;nd</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="0" column="1">
+ <property name="name">
+ <cstring>kcfg_WhitespacePoints</cstring>
+ </property>
+ <property name="text">
+ <string>Mark &amp;whitespaces with points</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="1">
+ <property name="name">
+ <cstring>kcfg_EnableQuotes</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Show surrounding quotes</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>buttonGroup1</cstring>
+ </property>
+ <property name="title">
+ <string>Status LEDs</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;&lt;p&gt;&lt;b&gt;Status LEDs&lt;/b&gt;&lt;/p&gt;
+&lt;p&gt;Choose here where the status LEDs are displayed and what color they have.&lt;/p&gt;&lt;/qt&gt;</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>kcfg_LedInStatusbar</cstring>
+ </property>
+ <property name="text">
+ <string>Display in stat&amp;usbar</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>radioButton2</cstring>
+ </property>
+ <property name="text">
+ <string>Display in edi&amp;tor</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <spacer>
+ <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>51</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel7</cstring>
+ </property>
+ <property name="text">
+ <string>Colo&amp;r:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>kcfg_LedColor</cstring>
+ </property>
+ </widget>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>kcfg_LedColor</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>29</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>ToolSelectionWidget</class>
+ <header location="global">toolselectionwidget.h</header>
+ <sizehint>
+ <width>200</width>
+ <height>200</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="XBM.GZ" length="79">789c534e494dcbcc4b554829cdcdad8c2fcf4c29c95030e0524611cd48cd4ccf28010a1797249664262b2467241641a592324b8aa363156c15aab914146aadb90067111b1f</data>
+ </image>
+</images>
+<connections>
+ <connection>
+ <sender>kcfg_LedInStatusbar</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>EditorPreferences</receiver>
+ <slot>ledWarning(bool)</slot>
+ </connection>
+ <connection>
+ <sender>radioButton2</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>EditorPreferences</receiver>
+ <slot>ledWarning(bool)</slot>
+ </connection>
+ <connection>
+ <sender>kcfg_LedInStatusbar</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>EditorPreferences</receiver>
+ <slot>toggleOther(bool)</slot>
+ </connection>
+</connections>
+<includes>
+ <include location="local" impldecl="in implementation">editorpreferences.ui.h</include>
+</includes>
+<slots>
+ <slot specifier="non virtual">ledWarning( bool show )</slot>
+ <slot specifier="non virtual">toggleOther( bool other )</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>toolselectionwidget.h</includehint>
+ <includehint>kcolorbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kbabel/kbabel/editorpreferences.ui.h b/kbabel/kbabel/editorpreferences.ui.h
new file mode 100644
index 00000000..b7f9827c
--- /dev/null
+++ b/kbabel/kbabel/editorpreferences.ui.h
@@ -0,0 +1,23 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+#include <kmessagebox.h>
+#include "toolselectionwidget.h"
+
+void EditorPreferences::ledWarning( bool show )
+{
+if(show)
+ KMessageBox::information( this,i18n("This option takes no effect until KBabel is restarted.") );
+}
+
+
+void EditorPreferences::toggleOther( bool other )
+{
+ radioButton2->setChecked(! other);
+}
diff --git a/kbabel/kbabel/errorlistview.cpp b/kbabel/kbabel/errorlistview.cpp
new file mode 100644
index 00000000..2dcd3b12
--- /dev/null
+++ b/kbabel/kbabel/errorlistview.cpp
@@ -0,0 +1,76 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2002-2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#include "errorlistview.h"
+
+#include <qlayout.h>
+#include <qtextview.h>
+#include <qwhatsthis.h>
+
+#include <kcursor.h>
+#include <klocale.h>
+
+#include "resources.h"
+#include "kbcatalog.h"
+
+using namespace KBabel;
+
+ErrorListView::ErrorListView(KBCatalog* catalog,QWidget *parent, Project::Ptr project)
+ : KBCatalogView(catalog,parent,project)
+{
+ QVBoxLayout* layout = new QVBoxLayout( this );
+ layout->setResizeMode( QLayout::Minimum );
+
+ _textview = new QTextView (this);
+ KCursor::setAutoHideCursor(_textview->viewport(),true);
+ _textview->setReadOnly(true);
+
+ layout->addWidget(_textview);
+
+ QWhatsThis::add(this, i18n( "<qt><p><b>Error List</b></p>"
+ "<p>This window shows the list of errors found by validator tools "
+ "so you can know why the current message has been marked with an "
+ "error.</p></qt>" ) );
+}
+
+void ErrorListView::updateView()
+{
+ if( _catalog->numberOfEntries() == 0 )
+ return;
+
+ _textview->setText( _catalog->itemStatus( _currentIndex ).join( "\n---\n" ) );
+}
+
+#include "errorlistview.moc"
diff --git a/kbabel/kbabel/errorlistview.h b/kbabel/kbabel/errorlistview.h
new file mode 100644
index 00000000..d50e7ec7
--- /dev/null
+++ b/kbabel/kbabel/errorlistview.h
@@ -0,0 +1,55 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2004 by Albert Cervera Areny <albertca@hotpop.com>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef ERRORLISTVIEW_H
+#define ERRORLISTVIEW_H
+
+#include "kbcatalogview.h"
+
+class QTextView;
+
+class ErrorListView : public KBCatalogView
+{
+ Q_OBJECT
+public:
+ /**
+ * Default constructor
+ */
+ ErrorListView(KBCatalog* catalog,QWidget *parent, KBabel::Project::Ptr project);
+
+public slots:
+ virtual void updateView();
+
+private:
+ QTextView* _textview;
+};
+
+#endif // ERRORLISTVIEW_H
diff --git a/kbabel/kbabel/fontpreferences.ui b/kbabel/kbabel/fontpreferences.ui
new file mode 100644
index 00000000..aefb8c7e
--- /dev/null
+++ b/kbabel/kbabel/fontpreferences.ui
@@ -0,0 +1,63 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>FontPreferences</class>
+<author>Stanislav Visnovsky</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>FontPreferences</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>595</width>
+ <height>515</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="title">
+ <string>Font for Messages</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>checkBox1</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Show only fixed font</string>
+ </property>
+ </widget>
+ <widget class="KFontChooser">
+ <property name="name">
+ <cstring>kcfg_MsgFont</cstring>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>checkBox1</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>FontPreferences</receiver>
+ <slot>showOnlyFixedFonts(bool)</slot>
+ </connection>
+</connections>
+<includes>
+ <include location="local" impldecl="in implementation">fontpreferences.ui.h</include>
+</includes>
+<slots>
+ <slot access="private">showOnlyFixedFonts( bool on )</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kbabel/kbabel/fontpreferences.ui.h b/kbabel/kbabel/fontpreferences.ui.h
new file mode 100644
index 00000000..065318f1
--- /dev/null
+++ b/kbabel/kbabel/fontpreferences.ui.h
@@ -0,0 +1,14 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+
+void FontPreferences::showOnlyFixedFonts( bool on)
+{
+ kcfg_MsgFont->setFont(kcfg_MsgFont->font(), on);
+}
diff --git a/kbabel/kbabel/gotodialog.cpp b/kbabel/kbabel/gotodialog.cpp
new file mode 100644
index 00000000..f822f0dc
--- /dev/null
+++ b/kbabel/kbabel/gotodialog.cpp
@@ -0,0 +1,74 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#include <qstring.h>
+#include <klocale.h>
+#include <knuminput.h>
+
+#include "gotodialog.h"
+
+GotoDialog::GotoDialog(int max,QWidget* parent)
+ : KDialogBase(parent,0,true,i18n("Go to Entry"),Ok|Cancel)
+{
+ QGroupBox* box=new QGroupBox(1,Qt::Horizontal,i18n("Go to Entry"),this);
+ _spinBox= new KIntSpinBox(1,max,1,1,10,box);
+
+ setMainWidget(box);
+
+ _spinBox->setFocus();
+}
+
+GotoDialog::~GotoDialog()
+{
+}
+
+
+void GotoDialog::show()
+{
+ _spinBox->setEditFocus(true);
+
+ KDialogBase::show();
+}
+
+
+int GotoDialog::number()
+{
+ return _spinBox->value();
+}
+
+void GotoDialog::setMax(int max)
+{
+ _spinBox->setRange(1,max);
+ if(_spinBox->value()>max)
+ _spinBox->setValue(max);
+}
diff --git a/kbabel/kbabel/gotodialog.h b/kbabel/kbabel/gotodialog.h
new file mode 100644
index 00000000..4c8378d8
--- /dev/null
+++ b/kbabel/kbabel/gotodialog.h
@@ -0,0 +1,63 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef GOTODIALOG_H
+#define GOTODIALOG_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <kdialogbase.h>
+#include <qgroupbox.h>
+
+class KIntSpinBox;
+
+class GotoDialog : public KDialogBase
+{
+public:
+ GotoDialog(int max, QWidget* parent);
+ virtual ~GotoDialog();
+
+ /** reimplemented to select contents when shown*/
+ virtual void show();
+
+ int number();
+ void setMax(int max);
+
+private:
+ KIntSpinBox* _spinBox;
+
+};
+
+
+#endif // GOTODIALOG_H
diff --git a/kbabel/kbabel/headereditor.cpp b/kbabel/kbabel/headereditor.cpp
new file mode 100644
index 00000000..55ad4eb5
--- /dev/null
+++ b/kbabel/kbabel/headereditor.cpp
@@ -0,0 +1,214 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2002-2003 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include <kcursor.h>
+#include <kglobalsettings.h>
+#include <kglobal.h>
+#include <kconfig.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <ktextedit.h>
+#include <kurl.h>
+
+#include "catalog.h"
+#include "catalogitem.h"
+#include "headereditor.h"
+#include "headerwidget.h"
+
+using namespace KBabel;
+
+HeaderEditor::HeaderEditor(Catalog* cat,const char* name)
+ : KDialogBase((QWidget*)0,name,false,QString::null, Ok|Cancel|Default|User1)
+{
+ restoreSettings();
+
+ _catalog=cat;
+ connect(_catalog,SIGNAL(signalFileOpened(bool)),this,SLOT(readHeader(bool)));
+ connect(_catalog,SIGNAL(signalHeaderChanged()),this,SLOT(updateHeader()));
+
+ setButtonText(User1,i18n("&Apply Settings"));
+ setButtonWhatsThis (User1, i18n("<qt><p>This button "
+ "updates the header using the current settings. "
+ "The resulting header is the one that would be written into the PO file "
+ "on saving.</p></qt>") );
+ setButtonText(Default,i18n("&Reset"));
+ setButtonWhatsThis (Default, i18n("<qt><p>This button "
+ "will revert all changes made so far.</p></qt>") );
+
+ _editor=new HeaderWidget(this,"internal headereditor");
+ _editor->setMinimumSize(_editorSize);
+
+ KCursor::setAutoHideCursor(_editor,true);
+
+ readHeader(cat->isReadOnly());
+ updateHeader();
+
+ setMainWidget(_editor);
+}
+
+HeaderEditor::~HeaderEditor()
+{
+ saveSettings();
+}
+
+void HeaderEditor::saveSettings()
+{
+ KConfig* config = KGlobal::config();
+
+ KConfigGroupSaver saver(config, "HeaderEditor" );
+
+ config->writeEntry( "Size", _editor->size() );
+}
+
+void HeaderEditor::restoreSettings()
+{
+ KConfig* config = KGlobal::config();
+
+ KConfigGroupSaver saver(config, "HeaderEditor" );
+
+ QSize defaultSize(350,250);
+ _editorSize = config->readSizeEntry("Size", &defaultSize );
+}
+
+bool HeaderEditor::isModified()
+{
+ return _editor->commentEdit->isModified() || _editor->headerEdit->isModified();
+}
+
+void HeaderEditor::readHeader(bool readOnly)
+{
+ setCaption(i18n("Header Editor for %1").arg(_catalog->currentURL().prettyURL()));
+
+ _editor->headerEdit->setReadOnly(readOnly);
+ _editor->commentEdit->setReadOnly(readOnly);
+ enableButton(User1,!readOnly);
+}
+
+void HeaderEditor::updateHeader()
+{
+ _editor->headerEdit->setText(_catalog->header().msgstr().first());
+ _editor->headerEdit->setModified(false);
+ _editor->commentEdit->setText(_catalog->header().comment());
+ _editor->commentEdit->setModified(false);
+}
+
+
+// update button
+void HeaderEditor::slotUser1()
+{
+ CatalogItem header;
+
+ bool error = !isValid();
+
+ if(error)
+ {
+ QString msg=i18n("<qt><p>This is not a valid header.</p>\n"
+ "<p>Please edit the header before updating!</p></qt>");
+
+ KMessageBox::sorry(this,msg);
+
+ return;
+ }
+
+ header.setComment( _editor->commentEdit->text() );
+ header.setMsgstr( _editor->headerEdit->text() );
+
+ header=_catalog->updatedHeader(header,true);
+
+ _editor->headerEdit->setText(header.msgstr().first());
+ _editor->commentEdit->setText(header.comment());
+}
+
+
+void HeaderEditor::slotDefault()
+{
+ updateHeader();
+}
+
+void HeaderEditor::slotCancel()
+{
+ updateHeader();
+
+ QDialog::reject();
+}
+
+void HeaderEditor::slotOk()
+{
+ if(isModified())
+ {
+ if(!isValid())
+ {
+ QString msg=i18n("<qt><p>This is not a valid header.</p>\n"
+ "<p>Please edit the header before updating.</p></qt>");
+
+ switch(KMessageBox::warningYesNo(this,msg,i18n("Warning"),KStdGuiItem::discard(),i18n("Edit")))
+ {
+ case KMessageBox::Yes:
+ {
+ slotCancel();
+ return;
+ }
+ default:
+ return;
+ }
+ }
+
+ CatalogItem header;
+
+ header.setComment( _editor->commentEdit->text() );
+ header.setMsgstr( _editor->headerEdit->text() );
+
+ _catalog->setHeader(header);
+ }
+
+ QDialog::accept();
+}
+
+bool HeaderEditor::isValid()
+{
+ // check the comments
+ QStringList comments = QStringList::split('\n',_editor->commentEdit->text());
+
+ for( QStringList::Iterator it = comments.begin(); it != comments.end(); ++it )
+ {
+ if( !(*it).startsWith("#") )
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+#include "headereditor.moc"
diff --git a/kbabel/kbabel/headereditor.h b/kbabel/kbabel/headereditor.h
new file mode 100644
index 00000000..9fb9d6fb
--- /dev/null
+++ b/kbabel/kbabel/headereditor.h
@@ -0,0 +1,85 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2002-2003 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef HEADEREDITOR_H
+#define HEADEREDITOR_H
+
+#include <kdialogbase.h>
+
+namespace KBabel
+{
+ class Catalog;
+}
+
+class HeaderWidget;
+
+class HeaderEditor : public KDialogBase
+{
+ Q_OBJECT
+public:
+ /**
+ * constructor for the HeaderEditor
+ * @param cat The Catalog from which the header is edited
+ */
+ HeaderEditor(KBabel::Catalog* cat,const char* name=0);
+ virtual ~HeaderEditor();
+
+ bool isModified();
+
+public slots:
+ void readHeader(bool);
+
+protected slots:
+
+ /** update button */
+ virtual void slotUser1();
+ virtual void slotCancel();
+ virtual void slotOk();
+ virtual void slotDefault();
+
+ /** updates the header when header was changed by the catalog */
+ void updateHeader();
+
+private:
+ void saveSettings();
+ void restoreSettings();
+ bool isValid();
+
+ KBabel::Catalog* _catalog;
+ HeaderWidget* _editor;
+
+ QSize _editorSize;
+};
+
+#endif // HEADEREDITOR_H
diff --git a/kbabel/kbabel/headerwidget.ui b/kbabel/kbabel/headerwidget.ui
new file mode 100644
index 00000000..f74a9ef5
--- /dev/null
+++ b/kbabel/kbabel/headerwidget.ui
@@ -0,0 +1,64 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>HeaderWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>HeaderWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>401</width>
+ <height>380</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>commentLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Comment:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>commentEdit</cstring>
+ </property>
+ </widget>
+ <widget class="KTextEdit">
+ <property name="name">
+ <cstring>commentEdit</cstring>
+ </property>
+ <property name="wordWrap">
+ <enum>NoWrap</enum>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>headerLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Header:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>headerEdit</cstring>
+ </property>
+ </widget>
+ <widget class="KTextEdit">
+ <property name="name">
+ <cstring>headerEdit</cstring>
+ </property>
+ <property name="wordWrap">
+ <enum>NoWrap</enum>
+ </property>
+ </widget>
+ </vbox>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>ktextedit.h</includehint>
+ <includehint>ktextedit.h</includehint>
+</includehints>
+</UI>
diff --git a/kbabel/kbabel/hi16-app-kbabel.png b/kbabel/kbabel/hi16-app-kbabel.png
new file mode 100644
index 00000000..3b062e51
--- /dev/null
+++ b/kbabel/kbabel/hi16-app-kbabel.png
Binary files differ
diff --git a/kbabel/kbabel/hi32-app-kbabel.png b/kbabel/kbabel/hi32-app-kbabel.png
new file mode 100644
index 00000000..b7f1e843
--- /dev/null
+++ b/kbabel/kbabel/hi32-app-kbabel.png
Binary files differ
diff --git a/kbabel/kbabel/hi48-app-kbabel.png b/kbabel/kbabel/hi48-app-kbabel.png
new file mode 100644
index 00000000..77bd3530
--- /dev/null
+++ b/kbabel/kbabel/hi48-app-kbabel.png
Binary files differ
diff --git a/kbabel/kbabel/hidingmsgedit.cpp b/kbabel/kbabel/hidingmsgedit.cpp
new file mode 100644
index 00000000..f18f8b81
--- /dev/null
+++ b/kbabel/kbabel/hidingmsgedit.cpp
@@ -0,0 +1,426 @@
+/***************************************************************************
+ hidingmsgedit.cpp - description
+ -------------------
+ begin : So nov 2 2002
+ copyright : (C) 2002 by Stanislav Visnovsky
+ email : visnovsky@kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+ ***************************************************************************/
+
+#include "resources.h"
+#include "hidingmsgedit.h"
+#include "mymultilineedit.h"
+#include "editcmd.h"
+
+#include <qptrlist.h>
+#include <qsizepolicy.h>
+#include <qstringlist.h>
+#include <qtabwidget.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+using namespace KBabel;
+
+HidingMsgEdit::HidingMsgEdit(uint numberOfPlurals, QWidget* eventFilter, KSpell* spell, QWidget *parent, const char *name ) :
+ QWidgetStack(parent,name)
+ , _singleEdit(0)
+ , _multipleEdit(0)
+ , _eventFilter(eventFilter)
+ , _currentEdit(0)
+ , _numberOfPlurals(numberOfPlurals)
+ , _spell(spell)
+{
+
+ _allEdits.clear();
+ setNumberOfPlurals( _numberOfPlurals );
+
+ connect( _multipleEdit, SIGNAL(currentChanged( QWidget* )),
+ this, SLOT( newCurrentMultiple( QWidget* )));
+
+ showSingle();
+}
+
+HidingMsgEdit::~HidingMsgEdit(){
+}
+
+void HidingMsgEdit::setText(QStringList texts, QString msgctxt){
+ if( texts.count() == 0 )
+ {
+ kdWarning() << "HidingMsgEdit::setText with empty text" << endl;
+ _singleEdit->clear();
+ showSingle();
+ return;
+ }
+
+ if (!msgctxt.isEmpty())
+ msgctxt = "\n>>>>> " + i18n("Context inserted by KBabel, do not translate:") + "\n" + msgctxt;
+
+ if( texts.count() == 1 )
+ {
+ _singleEdit->setText(*texts.at(0) + msgctxt);
+ showSingle();
+ }
+ else
+ {
+ if( _numberOfPlurals )
+ {
+ QStringList::iterator text = texts.begin();
+ uint i;
+ for( i=0 ; i < _numberOfPlurals && text!= texts.end() ; i++, text++ )
+ {
+ static_cast<MsgMultiLineEdit *>(_multipleEdit->page(i))->setText(*text + msgctxt);
+ }
+
+ // clean the non-initialized ones
+ while (i < _numberOfPlurals)
+ {
+ static_cast<MsgMultiLineEdit *>(_multipleEdit->page(i))->setText("");
+ i++;
+ }
+ }
+ showMultiple();
+ }
+}
+
+void HidingMsgEdit::showSingle(){
+ raiseWidget(_singleEdit);
+ _currentEdit=_singleEdit;
+ _currentEdit->setFocus();
+
+ emit currentFormChanged ( 0 );
+}
+
+void HidingMsgEdit::showMultiple(){
+ raiseWidget(_multipleEdit);
+ _currentEdit=static_cast<MsgMultiLineEdit*>(_multipleEdit->currentPage());
+ _currentEdit->setFocus();
+
+ emit currentFormChanged ( _multipleEdit->currentPageIndex () );
+}
+
+void HidingMsgEdit::showPlurals( bool on )
+{
+ if( on ) showMultiple();
+ else showSingle();
+}
+
+void HidingMsgEdit::showForm(int form)
+{
+ if( _currentEdit==_singleEdit && form>0 )
+ {
+ showMultiple();
+ _multipleEdit->setCurrentPage(form);
+ _currentEdit=static_cast<MsgMultiLineEdit*>(_multipleEdit->currentPage());
+ emit currentFormChanged ( form );
+ }
+ else
+ if( _currentEdit!=_singleEdit )
+ {
+ _multipleEdit->setCurrentPage(form);
+ _currentEdit=static_cast<MsgMultiLineEdit*>(_multipleEdit->currentPage());
+ emit currentFormChanged ( 0 );
+ }
+ _currentEdit->setFocus();
+}
+
+void HidingMsgEdit::setNumberOfPlurals( uint numberOfPlurals )
+{
+ _numberOfPlurals = numberOfPlurals;
+
+ // find out the current shown version
+ bool plurals = _currentEdit != _singleEdit;
+ bool readonly = _currentEdit ? _currentEdit->isReadOnly () : true;
+
+ // cleanup old
+ _currentEdit=0;
+ _allEdits.clear();
+ if( _singleEdit )
+ {
+ removeWidget( _singleEdit );
+ delete _singleEdit;
+ }
+
+ if( _multipleEdit )
+ {
+ removeWidget( _multipleEdit );
+ delete _multipleEdit;
+ }
+
+ // create new
+ _singleEdit = new MsgMultiLineEdit( 0, _spell, this, "singleEdit" );
+ _allEdits.append( _singleEdit );
+ if( _eventFilter )
+ _singleEdit->installEventFilter(_eventFilter);
+
+ _multipleEdit = new QTabWidget( this );
+
+ MsgMultiLineEdit* pl;
+ for(uint i=0 ; i< _numberOfPlurals ; i++)
+ {
+ pl = new MsgMultiLineEdit( i, _spell, _multipleEdit, QString("multipleEdit %1").arg(i).local8Bit());
+ _allEdits.append(pl);
+ _multipleEdit->addTab( pl, i18n("Plural %1").arg(i+1));
+ if( _eventFilter )
+ pl->installEventFilter(_eventFilter);
+ }
+
+ addWidget(_singleEdit);
+ addWidget(_multipleEdit);
+
+ for( MsgMultiLineEdit* e = _allEdits.first() ; e ; e = _allEdits.next() )
+ {
+ connect( e, SIGNAL( signalUndoCmd( KBabel::EditCommand* )),
+ this, SIGNAL( signalUndoCmd( KBabel::EditCommand* )));
+ connect( e, SIGNAL( textChanged() ) , this, SIGNAL( textChanged() ));
+ connect( e, SIGNAL( textChanged() ) , this, SLOT( emitTextChanged() ));
+ connect( e, SIGNAL( cursorPositionChanged( int, int )),
+ this, SLOT( emitCursorPositionChanged( int, int )) );
+ }
+
+ showPlurals( plurals );
+
+ _currentEdit->setReadOnly (readonly);
+}
+
+void HidingMsgEdit::emitTextChanged()
+{
+ emit textChanged(_currentEdit->text());
+}
+
+uint HidingMsgEdit::currentForm()
+{
+ if( _currentEdit == _singleEdit ) return 0;
+ else return _multipleEdit->currentPageIndex();
+}
+
+void HidingMsgEdit::newCurrentMultiple( QWidget* widget )
+{
+ _currentEdit = dynamic_cast<MsgMultiLineEdit*>(widget);
+ emit currentFormChanged ( _multipleEdit->currentPageIndex () );
+}
+
+bool HidingMsgEdit::isModified() {
+ for( MsgMultiLineEdit* e = _allEdits.first(); e ; e = _allEdits.next() )
+ {
+ if( e->isModified() )
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void HidingMsgEdit::setReadOnly(bool on) {
+ for( MsgMultiLineEdit* e = _allEdits.first(); e ; e = _allEdits.next() )
+ {
+ e->setReadOnly( on );
+ }
+}
+
+void HidingMsgEdit::processCommand(EditCommand* cmd, bool undo)
+{
+ if( _currentEdit == _singleEdit )
+ {
+ _singleEdit->processCommand(cmd,undo);
+ }
+ else
+ {
+ if( cmd->terminator() == 0)
+ {
+ static_cast<MsgMultiLineEdit*>(
+ _multipleEdit->page(static_cast<DelTextCmd*>(cmd)->pluralNumber)
+ )->processCommand(cmd,undo);
+ }
+ }
+}
+
+void HidingMsgEdit::setSpacePoints(bool on)
+{
+ for( MsgMultiLineEdit* e = _allEdits.first(); e ; e = _allEdits.next() )
+ {
+ e->setSpacePoints( on );
+ }
+}
+
+void HidingMsgEdit::setHighlightSyntax( bool on )
+{
+ for( MsgMultiLineEdit* e = _allEdits.first(); e ; e = _allEdits.next() )
+ {
+ e->setHighlightSyntax( on );
+ }
+}
+
+void HidingMsgEdit::setQuotes(bool on)
+{
+ for( MsgMultiLineEdit* e = _allEdits.first(); e ; e = _allEdits.next() )
+ {
+ e->setQuotes( on );
+ }
+}
+
+void HidingMsgEdit::setBgColor( const QColor& color)
+{
+ for( MsgMultiLineEdit* e = _allEdits.first(); e ; e = _allEdits.next() )
+ {
+ e->setBgColor( color );
+ }
+}
+
+void HidingMsgEdit::setHighlightColors(const QColor& quoteColor, const QColor& unquoteColor
+ , const QColor& cformatColor, const QColor& accelColor, const QColor& tagColor)
+{
+ for( MsgMultiLineEdit* e = _allEdits.first(); e ; e = _allEdits.next() )
+ {
+ e->setHighlightColors( quoteColor, unquoteColor, cformatColor,
+ accelColor, tagColor );
+ }
+}
+
+void HidingMsgEdit::setOverwriteMode( bool b )
+{
+ for( MsgMultiLineEdit* e = _allEdits.first(); e ; e = _allEdits.next() )
+ {
+ e->setOverwriteMode( b );
+ }
+}
+
+void HidingMsgEdit::setModified( bool b )
+{
+ for( MsgMultiLineEdit* e = _allEdits.first(); e ; e = _allEdits.next() )
+ {
+ e->setModified( b );
+ }
+}
+
+void HidingMsgEdit::setCleverEditing( bool on )
+{
+ for( MsgMultiLineEdit* e = _allEdits.first(); e ; e = _allEdits.next() )
+ {
+ e->setCleverEditing( on );
+ }
+}
+
+void HidingMsgEdit::setHighlightBg( bool on )
+{
+ for( MsgMultiLineEdit* e = _allEdits.first(); e ; e = _allEdits.next() )
+ {
+ e->setHighlightBg( on );
+ }
+}
+
+void HidingMsgEdit::setContextMenu( QPopupMenu *menu )
+{
+ for( MsgMultiLineEdit* e = _allEdits.first(); e ; e = _allEdits.next() )
+ {
+ e->setContextMenu( menu );
+ }
+}
+
+void HidingMsgEdit::setCurrentColor( const MsgMultiLineEdit::TextColor color)
+{
+ for( MsgMultiLineEdit* e = _allEdits.first(); e ; e = _allEdits.next() )
+ {
+ e->setCurrentColor( color );
+ }
+}
+
+bool HidingMsgEdit::hasFocus ()
+{
+ for( MsgMultiLineEdit* e = _allEdits.first(); e ; e = _allEdits.next() )
+ {
+ if( e->hasFocus() ) return true;
+ }
+
+ return _multipleEdit->hasFocus() || QWidgetStack::hasFocus();
+}
+
+void HidingMsgEdit::setDiffColors(const QColor& addColor, const QColor& delColor)
+{
+ for( MsgMultiLineEdit* e = _allEdits.first(); e ; e = _allEdits.next() )
+ {
+ e->setDiffColors( addColor, delColor );
+ }
+}
+
+void HidingMsgEdit::setDiffMode(bool on)
+{
+ for( MsgMultiLineEdit* e = _allEdits.first(); e ; e = _allEdits.next() )
+ {
+ e->setDiffMode( on );
+ }
+}
+
+void HidingMsgEdit::setDiffDisplayMode(bool underlineAdded, bool strikeOutDeleted)
+{
+ for( MsgMultiLineEdit* e = _allEdits.first(); e ; e = _allEdits.next() )
+ {
+ e->setDiffDisplayMode( underlineAdded, strikeOutDeleted );
+ }
+}
+
+void HidingMsgEdit::setFont(const QFont& font)
+{
+ for( MsgMultiLineEdit* e = _allEdits.first(); e ; e = _allEdits.next() )
+ {
+ e->setFont( font );
+ }
+}
+
+void HidingMsgEdit::setSpellChecker(KSpell* spell)
+{
+ for( MsgMultiLineEdit* e = _allEdits.first(); e ; e = _allEdits.next() )
+ {
+ e->setSpellChecker( spell );
+ }
+ _spell = spell;
+}
+
+void HidingMsgEdit::emitCursorPositionChanged(int line, int col )
+{
+ int linestart = 0;
+ int indexline = _currentEdit->lineOfChar( line, col );
+ if ( indexline > 0 )
+ {
+ int min = 0, max = col;
+ int i = (min + max)/2;
+ int iline = _currentEdit->lineOfChar( line, i );
+ while ( iline != indexline-1 ||
+ _currentEdit->lineOfChar( line, i+1 ) != indexline )
+ {
+ Q_ASSERT( min != max && min != i && max != i );
+ if ( iline < indexline )
+ min = i;
+ else
+ max = i;
+ i = (min + max)/2;
+ iline = _currentEdit->lineOfChar( line, i );
+ }
+ linestart = i+1;
+ }
+ Q_ASSERT( linestart >= 0 );
+
+ emit cursorPositionChanged(line + _currentEdit->lineOfChar( line, col ) ,col-linestart);
+}
+
+#include "hidingmsgedit.moc"
+
diff --git a/kbabel/kbabel/hidingmsgedit.h b/kbabel/kbabel/hidingmsgedit.h
new file mode 100644
index 00000000..38e5d750
--- /dev/null
+++ b/kbabel/kbabel/hidingmsgedit.h
@@ -0,0 +1,161 @@
+/***************************************************************************
+ hidingmsgedit.h - description
+ -------------------
+ begin : So nov 2 2002
+ copyright : (C) 2002 by Stanislav Visnovsky
+ email : visnovsky@kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+ * *
+ ***************************************************************************/
+
+#ifndef HIDINGMSGEDIT_H
+#define HIDINGMSGEDIT_H
+
+#include <qwidgetstack.h>
+#include <qguardedptr.h>
+#include <qptrlist.h>
+
+#include "mymultilineedit.h"
+
+class KSpell;
+class QTabWidget;
+class QPopupMenu;
+
+namespace KBabel
+{
+ class EditCommand;
+}
+
+/**
+ *@author Stanislav Visnovsky <visnovsky@kde.org>
+ */
+
+class HidingMsgEdit : public QWidgetStack {
+ Q_OBJECT
+public:
+ HidingMsgEdit(uint numberOfPlurals, QWidget* eventFilter=0, KSpell* spell=0, QWidget *parent=0, const char *name=0);
+ ~HidingMsgEdit();
+
+ void setNumberOfPlurals(uint numberOfPlurals);
+
+ // return index number for a currently shown plural form (0=singular or no plurals)
+ uint currentForm();
+
+ // MsgMultiLineEdit interface
+ bool isOverwriteMode() const { return _currentEdit->isOverwriteMode(); }
+ bool isModified();
+ bool hasSelectedText() const { return _currentEdit->hasSelectedText(); }
+ QString selectedText () const { return _currentEdit->selectedText(); }
+ void processCommand(KBabel::EditCommand* cmd, bool undo=false);
+ void offset2Pos(int offset, int &row, int &col) const
+ { return _currentEdit->offset2Pos(offset, row, col ); }
+ void getCursorPosition(int *para, int *index) const
+ { _currentEdit->getCursorPosition(para,index); }
+ int currentIndex() const
+ { return _currentEdit->currentIndex(); }
+ int beginOfLastMarkedText() const
+ { return _currentEdit->beginOfLastMarkedText(); }
+ virtual void setFont ( const QFont & );
+ void setCurrentColor(const MsgMultiLineEdit::TextColor color);
+ bool spacePoints() const { return _currentEdit->spacePoints(); }
+ void setSpacePoints(bool on);
+ bool quotes() const { return _currentEdit->quotes(); }
+ void setQuotes(bool on);
+ void setBgColor( const QColor& color);
+ bool highlightBg() const { return _currentEdit->highlightBg(); }
+ bool highlightSyntax() const { return _currentEdit->highlightSyntax(); }
+ void setHighlightColors(const QColor& quoteColor, const QColor& unquoteColor
+ , const QColor& cformatColor, const QColor& accelColor, const QColor& tagColor);
+ int beginOfMarkedText() { return _currentEdit->beginOfMarkedText(); }
+ virtual void insertAt ( const QString & s, int line, int col, bool mark = false )
+ { _currentEdit->insertAt( s, line, col, mark ); }
+
+ void setDiffMode(bool on);
+ void setDiffDisplayMode(bool underlineAdded, bool strikeOutDeleted);
+ void setDiffColors(const QColor& addColor, const QColor& delColor);
+ QString text(int para) { return _currentEdit->text(para); }
+
+ void setSpellChecker(KSpell* spell);
+
+ void selectTag(int start, int length) { _currentEdit->selectTag(start,length); }
+
+ // reiplemented to return correct value
+ bool hasFocus ();
+public slots: // Public slots
+ void setText(QStringList texts, QString msgctxt = QString::null);
+ void showSingle();
+ void showMultiple();
+ void showPlurals( bool on );
+ void showForm(int form);
+ virtual void setFocus() { _currentEdit->setFocus(); }
+ void forceUpdate() { _currentEdit->forceUpdate(); }
+
+ // MsgMultiLineEdit interface
+ virtual void setReadOnly( bool b );
+ virtual void setOverwriteMode( bool b );
+ virtual void setModified( bool b );
+ void setCleverEditing( bool on );
+ void setHighlightBg( bool on );
+ void setHighlightSyntax( bool on );
+ virtual void clear() { _currentEdit->clear(); }
+ virtual void cut() { _currentEdit->cut(); }
+ virtual void copy() { _currentEdit->copy(); }
+ virtual void paste() { _currentEdit->paste(); }
+ virtual void setSelection( int paraFrom, int indexFrom, int paraTo, int indexTo, int selNum = 0 )
+ { _currentEdit->setSelection( paraFrom, indexFrom, paraTo, indexTo, selNum) ; }
+ virtual void selectAll(bool select=true) { _currentEdit->selectAll(select); }
+ virtual void setCursorPosition ( int para, int index )
+ { _currentEdit->setCursorPosition(para,index); }
+ virtual void setContextMenu( QPopupMenu *menu );
+
+signals:
+ void signalUndoCmd(KBabel::EditCommand*);
+ void textChanged();
+ void textChanged(const QString&);
+ void cursorPositionChanged ( int para, int pos );
+ void currentFormChanged ( uint form );
+
+private slots:
+
+ void emitTextChanged();
+
+ // invoked if TabWidget changes the shown widget
+ void newCurrentMultiple( QWidget * );
+ // invoked by inner cursorPositionChanged() to transform line/col for wrapping
+ void emitCursorPositionChanged( int para, int pos );
+
+private: // Private attributes
+ /** Used for editting non-plural messages */
+ MsgMultiLineEdit* _singleEdit;
+ /** Used for editting plural forms */
+ QTabWidget* _multipleEdit;
+ QWidget* _eventFilter;
+
+ MsgMultiLineEdit* _currentEdit;
+ QPtrList<MsgMultiLineEdit> _allEdits;
+
+ uint _numberOfPlurals;
+
+ QGuardedPtr<KSpell> _spell;
+};
+
+#endif
diff --git a/kbabel/kbabel/icons/Makefile.am b/kbabel/kbabel/icons/Makefile.am
new file mode 100644
index 00000000..07f64107
--- /dev/null
+++ b/kbabel/kbabel/icons/Makefile.am
@@ -0,0 +1,5 @@
+# Add all of your pixmaps here
+icons_ICON = msgid2msgstr nexterror nextfuzzy nextfuzzyuntrans nextuntranslated preverror prevfuzzy prevfuzzyuntrans prevuntranslated search2msgstr transsearch insert_tag diff autodiff togglefuzzy insert_arg spellcheck_all spellcheck_actual spellcheck_from_cursor spellcheck_selected catalogmanager
+
+# This is where it will all be installed
+iconsdir = $(kde_datadir)/kbabel/icons
diff --git a/kbabel/kbabel/icons/hi16-action-autodiff.png b/kbabel/kbabel/icons/hi16-action-autodiff.png
new file mode 100644
index 00000000..d79e471f
--- /dev/null
+++ b/kbabel/kbabel/icons/hi16-action-autodiff.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi16-action-catalogmanager.png b/kbabel/kbabel/icons/hi16-action-catalogmanager.png
new file mode 100644
index 00000000..369ab591
--- /dev/null
+++ b/kbabel/kbabel/icons/hi16-action-catalogmanager.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi16-action-diff.png b/kbabel/kbabel/icons/hi16-action-diff.png
new file mode 100644
index 00000000..9e13d750
--- /dev/null
+++ b/kbabel/kbabel/icons/hi16-action-diff.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi16-action-insert_arg.png b/kbabel/kbabel/icons/hi16-action-insert_arg.png
new file mode 100644
index 00000000..e133f0e4
--- /dev/null
+++ b/kbabel/kbabel/icons/hi16-action-insert_arg.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi16-action-insert_tag.png b/kbabel/kbabel/icons/hi16-action-insert_tag.png
new file mode 100644
index 00000000..e0757463
--- /dev/null
+++ b/kbabel/kbabel/icons/hi16-action-insert_tag.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi16-action-msgid2msgstr.png b/kbabel/kbabel/icons/hi16-action-msgid2msgstr.png
new file mode 100644
index 00000000..6f5534fa
--- /dev/null
+++ b/kbabel/kbabel/icons/hi16-action-msgid2msgstr.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi16-action-nexterror.png b/kbabel/kbabel/icons/hi16-action-nexterror.png
new file mode 100644
index 00000000..78876d16
--- /dev/null
+++ b/kbabel/kbabel/icons/hi16-action-nexterror.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi16-action-nextfuzzy.png b/kbabel/kbabel/icons/hi16-action-nextfuzzy.png
new file mode 100644
index 00000000..6bcc43ed
--- /dev/null
+++ b/kbabel/kbabel/icons/hi16-action-nextfuzzy.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi16-action-nextfuzzyuntrans.png b/kbabel/kbabel/icons/hi16-action-nextfuzzyuntrans.png
new file mode 100644
index 00000000..d17b402f
--- /dev/null
+++ b/kbabel/kbabel/icons/hi16-action-nextfuzzyuntrans.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi16-action-nextuntranslated.png b/kbabel/kbabel/icons/hi16-action-nextuntranslated.png
new file mode 100644
index 00000000..317bb595
--- /dev/null
+++ b/kbabel/kbabel/icons/hi16-action-nextuntranslated.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi16-action-preverror.png b/kbabel/kbabel/icons/hi16-action-preverror.png
new file mode 100644
index 00000000..630da7d7
--- /dev/null
+++ b/kbabel/kbabel/icons/hi16-action-preverror.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi16-action-prevfuzzy.png b/kbabel/kbabel/icons/hi16-action-prevfuzzy.png
new file mode 100644
index 00000000..a381d93e
--- /dev/null
+++ b/kbabel/kbabel/icons/hi16-action-prevfuzzy.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi16-action-prevfuzzyuntrans.png b/kbabel/kbabel/icons/hi16-action-prevfuzzyuntrans.png
new file mode 100644
index 00000000..64995893
--- /dev/null
+++ b/kbabel/kbabel/icons/hi16-action-prevfuzzyuntrans.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi16-action-prevuntranslated.png b/kbabel/kbabel/icons/hi16-action-prevuntranslated.png
new file mode 100644
index 00000000..49610f03
--- /dev/null
+++ b/kbabel/kbabel/icons/hi16-action-prevuntranslated.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi16-action-search2msgstr.png b/kbabel/kbabel/icons/hi16-action-search2msgstr.png
new file mode 100644
index 00000000..99986bba
--- /dev/null
+++ b/kbabel/kbabel/icons/hi16-action-search2msgstr.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi16-action-spellcheck_actual.png b/kbabel/kbabel/icons/hi16-action-spellcheck_actual.png
new file mode 100644
index 00000000..1a653f5e
--- /dev/null
+++ b/kbabel/kbabel/icons/hi16-action-spellcheck_actual.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi16-action-spellcheck_all.png b/kbabel/kbabel/icons/hi16-action-spellcheck_all.png
new file mode 100644
index 00000000..c0b622d2
--- /dev/null
+++ b/kbabel/kbabel/icons/hi16-action-spellcheck_all.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi16-action-spellcheck_from_cursor.png b/kbabel/kbabel/icons/hi16-action-spellcheck_from_cursor.png
new file mode 100644
index 00000000..0bbd0a61
--- /dev/null
+++ b/kbabel/kbabel/icons/hi16-action-spellcheck_from_cursor.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi16-action-spellcheck_selected.png b/kbabel/kbabel/icons/hi16-action-spellcheck_selected.png
new file mode 100644
index 00000000..feacd83d
--- /dev/null
+++ b/kbabel/kbabel/icons/hi16-action-spellcheck_selected.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi16-action-togglefuzzy.png b/kbabel/kbabel/icons/hi16-action-togglefuzzy.png
new file mode 100644
index 00000000..3538fde6
--- /dev/null
+++ b/kbabel/kbabel/icons/hi16-action-togglefuzzy.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi16-action-transsearch.png b/kbabel/kbabel/icons/hi16-action-transsearch.png
new file mode 100644
index 00000000..e1776a6e
--- /dev/null
+++ b/kbabel/kbabel/icons/hi16-action-transsearch.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi22-action-autodiff.png b/kbabel/kbabel/icons/hi22-action-autodiff.png
new file mode 100644
index 00000000..91988ede
--- /dev/null
+++ b/kbabel/kbabel/icons/hi22-action-autodiff.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi22-action-catalogmanager.png b/kbabel/kbabel/icons/hi22-action-catalogmanager.png
new file mode 100644
index 00000000..48bbade3
--- /dev/null
+++ b/kbabel/kbabel/icons/hi22-action-catalogmanager.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi22-action-diff.png b/kbabel/kbabel/icons/hi22-action-diff.png
new file mode 100644
index 00000000..321ed59e
--- /dev/null
+++ b/kbabel/kbabel/icons/hi22-action-diff.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi22-action-insert_arg.png b/kbabel/kbabel/icons/hi22-action-insert_arg.png
new file mode 100644
index 00000000..6aa1da61
--- /dev/null
+++ b/kbabel/kbabel/icons/hi22-action-insert_arg.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi22-action-insert_tag.png b/kbabel/kbabel/icons/hi22-action-insert_tag.png
new file mode 100644
index 00000000..cbd50021
--- /dev/null
+++ b/kbabel/kbabel/icons/hi22-action-insert_tag.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi22-action-msgid2msgstr.png b/kbabel/kbabel/icons/hi22-action-msgid2msgstr.png
new file mode 100644
index 00000000..3323ada2
--- /dev/null
+++ b/kbabel/kbabel/icons/hi22-action-msgid2msgstr.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi22-action-nexterror.png b/kbabel/kbabel/icons/hi22-action-nexterror.png
new file mode 100644
index 00000000..24a94589
--- /dev/null
+++ b/kbabel/kbabel/icons/hi22-action-nexterror.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi22-action-nextfuzzy.png b/kbabel/kbabel/icons/hi22-action-nextfuzzy.png
new file mode 100644
index 00000000..2e302679
--- /dev/null
+++ b/kbabel/kbabel/icons/hi22-action-nextfuzzy.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi22-action-nextfuzzyuntrans.png b/kbabel/kbabel/icons/hi22-action-nextfuzzyuntrans.png
new file mode 100644
index 00000000..47a3c36a
--- /dev/null
+++ b/kbabel/kbabel/icons/hi22-action-nextfuzzyuntrans.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi22-action-nextuntranslated.png b/kbabel/kbabel/icons/hi22-action-nextuntranslated.png
new file mode 100644
index 00000000..eb4ea46c
--- /dev/null
+++ b/kbabel/kbabel/icons/hi22-action-nextuntranslated.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi22-action-preverror.png b/kbabel/kbabel/icons/hi22-action-preverror.png
new file mode 100644
index 00000000..089e5a12
--- /dev/null
+++ b/kbabel/kbabel/icons/hi22-action-preverror.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi22-action-prevfuzzy.png b/kbabel/kbabel/icons/hi22-action-prevfuzzy.png
new file mode 100644
index 00000000..aec1f219
--- /dev/null
+++ b/kbabel/kbabel/icons/hi22-action-prevfuzzy.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi22-action-prevfuzzyuntrans.png b/kbabel/kbabel/icons/hi22-action-prevfuzzyuntrans.png
new file mode 100644
index 00000000..4e7c88d4
--- /dev/null
+++ b/kbabel/kbabel/icons/hi22-action-prevfuzzyuntrans.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi22-action-prevuntranslated.png b/kbabel/kbabel/icons/hi22-action-prevuntranslated.png
new file mode 100644
index 00000000..8f5c764f
--- /dev/null
+++ b/kbabel/kbabel/icons/hi22-action-prevuntranslated.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi22-action-search2msgstr.png b/kbabel/kbabel/icons/hi22-action-search2msgstr.png
new file mode 100644
index 00000000..9df8dfca
--- /dev/null
+++ b/kbabel/kbabel/icons/hi22-action-search2msgstr.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi22-action-togglefuzzy.png b/kbabel/kbabel/icons/hi22-action-togglefuzzy.png
new file mode 100644
index 00000000..40227189
--- /dev/null
+++ b/kbabel/kbabel/icons/hi22-action-togglefuzzy.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi22-action-transsearch.png b/kbabel/kbabel/icons/hi22-action-transsearch.png
new file mode 100644
index 00000000..06d5852c
--- /dev/null
+++ b/kbabel/kbabel/icons/hi22-action-transsearch.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi32-action-autodiff.png b/kbabel/kbabel/icons/hi32-action-autodiff.png
new file mode 100644
index 00000000..471ece08
--- /dev/null
+++ b/kbabel/kbabel/icons/hi32-action-autodiff.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi32-action-catalogmanager.png b/kbabel/kbabel/icons/hi32-action-catalogmanager.png
new file mode 100644
index 00000000..d527b872
--- /dev/null
+++ b/kbabel/kbabel/icons/hi32-action-catalogmanager.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi32-action-diff.png b/kbabel/kbabel/icons/hi32-action-diff.png
new file mode 100644
index 00000000..535d508a
--- /dev/null
+++ b/kbabel/kbabel/icons/hi32-action-diff.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi32-action-insert_arg.png b/kbabel/kbabel/icons/hi32-action-insert_arg.png
new file mode 100644
index 00000000..ea8c8179
--- /dev/null
+++ b/kbabel/kbabel/icons/hi32-action-insert_arg.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi32-action-insert_tag.png b/kbabel/kbabel/icons/hi32-action-insert_tag.png
new file mode 100644
index 00000000..d11981ef
--- /dev/null
+++ b/kbabel/kbabel/icons/hi32-action-insert_tag.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi32-action-msgid2msgstr.png b/kbabel/kbabel/icons/hi32-action-msgid2msgstr.png
new file mode 100644
index 00000000..8dc03384
--- /dev/null
+++ b/kbabel/kbabel/icons/hi32-action-msgid2msgstr.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi32-action-nexterror.png b/kbabel/kbabel/icons/hi32-action-nexterror.png
new file mode 100644
index 00000000..ee458abc
--- /dev/null
+++ b/kbabel/kbabel/icons/hi32-action-nexterror.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi32-action-nextfuzzy.png b/kbabel/kbabel/icons/hi32-action-nextfuzzy.png
new file mode 100644
index 00000000..089e6357
--- /dev/null
+++ b/kbabel/kbabel/icons/hi32-action-nextfuzzy.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi32-action-nextfuzzyuntrans.png b/kbabel/kbabel/icons/hi32-action-nextfuzzyuntrans.png
new file mode 100644
index 00000000..82f535e6
--- /dev/null
+++ b/kbabel/kbabel/icons/hi32-action-nextfuzzyuntrans.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi32-action-nextuntranslated.png b/kbabel/kbabel/icons/hi32-action-nextuntranslated.png
new file mode 100644
index 00000000..8b9db6f7
--- /dev/null
+++ b/kbabel/kbabel/icons/hi32-action-nextuntranslated.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi32-action-preverror.png b/kbabel/kbabel/icons/hi32-action-preverror.png
new file mode 100644
index 00000000..7ff8da13
--- /dev/null
+++ b/kbabel/kbabel/icons/hi32-action-preverror.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi32-action-prevfuzzy.png b/kbabel/kbabel/icons/hi32-action-prevfuzzy.png
new file mode 100644
index 00000000..0280c02f
--- /dev/null
+++ b/kbabel/kbabel/icons/hi32-action-prevfuzzy.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi32-action-prevfuzzyuntrans.png b/kbabel/kbabel/icons/hi32-action-prevfuzzyuntrans.png
new file mode 100644
index 00000000..bcfb55aa
--- /dev/null
+++ b/kbabel/kbabel/icons/hi32-action-prevfuzzyuntrans.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi32-action-prevuntranslated.png b/kbabel/kbabel/icons/hi32-action-prevuntranslated.png
new file mode 100644
index 00000000..e4bdb694
--- /dev/null
+++ b/kbabel/kbabel/icons/hi32-action-prevuntranslated.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi32-action-search2msgstr.png b/kbabel/kbabel/icons/hi32-action-search2msgstr.png
new file mode 100644
index 00000000..3337b646
--- /dev/null
+++ b/kbabel/kbabel/icons/hi32-action-search2msgstr.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi32-action-togglefuzzy.png b/kbabel/kbabel/icons/hi32-action-togglefuzzy.png
new file mode 100644
index 00000000..0a9492a0
--- /dev/null
+++ b/kbabel/kbabel/icons/hi32-action-togglefuzzy.png
Binary files differ
diff --git a/kbabel/kbabel/icons/hi32-action-transsearch.png b/kbabel/kbabel/icons/hi32-action-transsearch.png
new file mode 100644
index 00000000..19e766c5
--- /dev/null
+++ b/kbabel/kbabel/icons/hi32-action-transsearch.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo16-action-autodiff.png b/kbabel/kbabel/icons/lo16-action-autodiff.png
new file mode 100644
index 00000000..7cb56260
--- /dev/null
+++ b/kbabel/kbabel/icons/lo16-action-autodiff.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo16-action-catalogmanager.png b/kbabel/kbabel/icons/lo16-action-catalogmanager.png
new file mode 100644
index 00000000..75a95c0c
--- /dev/null
+++ b/kbabel/kbabel/icons/lo16-action-catalogmanager.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo16-action-diff.png b/kbabel/kbabel/icons/lo16-action-diff.png
new file mode 100644
index 00000000..05b82b53
--- /dev/null
+++ b/kbabel/kbabel/icons/lo16-action-diff.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo16-action-insert_arg.png b/kbabel/kbabel/icons/lo16-action-insert_arg.png
new file mode 100644
index 00000000..bc67bc15
--- /dev/null
+++ b/kbabel/kbabel/icons/lo16-action-insert_arg.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo16-action-insert_tag.png b/kbabel/kbabel/icons/lo16-action-insert_tag.png
new file mode 100644
index 00000000..283b0793
--- /dev/null
+++ b/kbabel/kbabel/icons/lo16-action-insert_tag.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo16-action-msgid2msgstr.png b/kbabel/kbabel/icons/lo16-action-msgid2msgstr.png
new file mode 100644
index 00000000..8cb33ccb
--- /dev/null
+++ b/kbabel/kbabel/icons/lo16-action-msgid2msgstr.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo16-action-nexterror.png b/kbabel/kbabel/icons/lo16-action-nexterror.png
new file mode 100644
index 00000000..a2d48527
--- /dev/null
+++ b/kbabel/kbabel/icons/lo16-action-nexterror.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo16-action-nextfuzzy.png b/kbabel/kbabel/icons/lo16-action-nextfuzzy.png
new file mode 100644
index 00000000..828bfc3b
--- /dev/null
+++ b/kbabel/kbabel/icons/lo16-action-nextfuzzy.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo16-action-nextfuzzyuntrans.png b/kbabel/kbabel/icons/lo16-action-nextfuzzyuntrans.png
new file mode 100644
index 00000000..ad150c58
--- /dev/null
+++ b/kbabel/kbabel/icons/lo16-action-nextfuzzyuntrans.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo16-action-nextuntranslated.png b/kbabel/kbabel/icons/lo16-action-nextuntranslated.png
new file mode 100644
index 00000000..bbcda8c3
--- /dev/null
+++ b/kbabel/kbabel/icons/lo16-action-nextuntranslated.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo16-action-preverror.png b/kbabel/kbabel/icons/lo16-action-preverror.png
new file mode 100644
index 00000000..10c2f7e5
--- /dev/null
+++ b/kbabel/kbabel/icons/lo16-action-preverror.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo16-action-prevfuzzy.png b/kbabel/kbabel/icons/lo16-action-prevfuzzy.png
new file mode 100644
index 00000000..a19cb6ac
--- /dev/null
+++ b/kbabel/kbabel/icons/lo16-action-prevfuzzy.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo16-action-prevfuzzyuntrans.png b/kbabel/kbabel/icons/lo16-action-prevfuzzyuntrans.png
new file mode 100644
index 00000000..f63b3598
--- /dev/null
+++ b/kbabel/kbabel/icons/lo16-action-prevfuzzyuntrans.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo16-action-prevuntranslated.png b/kbabel/kbabel/icons/lo16-action-prevuntranslated.png
new file mode 100644
index 00000000..a3ad3431
--- /dev/null
+++ b/kbabel/kbabel/icons/lo16-action-prevuntranslated.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo16-action-search2msgstr.png b/kbabel/kbabel/icons/lo16-action-search2msgstr.png
new file mode 100644
index 00000000..36d25867
--- /dev/null
+++ b/kbabel/kbabel/icons/lo16-action-search2msgstr.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo16-action-spellcheck_actual.png b/kbabel/kbabel/icons/lo16-action-spellcheck_actual.png
new file mode 100644
index 00000000..1a653f5e
--- /dev/null
+++ b/kbabel/kbabel/icons/lo16-action-spellcheck_actual.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo16-action-spellcheck_all.png b/kbabel/kbabel/icons/lo16-action-spellcheck_all.png
new file mode 100644
index 00000000..c0b622d2
--- /dev/null
+++ b/kbabel/kbabel/icons/lo16-action-spellcheck_all.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo16-action-spellcheck_from_cursor.png b/kbabel/kbabel/icons/lo16-action-spellcheck_from_cursor.png
new file mode 100644
index 00000000..0bbd0a61
--- /dev/null
+++ b/kbabel/kbabel/icons/lo16-action-spellcheck_from_cursor.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo16-action-spellcheck_selected.png b/kbabel/kbabel/icons/lo16-action-spellcheck_selected.png
new file mode 100644
index 00000000..feacd83d
--- /dev/null
+++ b/kbabel/kbabel/icons/lo16-action-spellcheck_selected.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo16-action-togglefuzzy.png b/kbabel/kbabel/icons/lo16-action-togglefuzzy.png
new file mode 100644
index 00000000..3538fde6
--- /dev/null
+++ b/kbabel/kbabel/icons/lo16-action-togglefuzzy.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo16-action-transsearch.png b/kbabel/kbabel/icons/lo16-action-transsearch.png
new file mode 100644
index 00000000..f933a6eb
--- /dev/null
+++ b/kbabel/kbabel/icons/lo16-action-transsearch.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo32-action-autodiff.png b/kbabel/kbabel/icons/lo32-action-autodiff.png
new file mode 100644
index 00000000..b6cb074a
--- /dev/null
+++ b/kbabel/kbabel/icons/lo32-action-autodiff.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo32-action-catalogmanager.png b/kbabel/kbabel/icons/lo32-action-catalogmanager.png
new file mode 100644
index 00000000..1e9da58f
--- /dev/null
+++ b/kbabel/kbabel/icons/lo32-action-catalogmanager.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo32-action-diff.png b/kbabel/kbabel/icons/lo32-action-diff.png
new file mode 100644
index 00000000..8be1d0a4
--- /dev/null
+++ b/kbabel/kbabel/icons/lo32-action-diff.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo32-action-insert_arg.png b/kbabel/kbabel/icons/lo32-action-insert_arg.png
new file mode 100644
index 00000000..39fcf1fd
--- /dev/null
+++ b/kbabel/kbabel/icons/lo32-action-insert_arg.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo32-action-insert_tag.png b/kbabel/kbabel/icons/lo32-action-insert_tag.png
new file mode 100644
index 00000000..820bc66f
--- /dev/null
+++ b/kbabel/kbabel/icons/lo32-action-insert_tag.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo32-action-msgid2msgstr.png b/kbabel/kbabel/icons/lo32-action-msgid2msgstr.png
new file mode 100644
index 00000000..7497c265
--- /dev/null
+++ b/kbabel/kbabel/icons/lo32-action-msgid2msgstr.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo32-action-nexterror.png b/kbabel/kbabel/icons/lo32-action-nexterror.png
new file mode 100644
index 00000000..de06b7e8
--- /dev/null
+++ b/kbabel/kbabel/icons/lo32-action-nexterror.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo32-action-nextfuzzy.png b/kbabel/kbabel/icons/lo32-action-nextfuzzy.png
new file mode 100644
index 00000000..9218c291
--- /dev/null
+++ b/kbabel/kbabel/icons/lo32-action-nextfuzzy.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo32-action-nextfuzzyuntrans.png b/kbabel/kbabel/icons/lo32-action-nextfuzzyuntrans.png
new file mode 100644
index 00000000..6efbd5a7
--- /dev/null
+++ b/kbabel/kbabel/icons/lo32-action-nextfuzzyuntrans.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo32-action-nextuntranslated.png b/kbabel/kbabel/icons/lo32-action-nextuntranslated.png
new file mode 100644
index 00000000..c6954974
--- /dev/null
+++ b/kbabel/kbabel/icons/lo32-action-nextuntranslated.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo32-action-preverror.png b/kbabel/kbabel/icons/lo32-action-preverror.png
new file mode 100644
index 00000000..c8196a3e
--- /dev/null
+++ b/kbabel/kbabel/icons/lo32-action-preverror.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo32-action-prevfuzzy.png b/kbabel/kbabel/icons/lo32-action-prevfuzzy.png
new file mode 100644
index 00000000..4a078602
--- /dev/null
+++ b/kbabel/kbabel/icons/lo32-action-prevfuzzy.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo32-action-prevfuzzyuntrans.png b/kbabel/kbabel/icons/lo32-action-prevfuzzyuntrans.png
new file mode 100644
index 00000000..902c84cb
--- /dev/null
+++ b/kbabel/kbabel/icons/lo32-action-prevfuzzyuntrans.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo32-action-prevuntranslated.png b/kbabel/kbabel/icons/lo32-action-prevuntranslated.png
new file mode 100644
index 00000000..32ea00c4
--- /dev/null
+++ b/kbabel/kbabel/icons/lo32-action-prevuntranslated.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo32-action-search2msgstr.png b/kbabel/kbabel/icons/lo32-action-search2msgstr.png
new file mode 100644
index 00000000..b2a83b66
--- /dev/null
+++ b/kbabel/kbabel/icons/lo32-action-search2msgstr.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo32-action-togglefuzzy.png b/kbabel/kbabel/icons/lo32-action-togglefuzzy.png
new file mode 100644
index 00000000..0a9492a0
--- /dev/null
+++ b/kbabel/kbabel/icons/lo32-action-togglefuzzy.png
Binary files differ
diff --git a/kbabel/kbabel/icons/lo32-action-transsearch.png b/kbabel/kbabel/icons/lo32-action-transsearch.png
new file mode 100644
index 00000000..e91eedcc
--- /dev/null
+++ b/kbabel/kbabel/icons/lo32-action-transsearch.png
Binary files differ
diff --git a/kbabel/kbabel/kbabel-difftoproject.upd b/kbabel/kbabel/kbabel-difftoproject.upd
new file mode 100644
index 00000000..183f6268
--- /dev/null
+++ b/kbabel/kbabel/kbabel-difftoproject.upd
@@ -0,0 +1,6 @@
+Id=kde34
+File=kbabelrc,kbabel.defaultproject
+Group=Editor,Misc
+Key=DiffBaseDir
+Key=UseDBForDiff
+#eof
diff --git a/kbabel/kbabel/kbabel-project.upd b/kbabel/kbabel/kbabel-project.upd
new file mode 100644
index 00000000..20fcb958
--- /dev/null
+++ b/kbabel/kbabel/kbabel-project.upd
@@ -0,0 +1,11 @@
+Id=kde33
+File=kbabelrc,kbabel.defaultproject
+Group=CatalogManager
+AllKeys
+Group=Header
+AllKeys
+Group=Misc
+AllKeys
+Group=SourceContext
+AllKeys
+#eof
diff --git a/kbabel/kbabel/kbabel.cpp b/kbabel/kbabel/kbabel.cpp
new file mode 100644
index 00000000..cae7bf77
--- /dev/null
+++ b/kbabel/kbabel/kbabel.cpp
@@ -0,0 +1,1825 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2002-2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#include "kbabel.h"
+
+#include "kbabelsettings.h"
+#include "kbprojectsettings.h"
+#include "kbabelpref.h"
+#include "projectpref.h"
+#include "kbabelsplash.h"
+#include "regexpextractor.h"
+#include "toolaction.h"
+#include "commentview.h"
+#include "contextview.h"
+#include "charselectview.h"
+#include "taglistview.h"
+#include "sourceview.h"
+
+#include <qdragobject.h>
+#include <qlineedit.h>
+#include <qpopupmenu.h>
+#include <qhbox.h>
+#include <qwhatsthis.h>
+#include <qsize.h>
+#include <qtextcodec.h>
+#include <qtooltip.h>
+#include <qtimer.h>
+
+#include <dcopclient.h>
+#include <kdatatool.h>
+#include <kpopupmenu.h>
+#include <kstatusbar.h>
+#include <kstdaccel.h>
+#include <kedittoolbar.h>
+#include <kglobal.h>
+#include <kled.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <ktoolbar.h>
+#include <kfiledialog.h>
+#include <kconfig.h>
+#include <kurl.h>
+#include <kdialogbase.h>
+#include <kprogress.h>
+#include <kpushbutton.h>
+#include <kmessagebox.h>
+#include <kwin.h>
+#include <kaction.h>
+#include <kstdaction.h>
+#include <kspelldlg.h>
+#include <ksqueezedtextlabel.h>
+#include <kurldrag.h>
+
+#include "resources.h"
+#include "kbcatalog.h"
+#include "dictionarymenu.h"
+#include "kbabeldictbox.h"
+#include "kbmailer.h"
+#include "kbbookmarkhandler.h"
+#include "kbprojectmanager.h"
+#include "projectpref.h"
+#include "projectwizard.h"
+
+#include "version.h"
+
+#define ID_STATUS_TOTAL 1
+#define ID_STATUS_CURRENT 2
+#define ID_STATUS_FUZZY 3
+#define ID_STATUS_UNTRANS 4
+#define ID_STATUS_EDITMODE 5
+#define ID_STATUS_READONLY 6
+#define ID_STATUS_CURSOR 7
+
+// maximum number of recent files
+#define MAX_RECENT 10
+
+using namespace KBabel;
+
+QPtrList<KBabelPreferences> KBabelMW::prefDialogs;
+
+class MyKProgress: public KProgress
+{
+public:
+ MyKProgress( QWidget *parent, const char *name ) : KProgress( parent, name )
+ {
+ setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Preferred );
+ }
+ QSize sizeHint() const { return QSize( 1, 1);}
+};
+
+KBabelMW::KBabelMW(QString projectFile)
+ : KDockMainWindow (), m_charselectorview(0)
+{
+ if ( projectFile.isEmpty() )
+ projectFile = KBabel::ProjectManager::defaultProjectName();
+ _project = ProjectManager::open(projectFile);
+
+ if ( _project == NULL ) // FIXME should not happen anymore
+ {
+ KMessageBox::error( this, i18n("Cannot open project file\n%1").arg(projectFile)
+ , i18n("Project File Error"));
+ _project = ProjectManager::open(KBabel::ProjectManager::defaultProjectName());
+ }
+
+ KBCatalog* catalog=new KBCatalog(projectFile);
+ init(catalog);
+}
+
+KBabelMW::KBabelMW(KBCatalog* catalog, QString projectFile)
+ : KDockMainWindow (), m_charselectorview(0)
+{
+ if ( projectFile.isEmpty() )
+ projectFile = KBabel::ProjectManager::defaultProjectName();
+ _project = ProjectManager::open(projectFile);
+
+ if ( _project == NULL )
+ {
+ KMessageBox::error( this, i18n("Cannot open project file\n%1").arg(projectFile)
+ , i18n("Project File Error"));
+ _project = ProjectManager::open(KBabel::ProjectManager::defaultProjectName());
+ }
+
+ init(catalog);
+}
+
+void KBabelMW::init(KBCatalog* catalog)
+{
+ _config = KSharedConfig::openConfig( "kbabelrc" );
+
+ _toolsShortcuts.clear();
+
+ _fuzzyLed=0;
+ _untransLed=0;
+ _errorLed=0;
+
+ _projectDialog=0;
+
+ _prefDialog=0;
+ prefDialogs.setAutoDelete(true);
+
+ _statusbarTimer = new QTimer(this, "statusbartimer");
+ connect(_statusbarTimer,SIGNAL(timeout()),this
+ ,SLOT(clearStatusbarMsg()));
+
+ // FIXME:
+ Q_ASSERT(_project);
+
+ m_view=new KBabelView(catalog,this, _project);
+
+ setXMLFile ("kbabelui.rc");
+
+ createGUI (0);
+
+ // accept dnd
+ setAcceptDrops(true);
+
+
+ // setup our menubars and toolbars
+ setupStatusBar();
+ setupActions();
+ stateChanged( "fileopened" , StateReverse );
+ stateChanged( "readonly", StateNoReverse );
+
+ QPopupMenu* popup;
+ popup = (QPopupMenu*)(factory()->container("rmb_edit", this));
+ if(popup)
+ {
+ m_view->setRMBEditMenu(popup);
+ }
+ popup = (QPopupMenu*)(factory()->container("rmb_search", this));
+ if(popup)
+ {
+ m_view->setRMBSearchMenu(popup);
+ }
+
+
+ connect(catalog,SIGNAL(signalUndoAvailable(bool)),this
+ ,SLOT(enableUndo(bool)));
+ connect(catalog,SIGNAL(signalRedoAvailable(bool)),this
+ ,SLOT(enableRedo(bool)));
+ connect(catalog,SIGNAL(signalNumberOfFuzziesChanged(uint)),this
+ ,SLOT(setNumberOfFuzzies(uint)));
+ connect(catalog,SIGNAL(signalNumberOfUntranslatedChanged(uint)),this
+ ,SLOT(setNumberOfUntranslated(uint)));
+ connect(catalog,SIGNAL(signalTotalNumberChanged(uint)),this
+ ,SLOT(setNumberOfTotal(uint)));
+ connect(catalog,SIGNAL(signalProgress(int)),_progressBar,SLOT(setProgress(int)));
+ connect(catalog,SIGNAL(signalClearProgressBar()),this,SLOT(clearProgressBar()));
+ connect(catalog,SIGNAL(signalResetProgressBar(QString,int))
+ ,this,SLOT(prepareProgressBar(QString,int)));
+ connect(catalog,SIGNAL(signalFileOpened(bool)),this,SLOT(enableDefaults(bool)));
+ connect(catalog,SIGNAL(signalFileOpened(bool)),m_view,SLOT(newFileOpened(bool)));
+ connect(catalog,SIGNAL(signalModified(bool)),this,SLOT(showModified(bool)));
+
+ // allow the view to change the statusbar and caption
+ connect(m_view, SIGNAL(signalChangeStatusbar(const QString&)),
+ this, SLOT(changeStatusbar(const QString&)));
+ connect(m_view, SIGNAL(signalChangeCaption(const QString&)),
+ this, SLOT(changeCaption(const QString&)));
+ connect(m_view,SIGNAL(signalFirstDisplayed(bool, bool)),this
+ ,SLOT(firstEntryDisplayed(bool, bool)));
+ connect(m_view,SIGNAL(signalLastDisplayed(bool, bool)),this
+ ,SLOT(lastEntryDisplayed(bool, bool)));
+ connect(m_view,SIGNAL(signalFuzzyDisplayed(bool)),this
+ ,SLOT(fuzzyDisplayed(bool)));
+ connect(m_view,SIGNAL(signalUntranslatedDisplayed(bool)),this
+ ,SLOT(untranslatedDisplayed(bool)));
+ connect(m_view,SIGNAL(signalFaultyDisplayed(bool)),this
+ ,SLOT(faultyDisplayed(bool)));
+ connect(m_view,SIGNAL(signalDisplayed(const KBabel::DocPosition&)),this
+ ,SLOT(displayedEntryChanged(const KBabel::DocPosition&)));
+ connect(m_view,SIGNAL(signalFuzzyAfterwards(bool)),this
+ ,SLOT(hasFuzzyAfterwards(bool)));
+ connect(m_view,SIGNAL(signalFuzzyInFront(bool)),this
+ ,SLOT(hasFuzzyInFront(bool)));
+ connect(m_view,SIGNAL(signalUntranslatedAfterwards(bool)),this
+ ,SLOT(hasUntranslatedAfterwards(bool)));
+ connect(m_view,SIGNAL(signalUntranslatedInFront(bool)),this
+ ,SLOT(hasUntranslatedInFront(bool)));
+ connect(m_view,SIGNAL(signalErrorAfterwards(bool)),this
+ ,SLOT(hasErrorAfterwards(bool)));
+ connect(m_view,SIGNAL(signalErrorInFront(bool)),this
+ ,SLOT(hasErrorInFront(bool)));
+ connect(m_view,SIGNAL(signalBackHistory(bool)),this
+ ,SLOT(enableBackHistory(bool)));
+ connect(m_view,SIGNAL(signalForwardHistory(bool)),this
+ ,SLOT(enableForwardHistory(bool)));
+
+
+ connect(m_view,SIGNAL(ledColorChanged(const QColor&)),this
+ ,SLOT(setLedColor(const QColor&)));
+
+
+ connect(m_view,SIGNAL(signalSearchActive(bool)),this,SLOT(enableStop(bool)));
+
+ connect(m_view,SIGNAL(signalProgress(int)),_progressBar,SLOT(setProgress(int)));
+ connect(m_view,SIGNAL(signalClearProgressBar()),this,SLOT(clearProgressBar()));
+ connect(m_view,SIGNAL(signalResetProgressBar(QString,int))
+ ,this,SLOT(prepareProgressBar(QString,int)));
+
+ connect(m_view,SIGNAL(signalDictionariesChanged())
+ , this, SLOT(buildDictMenus()));
+ connect(m_view,SIGNAL(signalCursorPosChanged(int,int)), this
+ , SLOT(updateCursorPosition(int,int)));
+
+ if(!catalog->currentURL().isEmpty())
+ {
+ enableDefaults(catalog->isReadOnly());
+ setNumberOfFuzzies(catalog->numberOfFuzzies());
+ setNumberOfUntranslated(catalog->numberOfUntranslated());
+ setNumberOfTotal(catalog->numberOfEntries());
+
+ enableUndo(catalog->isUndoAvailable());
+ enableUndo(catalog->isRedoAvailable());
+
+ m_view->emitEntryState();
+
+ changeCaption(catalog->currentURL().prettyURL() );
+ }
+
+ mailer = new KBabelMailer( this, _project );
+
+ bmHandler = new KBabelBookmarkHandler((QPopupMenu*)factory()->container("bookmark", this));
+ // the earlier created KAction for "clear_bookmarks" is now reconnected
+ KAction* action = actionCollection()->action("clear_bookmarks");
+ if (action) {
+ action->disconnect(SIGNAL(activated()));
+ connect(action, SIGNAL(activated()),
+ bmHandler, SLOT(slotClearBookmarks()));
+ }
+ connect(bmHandler, SIGNAL(signalBookmarkSelected(int)),
+ this, SLOT(slotOpenBookmark(int)));
+ connect(m_view, SIGNAL(signalNewFileOpened(KURL)),
+ bmHandler, SLOT(slotClearBookmarks()));
+
+ _config = KSharedConfig::openConfig( "kbabelrc" );
+ restoreSettings();
+
+ _config->setGroup("KBabel");
+
+ if(!_config->hasKey("Version"))
+ {
+ QString encodingStr;
+ switch(catalog->saveSettings().encoding)
+ {
+ case KBabel::ProjectSettingsBase::UTF8:
+ encodingStr=QTextCodec::codecForName("UTF-8")->name();
+ break;
+ case KBabel::ProjectSettingsBase::UTF16:
+ encodingStr=QTextCodec::codecForName("UTF-16")->name();
+ break;
+ default:
+ encodingStr=QTextCodec::codecForLocale()->name();
+ }
+
+ if( KBabelSplash::instance ) KBabelSplash::instance->close(); //close splash screen window, if there is one
+
+ KMessageBox::information(0,i18n("You have not run KBabel before. "
+ "To allow KBabel to work correctly you must enter some "
+ "information in the preferences dialog first.\n"
+ "The minimum requirement is to fill out the Identity page.\n"
+ "Also check the encoding on the Save page, which is currently "
+ "set to %1. You may want to change this setting "
+ "according to the settings of your language team.").arg(encodingStr));
+
+ QTimer::singleShot(1,this,SLOT(projectConfigure()));
+ }
+
+ _config->writeEntry("Version",VERSION);
+ _config->sync();
+
+}
+
+KBabelMW::~KBabelMW()
+{
+ if(_prefDialog)
+ {
+ prefDialogs.remove(_prefDialog);
+ }
+ if(_projectDialog)
+ {
+ delete _projectDialog;
+ }
+ delete mailer;
+ delete bmHandler;
+}
+
+
+void KBabelMW::setSettings(SaveSettings saveOpts,IdentitySettings idOpts)
+{
+ m_view->updateSettings();
+ m_view->catalog()->setSettings(saveOpts);
+ m_view->catalog()->setSettings(idOpts);
+
+ if(_fuzzyLed)
+ {
+ _fuzzyLed->setColor(KBabelSettings::ledColor());
+ }
+ if(_untransLed)
+ {
+ _untransLed->setColor(KBabelSettings::ledColor());
+ }
+ if(_errorLed)
+ {
+ _errorLed->setColor(KBabelSettings::ledColor());
+ }
+
+}
+
+void KBabelMW::updateSettings()
+{
+ m_view->updateSettings();
+
+ if(_fuzzyLed)
+ {
+ _fuzzyLed->setColor(KBabelSettings::ledColor());
+ }
+ if(_untransLed)
+ {
+ _untransLed->setColor(KBabelSettings::ledColor());
+ }
+ if(_errorLed)
+ {
+ _errorLed->setColor(KBabelSettings::ledColor());
+ }
+
+}
+
+
+void KBabelMW::setupActions()
+{
+ KAction* action;
+
+ // the file menu
+ action = KStdAction::open(this, SLOT(fileOpen()), actionCollection());
+
+ a_recent = KStdAction::openRecent(this, SLOT(openRecent(const KURL&)), actionCollection());
+ a_recent->setMaxItems(MAX_RECENT);
+
+ action = KStdAction::revert(m_view,SLOT(revertToSaved()),actionCollection());
+ action=KStdAction::save(this, SLOT(fileSave()), actionCollection());
+ action = KStdAction::saveAs(this, SLOT(fileSaveAs()), actionCollection());
+ action = new KAction(i18n("Save Sp&ecial..."), 0, this, SLOT(fileSaveSpecial()),
+ actionCollection(), "save_special" );
+ action = new KAction(i18n("Set &Package..."), 0, m_view, SLOT(setFilePackage()),
+ actionCollection(), "set_package" );
+
+ action = KStdAction::mail(this, SLOT(fileMail()), actionCollection());
+
+ action = new KAction(i18n("&New View"), 0, this, SLOT(fileNewView()),
+ actionCollection(), "file_new_view");
+
+ action = new KAction(i18n("New &Window"), 0, this, SLOT(fileNewWindow()),
+ actionCollection(), "file_new_window");
+ action->setShortcut( KStdAccel::openNew() );
+
+ action = KStdAction::quit(this, SLOT(quit()), actionCollection());
+
+
+
+ // the edit menu
+ action = KStdAction::undo(m_view, SLOT(undo()), actionCollection());
+ action = KStdAction::redo(m_view, SLOT(redo()), actionCollection());
+ action = KStdAction::cut(m_view, SIGNAL(signalCut()), actionCollection());
+ action = KStdAction::copy(m_view, SIGNAL(signalCopy()), actionCollection());
+ action = KStdAction::paste(m_view, SIGNAL(signalPaste()), actionCollection());
+ action = KStdAction::selectAll(m_view, SIGNAL(signalSelectAll()), actionCollection());
+ action = KStdAction::find(m_view, SLOT(find()), actionCollection());
+ action = KStdAction::findNext(m_view, SLOT(findNext()), actionCollection());
+ action = KStdAction::findPrev(m_view, SLOT(findPrev()), actionCollection());
+ action = KStdAction::replace(m_view, SLOT(replace()), actionCollection());
+
+ action = KStdAction::clear( m_view, SLOT(clear()), actionCollection(), "clear" );
+
+ action = new KAction(i18n("Cop&y Msgid to Msgstr"), "msgid2msgstr", CTRL+Key_Space, m_view
+ ,SLOT(msgid2msgstr()), actionCollection(), "msgid2msgstr");
+ action = new KAction(i18n("Copy Searc&h Result to Msgstr"), "search2msgstr",
+ CTRL+ALT+Key_Space, m_view, SLOT(search2msgstr()),
+ actionCollection(), "search2msgstr");
+ action = new KAction(i18n("Copy Msgstr to Other &Plurals"), Key_F11, m_view
+ ,SLOT(plural2msgstr()), actionCollection(), "plural2msgstr");
+ action = new KAction(i18n("Copy Selected Character to Msgstr"), Key_F10, m_charselectorview
+ ,SLOT(emitChar()), actionCollection(), "char2msgstr");
+
+ a_unsetFuzzy = new KAction(i18n("To&ggle Fuzzy Status"), "togglefuzzy", CTRL+Key_U, m_view
+ , SLOT(removeFuzzyStatus()), actionCollection(), "edit_toggle_fuzzy");
+ action = new KAction(i18n("&Edit Header..."), 0, m_view, SLOT(editHeader()),
+ actionCollection(), "edit_edit_header");
+
+ action = new KAction(i18n("&Insert Next Tag"), "insert_tag", CTRL+ALT+Key_N
+ , m_view, SLOT(insertNextTag())
+ , actionCollection(),"insert_next_tag");
+ connect(m_view,SIGNAL(signalNextTagAvailable(bool)),action
+ ,SLOT(setEnabled(bool)));
+ action = new KAction(i18n("Insert Next Tag From Msgid P&osition"), "insert_tag", CTRL+Key_M
+ , m_view, SLOT(insertNextTagMsgid())
+ , actionCollection(),"insert_next_tag_msgid");
+ connect(m_view,SIGNAL(signalNextTagAvailable(bool)),action
+ ,SLOT(setEnabled(bool)));
+ KActionMenu *actionMenu= new KActionMenu(i18n("Inser&t Tag"), "insert_tag"
+ , actionCollection(),"insert_tag");
+ m_view->setTagsMenu(actionMenu->popupMenu());
+ connect(m_view,SIGNAL(signalTagsAvailable(bool)),actionMenu
+ ,SLOT(setEnabled(bool)));
+ connect(actionMenu,SIGNAL(activated()),m_view,SLOT(insertNextTag()));
+
+ action = new KAction(i18n("Show Tags Menu"),CTRL+Key_Less
+ , m_view, SLOT(showTagsMenu()), actionCollection(),"show_tags_menu");
+ action->setEnabled(false);
+
+ connect(m_view,SIGNAL(signalTagsAvailable(bool)),action
+ ,SLOT(setEnabled(bool)));
+
+ action = new KAction(i18n("Move to Next Tag"), 0, CTRL+ALT+Key_M
+ , m_view, SLOT(skipToNextTag())
+ , actionCollection(),"move_to_next_tag");
+
+ action = new KAction(i18n("Move to Previous Tag"), 0, CTRL+ALT+Key_B
+ , m_view, SLOT(skipToPreviousTag())
+ , actionCollection(),"move_to_prev_tag");
+
+ action = new KAction(i18n("Insert Next Argument"), "insert_arg", CTRL+ALT+Key_G
+ , m_view, SLOT(insertNextArg())
+ , actionCollection(),"insert_next_arg");
+ connect(m_view,SIGNAL(signalNextArgAvailable(bool)),action
+ ,SLOT(setEnabled(bool)));
+ actionMenu= new KActionMenu(i18n("Inser&t Argument"), "insert_arg"
+ , actionCollection(),"insert_arg");
+ m_view->setArgsMenu(actionMenu->popupMenu());
+ connect(m_view,SIGNAL(signalArgsAvailable(bool)),actionMenu
+ ,SLOT(setEnabled(bool)));
+ connect(actionMenu,SIGNAL(activated()),m_view,SLOT(insertNextArg()));
+
+ action = new KAction(i18n("Show Arguments Menu"),CTRL+Key_Percent
+ , m_view, SLOT(showArgsMenu()), actionCollection(),"show_args_menu");
+ action->setEnabled(false);
+
+ connect(m_view,SIGNAL(signalArgsAvailable(bool)),action
+ ,SLOT(setEnabled(bool)));
+
+ // next, the go-menu
+ action = new KAction(i18n("&Previous"), "previous",
+ KStdAccel::shortcut(KStdAccel::Prior), m_view , SLOT(gotoPrev()),
+ actionCollection(),"go_prev_entry");
+ action = new KAction(i18n("&Next"), "next",
+ KStdAccel::shortcut(KStdAccel::Next), m_view , SLOT(gotoNext()),
+ actionCollection(),"go_next_entry");
+ action = KStdAction::goTo(m_view, SLOT(gotoEntry()), actionCollection());
+ action->setShortcut( KStdAccel::gotoLine());
+ action = KStdAction::firstPage(m_view, SLOT(gotoFirst()),actionCollection());
+ action->setText(i18n("&First Entry"));
+ action->setShortcut(CTRL+ALT+Key_Home);
+ action = KStdAction::lastPage(m_view, SLOT(gotoLast()),actionCollection());
+ action->setText(i18n("&Last Entry"));
+ action->setShortcut(CTRL+ALT+Key_End);
+ a_prevFoU = new KAction(i18n("P&revious Fuzzy or Untranslated"),"prevfuzzyuntrans",
+ CTRL+SHIFT+Key_Prior, m_view,
+ SLOT(gotoPrevFuzzyOrUntrans()),actionCollection(), "go_prev_fuzzyUntr");
+ a_nextFoU = new KAction(i18n("N&ext Fuzzy or Untranslated"),"nextfuzzyuntrans",
+ CTRL+SHIFT+Key_Next, m_view,
+ SLOT(gotoNextFuzzyOrUntrans()),actionCollection(), "go_next_fuzzyUntr");
+ a_prevFuzzy = new KAction(i18n("Pre&vious Fuzzy"),"prevfuzzy",
+ CTRL+Key_Prior, m_view,
+ SLOT(gotoPrevFuzzy()),actionCollection(), "go_prev_fuzzy");
+ a_nextFuzzy = new KAction(i18n("Ne&xt Fuzzy"), "nextfuzzy",
+ CTRL+Key_Next, m_view,
+ SLOT(gotoNextFuzzy()),actionCollection(), "go_next_fuzzy");
+ a_prevUntrans = new KAction(i18n("Prev&ious Untranslated"), "prevuntranslated",
+ ALT+Key_Prior, m_view,
+ SLOT(gotoPrevUntranslated()),actionCollection(), "go_prev_untrans");
+ a_nextUntrans = new KAction(i18n("Nex&t Untranslated"), "nextuntranslated",
+ ALT+Key_Next, m_view,
+ SLOT(gotoNextUntranslated()),actionCollection(), "go_next_untrans");
+ action = new KAction(i18n("Previo&us Error"), "preverror",
+ SHIFT+Key_Prior, m_view,
+ SLOT(gotoPrevError()),actionCollection(), "go_prev_error");
+ action = new KAction(i18n("Next Err&or"), "nexterror",
+ SHIFT+Key_Next, m_view,
+ SLOT(gotoNextError()),actionCollection(), "go_next_error");
+ action = new KAction(i18n("&Back in History"), "back", ALT+Key_Left, m_view,
+ SLOT(backHistory()),actionCollection(), "go_back_history");
+ action = new KAction(i18n("For&ward in History"), "forward", ALT+Key_Right, m_view,
+ SLOT(forwardHistory()),actionCollection(), "go_forward_history");
+
+ // the search menu
+ actionMenu=new KActionMenu(i18n("&Find Text"),
+ "transsearch",actionCollection(),"dict_search_all");
+ connect(actionMenu,SIGNAL(activated()),m_view,SLOT(startSearch()));
+ dictMenu = new DictionaryMenu(actionMenu->popupMenu(),actionCollection(),this);
+ connect(dictMenu,SIGNAL(activated(const QString)), m_view
+ , SLOT(startSearch(const QString)));
+
+ actionMenu=new KActionMenu(i18n("F&ind Selected Text"),
+ "transsearch",actionCollection(),"dict_search_selected");
+ connect(actionMenu,SIGNAL(activated()),m_view,SLOT(startSelectionSearch()));
+ selectionDictMenu = new DictionaryMenu(actionMenu->popupMenu(),actionCollection(),this);
+ connect(selectionDictMenu,SIGNAL(activated(const QString)), m_view
+ , SLOT(startSelectionSearch(const QString)));
+
+ actionMenu=new KActionMenu(i18n("&Edit Dictionary"),
+ "transsearch",actionCollection(),"dict_edit");
+ editDictMenu = new DictionaryMenu(actionMenu->popupMenu(),actionCollection(),this);
+ connect(editDictMenu,SIGNAL(activated(const QString)), m_view
+ , SLOT(editDictionary(const QString)));
+
+
+ actionMenu=new KActionMenu(i18n("Con&figure Dictionary"),
+ "transsearch",actionCollection(),"dict_configure");
+ configDictMenu = new DictionaryMenu(actionMenu->popupMenu(),actionCollection(),this);
+ connect(configDictMenu,SIGNAL(activated(const QString)), m_view
+ , SLOT(configureDictionary(const QString)));
+
+ actionMenu=new KActionMenu(i18n("About Dictionary"), "transsearch",
+ actionCollection(), "dict_about");
+ aboutDictMenu = new DictionaryMenu(actionMenu->popupMenu(),actionCollection(),this);
+ connect(aboutDictMenu,SIGNAL(activated(const QString)), m_view
+ , SLOT(aboutDictionary(const QString)));
+
+ buildDictMenus();
+
+ // the project menu
+ action = new KAction(i18n("&New..."), "filenew"
+ , this, SLOT(projectNew()),actionCollection()
+ ,"project_new");
+
+ action = new KAction(i18n("&Open..."), "fileopen"
+ , this, SLOT(projectOpen()),actionCollection()
+ ,"project_open");
+
+ action = new KAction(i18n("C&lose"), "fileclose"
+ , this, SLOT(projectClose()),actionCollection()
+ ,"project_close");
+ action->setEnabled (_project->filename() != KBabel::ProjectManager::defaultProjectName() );
+
+ action = new KAction(i18n("&Configure..."), "configure"
+ , this, SLOT(projectConfigure()),actionCollection()
+ ,"project_settings");
+
+ a_recentprojects = new KRecentFilesAction(i18n("Open &Recent"), 0, this, SLOT(projectOpenRecent(const KURL&)), actionCollection(), "recent_projects");
+
+ // the tools menu
+ action = new KAction(i18n("&Spell Check..."), "spellcheck", CTRL+Key_I
+ , m_view, SLOT(spellcheckCommon()),actionCollection()
+ ,"spellcheck_common");
+ action = new KAction(i18n("&Check All..."), "spellcheck_all", 0
+ , m_view, SLOT(spellcheckAll()),actionCollection()
+ ,"spellcheck_all");
+ action = new KAction(i18n("C&heck From Cursor Position..."), "spellcheck_from_cursor", 0
+ , m_view, SLOT(spellcheckFromCursor()),actionCollection()
+ ,"spellcheck_from_cursor");
+ action = new KAction(i18n("Ch&eck Current..."), "spellcheck_actual", 0
+ , m_view, SLOT(spellcheckCurrent()),actionCollection()
+ ,"spellcheck_current");
+ action = new KAction(i18n("Check Fro&m Current to End of File..."), 0
+ , m_view, SLOT(spellcheckFromCurrent()),actionCollection()
+ ,"spellcheck_from_current");
+ action = new KAction(i18n("Chec&k Selected Text..."), "spellcheck_selected", 0
+ , m_view, SLOT(spellcheckMarked()),actionCollection()
+ ,"spellcheck_marked");
+
+ KToggleAction *toggleAction;
+
+ toggleAction = new KToggleAction(i18n("&Diffmode"), "autodiff", 0
+ ,actionCollection(), "diff_toggleDiff");
+ connect(toggleAction,SIGNAL(toggled(bool)), m_view, SLOT(toggleAutoDiff(bool)));
+ connect(m_view,SIGNAL(signalDiffEnabled(bool)), toggleAction
+ , SLOT(setChecked(bool)));
+ toggleAction->setChecked(m_view->autoDiffEnabled());
+
+ action = new KAction(i18n("&Show Diff"), "diff", Key_F5
+ , m_view, SLOT(diff()),actionCollection()
+ ,"diff_diff");
+ action = new KAction(i18n("S&how Original Text"), "contents", Key_F6
+ , m_view, SLOT(diffShowOrig()),actionCollection()
+ ,"diff_showOrig");
+
+ action = new KAction(i18n("&Open File for Diff"), "fileopen" ,0
+ , m_view, SLOT(openDiffFile()),actionCollection()
+ ,"diff_openFile");
+
+ action = new KAction(i18n("&Rough Translation..."), 0
+ , m_view, SLOT(roughTranslation()),actionCollection()
+ ,"rough_translation");
+
+ action = new KAction(i18n("&Catalog Manager..."),"catalogmanager", 0 , this,
+ SLOT(openCatalogManager()),actionCollection(), "open_catalog_manager");
+
+ new KAction( i18n("Toggle Edit Mode"), 0, Key_Insert,this,SLOT(toggleEditMode()), actionCollection(), "toggle_insert_mode");
+
+ new KAction( i18n("&Word Count"), 0, m_view, SLOT(wordCount()), actionCollection(), "word_count");
+
+ // next, the settings menu
+ createStandardStatusBarAction();
+
+ KStdAction::configureToolbars(this,SLOT(optionsEditToolbars()),actionCollection());
+
+ KStdAction::keyBindings(guiFactory(),SLOT(configureShortcuts()),actionCollection());
+ KStdAction::preferences(this,SLOT(optionsPreferences()),actionCollection());
+
+ setStandardToolBarMenuEnabled ( true );
+
+ action = new KAction(i18n("&Stop Searching"), "stop",Key_Escape, m_view,
+ SLOT(stopSearch()),actionCollection(), "stop_search");
+ action->setEnabled(false);
+
+ new KAction(i18n("&Gettext Info"), 0, this,
+ SLOT(gettextHelp()), actionCollection(), "help_gettext");
+
+
+ // the bookmarks menu
+
+ action = KStdAction::addBookmark(this, SLOT(slotAddBookmark()),
+ actionCollection(), "add_bookmark");
+ action->setEnabled(false);
+ // this action is now connected to dummySlot(), and later reconnected
+ // to bmHandler after that object actually is created
+ new KAction(i18n("Clear Bookmarks"), 0, this, SLOT(dummySlot()),
+ actionCollection(), "clear_bookmarks");
+
+ setupDynamicActions();
+
+ createGUI(0);
+
+ QPopupMenu *popup = static_cast<QPopupMenu*>(factory()->container("settings",this));
+ popup->insertItem( i18n("&Views"), dockHideShowMenu(), -1, 0 );
+}
+
+
+void KBabelMW::setupStatusBar()
+{
+ statusBar()->insertItem(i18n("Current: 0"),ID_STATUS_CURRENT);
+ statusBar()->insertItem(i18n("Total: 0"),ID_STATUS_TOTAL);
+ statusBar()->insertItem(i18n("Fuzzy: 0"),ID_STATUS_FUZZY);
+ statusBar()->insertItem(i18n("Untranslated: 0"),ID_STATUS_UNTRANS);
+
+ if(KBabelSettings::ledInStatusbar())
+ {
+ QColor ledColor=KBabelSettings::ledColor();
+ QHBox* statusBox = new QHBox(statusBar(),"statusBox");
+ statusBox->setSpacing(2);
+ new QLabel(" "+i18n("Status: "),statusBox);
+ _fuzzyLed = new KLed(ledColor,KLed::Off,KLed::Sunken,KLed::Rectangular
+ ,statusBox);
+ _fuzzyLed->setFixedSize(15,12);
+ new QLabel(i18n("fuzzy")+" ",statusBox);
+ _untransLed = new KLed(ledColor,KLed::Off,KLed::Sunken,KLed::Rectangular
+ ,statusBox);
+ _untransLed->setFixedSize(15,12);
+ new QLabel(i18n("untranslated")+" ",statusBox);
+ _errorLed = new KLed(ledColor,KLed::Off,KLed::Sunken,KLed::Rectangular
+ ,statusBox);
+ _errorLed->setFixedSize(15,12);
+ new QLabel(i18n("faulty")+" ",statusBox);
+
+ statusBox->setFixedWidth(statusBox->sizeHint().width());
+ statusBar()->addWidget(statusBox);
+ }
+
+ statusBar()->insertItem(i18n("INS"),ID_STATUS_EDITMODE);
+
+ statusBar()->insertItem(i18n("RW"),ID_STATUS_READONLY);
+
+ statusBar()->insertItem(i18n("Line: %1 Col: %2").arg(1).arg(1)
+ ,ID_STATUS_CURSOR);
+
+ QHBox* progressBox = new QHBox(statusBar(),"progressBox");
+ progressBox->setSpacing(2);
+ _progressLabel = new KSqueezedTextLabel( "", progressBox );
+ _progressBar=new MyKProgress(progressBox,"progressbar");
+ _progressBar->hide();
+ progressBox->setStretchFactor(_progressBar,1);
+
+ statusBar()->addWidget(progressBox,1);
+ statusBar()->setMinimumHeight(progressBox->sizeHint().height());
+
+ QWhatsThis::add(statusBar(),
+ i18n("<qt><p><b>Statusbar</b></p>\n\
+<p>The statusbar displays some information about the opened file,\n\
+like the total number of entries and the number of fuzzy and untranslated\n\
+messages. Also the index and the status of the currently displayed entry is shown.</p></qt>"));
+
+}
+
+void KBabelMW::setupDynamicActions()
+{
+ // dynamic validation tools
+ QValueList<KDataToolInfo> tools = ToolAction::validationTools();
+
+ QPtrList<KAction> actions = ToolAction::dataToolActionList(
+ tools, m_view, SLOT(validateUsingTool( const KDataToolInfo &, const QString & )),
+ "validate", false, actionCollection() );
+
+ KActionMenu* m_menu = new KActionMenu(i18n("&Validation"), actionCollection(), "dynamic_validation_tools");
+
+ KAction* ac = new KAction(i18n("Perform &All Checks"), CTRL+Key_E , m_view,
+ SLOT(checkAll()),actionCollection(), "check_all");
+ ac->setEnabled(false);
+ m_menu->insert(ac);
+
+ m_menu->insert( new KActionSeparator() );
+
+ ac = new KAction(i18n("C&heck Syntax"), CTRL+Key_T , m_view,
+ SLOT(checkSyntax()),actionCollection(), "check_syntax");
+ ac->setEnabled(false);
+ m_menu->insert(ac);
+
+ for( ac = actions.first(); ac ; ac = actions.next() )
+ {
+ m_menu->insert(ac);
+ }
+
+ // dynamic modify tools
+
+ // query available tools
+ QValueList<KDataToolInfo> allTools = KDataToolInfo::query
+ ("CatalogItem", "application/x-kbabel-catalogitem", KGlobal::instance());
+
+ // skip read-only tools for single items
+ QValueList<KDataToolInfo> modifyTools;
+
+ QValueList<KDataToolInfo>::ConstIterator entry = allTools.begin();
+ for( ; entry != allTools.end(); ++entry )
+ {
+ if( !(*entry).isReadOnly() )
+ {
+ modifyTools.append( (*entry) );
+ }
+ }
+
+ // create corresponding actions
+ actions = ToolAction::dataToolActionList(
+ modifyTools, m_view, SLOT(modifyUsingTool( const KDataToolInfo &, const QString & )),
+ "validate", true, actionCollection() );
+
+ // skip validation actions
+ for( ac = actions.first(); ac ; ac = actions.next() )
+ {
+ m_menu->insert(ac);
+ }
+
+ // insert tools
+ m_menu = new KActionMenu(i18n("&Modify"), actionCollection(), "dynamic_modify_tools");
+ for( ac = actions.first(); ac ; ac = actions.next() )
+ {
+ m_menu->insert(ac);
+ }
+
+ // query available tools for whole catalog
+ allTools = KDataToolInfo::query
+ ("Catalog", "application/x-kbabel-catalog", KGlobal::instance());
+
+ // skip read-only tools
+ entry = allTools.begin();
+ for( ; entry != allTools.end(); ++entry )
+ {
+ if( !(*entry).isReadOnly() )
+ {
+ modifyTools.append( (*entry) );
+ }
+ }
+
+ // create corresponding actions
+ actions = ToolAction::dataToolActionList(
+ modifyTools, m_view, SLOT(modifyUsingTool( const KDataToolInfo &, const QString & )),
+ "validate", true, actionCollection() );
+
+ // skip validation actions
+ for( ac = actions.first(); ac ; ac = actions.next() )
+ {
+ m_menu->insert(ac);
+ }
+
+ // create corresponding actions
+ actions = ToolAction::dataToolActionList(
+ modifyTools, m_view, SLOT(modifyCatalogUsingTool( const KDataToolInfo &, const QString & )),
+ "validate", true, actionCollection() );
+
+ // insert tools
+ m_menu = new KActionMenu(i18n("&Modify"), actionCollection(), "dynamic_modify_tools");
+ for( ac = actions.first(); ac ; ac = actions.next() )
+ {
+ m_menu->insert(ac);
+ }
+}
+
+void KBabelMW::saveSettings()
+{
+ {
+ saveMainWindowSettings(_config, "View");
+ writeDockConfig (_config, "View");
+ }
+
+ {
+ a_recent->saveEntries(_config);
+ a_recentprojects->saveEntries(_config,"Project");
+ }
+
+ _config->sync();
+}
+
+void KBabelMW::restoreSettings()
+{
+ {
+ applyMainWindowSettings(_config, "View");
+ KConfigGroupSaver saver(_config,"View");
+
+ _config->setGroup("View");
+ m_view->restoreView(_config);
+
+ readDockConfig (_config, "View");
+ }
+
+ {
+ a_recent->loadEntries(_config);
+
+ a_recentprojects->loadEntries(_config, "Project");
+ }
+}
+
+
+
+void KBabelMW::saveProperties(KConfig *config)
+{
+ m_view->saveSession(config);
+}
+
+void KBabelMW::readProperties(KConfig *config)
+{
+ m_view->restoreSession(config);
+
+ // need to ensure that the windows is propertly setup also
+ // for new views-only
+ if(!m_view->currentURL().isEmpty())
+ {
+ KBCatalog* catalog=m_view->catalog();
+ enableDefaults(catalog->isReadOnly());
+ setNumberOfFuzzies(catalog->numberOfFuzzies());
+ setNumberOfUntranslated(catalog->numberOfUntranslated());
+ setNumberOfTotal(catalog->numberOfEntries());
+
+ enableUndo(catalog->isUndoAvailable());
+ enableUndo(catalog->isRedoAvailable());
+
+ m_view->emitEntryState();
+
+ changeCaption(catalog->currentURL().prettyURL() );
+ }
+}
+
+bool KBabelMW::queryClose()
+{
+ if(m_view->isSearching())
+ {
+ connect(m_view,SIGNAL(signalSearchActive(bool)),this,SLOT(quit()));
+ m_view->stopSearch();
+ return false;
+ }
+
+ if(m_view->catalog()->isActive())
+ {
+ // stop the activity and try again
+ m_view->catalog()->stop();
+ QTimer::singleShot(0, this, SLOT( close() ));
+ return false;
+ }
+
+ if(m_view->isModified())
+ {
+ switch(KMessageBox::warningYesNoCancel(this,
+ i18n("The document contains unsaved changes.\n\
+Do you want to save your changes or discard them?"),i18n("Warning"),
+ KStdGuiItem::save(),KStdGuiItem::discard()))
+ {
+ case KMessageBox::Yes:
+ {
+ return m_view->saveFile();
+ }
+ case KMessageBox::No:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool KBabelMW::queryExit()
+{
+ saveSettings();
+ _config->setGroup("View");
+ m_view->saveView(_config);
+
+ m_view->saveSettings();
+ return true;
+}
+
+void KBabelMW::quit()
+{
+ close();
+}
+
+
+void KBabelMW::dragEnterEvent(QDragEnterEvent *event)
+{
+ // accept uri drops only
+ event->accept(KURLDrag::canDecode(event));
+}
+
+void KBabelMW::dropEvent(QDropEvent *event)
+{
+ KURL::List uri;
+ // see if we can decode a URI.. if not, just ignore it
+ if (KURLDrag::decode(event, uri))
+ {
+ m_view->processUriDrop(uri,mapToGlobal(event->pos()));
+ }
+}
+
+void KBabelMW::wheelEvent(QWheelEvent *e)
+{
+ m_view->wheelEvent(e);
+}
+
+void KBabelMW::openRecent(const KURL& url)
+{
+ KBabelView *view = KBabelView::viewForURL(url,QString::null);
+ if(view)
+ {
+ KWin::activateWindow(view->topLevelWidget()->winId());
+ return;
+ }
+
+ m_view->open(url);
+}
+
+void KBabelMW::open(const KURL& url)
+{
+ open(url,QString::null,false);
+}
+
+void KBabelMW::open(const KURL& url, const QString package, bool newWindow)
+{
+ kdDebug(KBABEL) << "opening file with project:" << _project->filename() << endl;
+ kdDebug(KBABEL) << "URL:" << url.prettyURL() << endl;
+ KBabelView *view = KBabelView::viewForURL(url, _project->filename());
+ if(view)
+ {
+ kdDebug(KBABEL) << "there is a such view" << endl;
+ KWin::activateWindow(view->topLevelWidget()->winId());
+ return;
+ }
+
+ addToRecentFiles(url);
+
+ if(newWindow)
+ {
+ kdDebug(KBABEL) << "creating new window"<< endl;
+ fileNewWindow()->open(url, package,false);
+ }
+ else
+ {
+ m_view->open(url,package);
+ }
+}
+
+void KBabelMW::openTemplate(const KURL& openURL,const KURL& saveURL,const QString& package, bool newWindow)
+{
+ if(newWindow)
+ {
+ fileNewWindow()->openTemplate(openURL,saveURL,package,false);
+ }
+ else
+ {
+ m_view->openTemplate(openURL,saveURL);
+ m_view->catalog()->setPackage(package);
+ }
+}
+
+void KBabelMW::fileOpen()
+{
+ m_view->open();
+
+ KURL url=m_view->currentURL();
+ addToRecentFiles(url);
+}
+
+
+void KBabelMW::addToRecentFiles(KURL url)
+{
+ if( url.isValid() && ! url.isEmpty() )
+ a_recent->addURL(url);
+}
+
+void KBabelMW::fileSave()
+{
+ // do it asynchronously due to kdelibs bug
+ QTimer::singleShot( 0, this, SLOT( fileSave_internal() ));
+}
+
+void KBabelMW::fileSave_internal()
+{
+ // this slot is called whenever the File->Save menu is selected,
+ // the Save shortcut is pressed (usually CTRL+S) or the Save toolbar
+ // button is clicked
+
+ if(!m_view->isModified())
+ {
+ statusBar()->message(i18n("There are no changes to save."),2000);
+ }
+ else
+ {
+ // disable save
+ KAction* saveAction=(KAction*)actionCollection()->action( KStdAction::name( KStdAction::Save) );
+ saveAction->setEnabled(false);
+
+ m_view->saveFile();
+
+ KURL url=m_view->currentURL();
+
+ DCOPClient *client = kapp->dcopClient();
+ QByteArray data;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << ((url.directory(false)+url.fileName()).utf8()) ;
+ if( !client->send( "catalogmanager-*", "CatalogManagerIFace", "updatedFile(QCString)", data ))
+ kdDebug(KBABEL) << "Unable to send file update info via DCOP" << endl;
+
+ // reenable save action
+ saveAction->setEnabled(true);
+ }
+}
+
+void KBabelMW::fileSaveAs()
+{
+ m_view->saveFileAs();
+ KURL url=m_view->currentURL();
+
+ DCOPClient *client = kapp->dcopClient();
+ QByteArray data;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << ((url.directory(false)+url.fileName()).utf8()) ;
+ if( !client->send( "catalogmanager-*", "CatalogManagerIFace", "updatedFile(QCString)", data ))
+ kdDebug(KBABEL) << "Unable to send file update info via DCOP" << endl;
+}
+
+void KBabelMW::fileSaveSpecial()
+{
+ if( !m_view->saveFileSpecial() ) return;
+
+ KURL url=m_view->currentURL();
+
+ DCOPClient *client = kapp->dcopClient();
+ QByteArray data;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << ((url.directory(false)+url.fileName()).utf8()) ;
+ if( !client->send( "catalogmanager-*", "CatalogManagerIFace", "updatedFile(QCString)", data ))
+ kdDebug(KBABEL) << "Unable to send file update info via DCOP" << endl;
+}
+
+void KBabelMW::fileMail()
+{
+ if( m_view->isModified() ) fileSave();
+ mailer->sendOneFile( m_view->currentURL() );
+}
+
+void KBabelMW::fileNewView()
+{
+ KBabelMW* b=new KBabelMW(m_view->catalog(),_project->filename());
+ b->updateSettings();
+ b->initBookmarks(bmHandler->bookmarks());
+ b->show();
+}
+
+KBabelMW* KBabelMW::fileNewWindow()
+{
+ KBabelMW* b=new KBabelMW(_project->filename());
+ b->setSettings(m_view->catalog()->saveSettings(),m_view->catalog()->identitySettings());
+ b->show();
+
+ return b;
+}
+
+void KBabelMW::toggleEditMode()
+{
+ bool ovr=!m_view->isOverwriteMode();
+
+ m_view->setOverwriteMode(ovr);
+
+ if(ovr)
+ statusBar()->changeItem(i18n("OVR"),ID_STATUS_EDITMODE);
+ else
+ statusBar()->changeItem(i18n("INS"),ID_STATUS_EDITMODE);
+
+}
+
+void KBabelMW::optionsShowStatusbar(bool on)
+{
+ if(on)
+ {
+ statusBar()->show();
+ }
+ else
+ {
+ statusBar()->hide();
+ }
+}
+
+void KBabelMW::optionsEditToolbars()
+{
+ saveMainWindowSettings( KGlobal::config(), "View" );
+ KEditToolbar dlg(actionCollection());
+ connect(&dlg, SIGNAL(newToolbarConfig()), this, SLOT(newToolbarConfig()));
+ dlg.exec();
+}
+
+void KBabelMW::newToolbarConfig()
+{
+ createGUI(0);
+ applyMainWindowSettings( KGlobal::config(), "View" );
+}
+
+void KBabelMW::optionsPreferences()
+{
+ if(!_prefDialog)
+ {
+ _prefDialog = new KBabelPreferences(m_view->dictionaries());
+ prefDialogs.append(_prefDialog);
+
+ connect(_prefDialog,SIGNAL(settingsChanged())
+ ,m_view,SLOT(updateSettings()));
+ }
+
+ int prefHeight=_prefDialog->height();
+ int prefWidth=_prefDialog->width();
+ int width=this->width();
+ int height=this->height();
+
+ int x=width/2-prefWidth/2;
+ int y=height/2-prefHeight/2;
+
+ _prefDialog->move(mapToGlobal(QPoint(x,y)));
+
+ if(!_prefDialog->isVisible())
+ {
+ _prefDialog->show();
+ }
+
+ _prefDialog->raise();
+ KWin::activateWindow(_prefDialog->winId());
+}
+
+void KBabelMW::setLedColor(const QColor& color)
+{
+ if(_fuzzyLed)
+ {
+ _fuzzyLed->setColor(color);
+ }
+ if(_untransLed)
+ {
+ _untransLed->setColor(color);
+ }
+ if(_errorLed)
+ {
+ _errorLed->setColor(color);
+ }
+}
+
+void KBabelMW::openCatalogManager()
+{
+ QCString service;
+ QString result;
+
+ DCOPClient * client = kapp->dcopClient();
+
+ // find out, if there is a running catalog manager
+ QCStringList apps = client->registeredApplications();
+ for( QCStringList::Iterator it = apps.begin() ; it != apps.end() ; ++it )
+ {
+ QString clientID = *it;
+ if( clientID.startsWith("catalogmanager") )
+ {
+ service = *it;
+ break;
+ }
+ }
+
+ // if there is no running catalog manager, start one
+ if( service.isEmpty() )
+ {
+ QString prog = "catalogmanager";
+ QString url = "";
+ if( kapp->startServiceByDesktopName(prog,url, &result,&service))
+ {
+ KMessageBox::error(this, i18n("Unable to use KLauncher to start "
+ "Catalog Manager. You should check the installation of KDE.\n"
+ "Please start Catalog Manager manually."));
+ return;
+ }
+ }
+
+ // set preferred window
+ QByteArray data;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << (this->winId()) ;
+ if( !client->send( service, "CatalogManagerIFace", "setPreferredWindow( WId )", data )) kdDebug(KBABEL) << "Unable to set preferred window via DCOP" << endl;
+}
+
+
+
+void KBabelMW::firstEntryDisplayed(bool firstEntry, bool firstForm)
+{
+ KAction* firstAction=(KAction*)actionCollection()->action(KStdAction::stdName(KStdAction::FirstPage));
+ KAction* prevAction=(KAction*)actionCollection()->action("go_prev_entry");
+
+ firstAction->setEnabled(!firstEntry);
+ prevAction->setEnabled(!(firstEntry && firstForm));
+
+}
+
+void KBabelMW::lastEntryDisplayed(bool lastEntry, bool lastForm)
+{
+ KAction* lastAction=(KAction*)actionCollection()->action(KStdAction::stdName(KStdAction::LastPage));
+ KAction* nextAction=(KAction*)actionCollection()->action("go_next_entry");
+
+ lastAction->setEnabled(!lastEntry);
+ nextAction->setEnabled(!(lastEntry && lastForm));
+}
+
+void KBabelMW::fuzzyDisplayed(bool flag)
+{
+ if(!_fuzzyLed)
+ return;
+
+ if(flag)
+ {
+ if(_fuzzyLed->state()==KLed::Off)
+ {
+ _fuzzyLed->on();
+ }
+ }
+ else
+ {
+ if(_fuzzyLed->state()==KLed::On)
+ _fuzzyLed->off();
+ }
+}
+
+void KBabelMW::untranslatedDisplayed(bool flag)
+{
+ if(!_untransLed)
+ return;
+
+ // do not allow fuzzy toggle for untranslated
+ KAction *action=actionCollection()->action("edit_toggle_fuzzy");
+ if(action)
+ action->setEnabled(!flag);
+
+
+ if(flag)
+ {
+ if(_untransLed->state()==KLed::Off)
+ _untransLed->on();
+ }
+ else
+ {
+ if(_untransLed->state()==KLed::On)
+ _untransLed->off();
+ }
+}
+
+
+void KBabelMW::faultyDisplayed(bool flag)
+{
+ if(!_errorLed)
+ return;
+
+ if(flag)
+ {
+ if(_errorLed->state()==KLed::Off)
+ _errorLed->on();
+ }
+ else
+ {
+ if(_errorLed->state()==KLed::On)
+ _errorLed->off();
+ }
+}
+
+
+void KBabelMW::displayedEntryChanged(const KBabel::DocPosition& pos)
+{
+ statusBar()->changeItem(i18n("Current: %1").arg(pos.item+1),ID_STATUS_CURRENT);
+ _currentIndex = pos.item;
+}
+
+void KBabelMW::setNumberOfTotal(uint number)
+{
+ statusBar()->changeItem(i18n("Total: %1").arg(number),ID_STATUS_TOTAL);
+}
+
+void KBabelMW::setNumberOfFuzzies(uint number)
+{
+ statusBar()->changeItem(i18n("Fuzzy: %1").arg(number),ID_STATUS_FUZZY);
+}
+
+void KBabelMW::setNumberOfUntranslated(uint number)
+{
+ statusBar()->changeItem(i18n("Untranslated: %1").arg(number),ID_STATUS_UNTRANS);
+}
+
+void KBabelMW::hasFuzzyAfterwards(bool flag)
+{
+ a_nextFuzzy->setEnabled(flag);
+
+ // check if there is a fuzzy or untranslated afterwards
+ if( flag || a_nextUntrans->isEnabled() )
+ {
+ a_nextFoU->setEnabled(true);
+ }
+ else
+ {
+ a_nextFoU->setEnabled(false);
+ }
+
+}
+
+void KBabelMW::hasFuzzyInFront(bool flag)
+{
+ a_prevFuzzy->setEnabled(flag);
+
+ // check if there is a fuzzy or untranslated in front
+ if( flag || a_prevUntrans->isEnabled() )
+ {
+ a_prevFoU->setEnabled(true);
+ }
+ else
+ {
+ a_prevFoU->setEnabled(false);
+ }
+}
+
+void KBabelMW::hasUntranslatedAfterwards(bool flag)
+{
+ a_nextUntrans->setEnabled(flag);
+
+ // check if there is a fuzzy or untranslated afterwards
+ if( flag || a_nextFuzzy->isEnabled() )
+ {
+ a_nextFoU->setEnabled(true);
+ }
+ else
+ {
+ a_nextFoU->setEnabled(false);
+ }
+}
+
+void KBabelMW::hasUntranslatedInFront(bool flag)
+{
+ a_prevUntrans->setEnabled(flag);
+
+ // check if there is a fuzzy or translated in front
+ if( flag || a_prevFuzzy->isEnabled() )
+ {
+ a_prevFoU->setEnabled(true);
+ }
+ else
+ {
+ a_prevFoU->setEnabled(false);
+ }
+}
+
+
+
+void KBabelMW::hasErrorAfterwards(bool flag)
+{
+ KAction* action=actionCollection()->action("go_next_error");
+ action->setEnabled(flag);
+}
+
+void KBabelMW::hasErrorInFront(bool flag)
+{
+ KAction* action=actionCollection()->action("go_prev_error");
+ action->setEnabled(flag);
+}
+
+
+void KBabelMW::enableBackHistory(bool on)
+{
+ KAction* action=actionCollection()->action("go_back_history");
+ action->setEnabled(on);
+}
+
+void KBabelMW::enableForwardHistory(bool on)
+{
+ KAction* action=actionCollection()->action("go_forward_history");
+ action->setEnabled(on);
+}
+
+
+void KBabelMW::prepareProgressBar(QString msg,int max)
+{
+ if(_statusbarTimer->isActive())
+ _statusbarTimer->stop();
+
+ _progressBar->show();
+ _progressLabel->setText(" "+msg);
+ _progressBar->setTotalSteps(max);
+ _progressBar->setProgress(0);
+
+}
+
+void KBabelMW::clearProgressBar()
+{
+ _progressBar->setProgress(0);
+ _progressBar->hide();
+ _progressLabel->setText(" ");
+}
+
+
+void KBabelMW::changeStatusbar(const QString& text)
+{
+ // display the text on the statusbar
+ _progressLabel->setText(" "+text);
+
+ if(_statusbarTimer->isActive())
+ _statusbarTimer->stop();
+
+ _statusbarTimer->start(5000,true);
+}
+
+void KBabelMW::clearStatusbarMsg()
+{
+ _progressLabel->setText("");
+}
+
+void KBabelMW::changeCaption(const QString& text)
+{
+ // display the text on the caption
+ setCaption(text + ( _project->filename () != KBabel::ProjectManager::defaultProjectName() ?
+ " (" + _project->name() + ")" : "" /* KDE 3.4: i18n("(No project)")*/ )
+ ,m_view->isModified());
+}
+
+
+void KBabelMW::showModified(bool on)
+{
+ // display the text on the caption
+ setCaption(m_view->catalog()->package(),on);
+
+ KAction *action=actionCollection()->action(
+ KStdAction::stdName(KStdAction::Save));
+ action->setEnabled(on);
+
+ action=actionCollection()->action(KStdAction::stdName(KStdAction::Revert));
+ action->setEnabled(on);
+}
+
+
+void KBabelMW::enableDefaults(bool readOnly)
+{
+ stateChanged( "readonly", readOnly ? StateNoReverse : StateReverse );
+ stateChanged( "fileopened", StateNoReverse );
+
+ if(readOnly)
+ statusBar()->changeItem(i18n("RO"),ID_STATUS_READONLY);
+ else
+ statusBar()->changeItem(i18n("RW"),ID_STATUS_READONLY);
+}
+
+void KBabelMW::enableUndo(bool on)
+{
+ KAction* action=actionCollection()->action(KStdAction::stdName(KStdAction::Undo));
+ action->setEnabled(on);
+}
+
+void KBabelMW::enableRedo(bool on)
+{
+ KAction* action=actionCollection()->action(KStdAction::stdName(KStdAction::Redo));
+ action->setEnabled(on);
+}
+
+void KBabelMW::enableStop(bool flag)
+{
+ KAction* action=(KAction*)actionCollection()->action("stop_search");
+ action->setEnabled(flag);
+}
+
+void KBabelMW::gettextHelp()
+{
+ QString error;
+ KApplication::startServiceByDesktopName("khelpcenter",
+ QString("info:/gettext"), &error);
+
+ if(!error.isEmpty())
+ {
+ KMessageBox::sorry(this,i18n("An error occurred while "
+ "trying to open the gettext info page:\n%1").arg(error));
+ }
+}
+
+void KBabelMW::buildDictMenus()
+{
+ QPtrList<ModuleInfo> dictList = m_view->dictionaries();
+ dictList.setAutoDelete(true);
+
+ dictMenu->clear();
+ selectionDictMenu->clear();
+ configDictMenu->clear();
+ editDictMenu->clear();
+ aboutDictMenu->clear();
+
+ ModuleInfo *info;
+ for(info = dictList.first(); info !=0; info = dictList.next())
+ {
+ QString accel="Ctrl+Alt+%1";
+ dictMenu->add(info->name,info->id, accel);
+
+ accel=QString("Ctrl+%1");
+ selectionDictMenu->add(info->name,info->id, accel);
+
+ configDictMenu->add(info->name,info->id);
+ aboutDictMenu->add(info->name,info->id);
+
+ if(info->editable)
+ {
+ dictMenu->add(info->name,info->id);
+ }
+ }
+}
+
+void KBabelMW::updateCursorPosition(int line, int col)
+{
+ statusBar()->changeItem(i18n("Line: %1 Col: %2").arg(line+1).arg(col+1)
+ ,ID_STATUS_CURSOR);
+}
+
+
+KBabelMW *KBabelMW::winForURL(const KURL& url, QString project)
+{
+ KBabelMW *kb=0;
+
+ KBabelView *v = KBabelView::viewForURL(url,project);
+ if(v)
+ {
+ QObject *p = v->parent();
+ while(p && !p->inherits("KBabelMW"))
+ {
+ p = p->parent();
+ }
+
+ if(p)
+ kb = static_cast<KBabelMW*>(p);
+ }
+
+ return kb;
+}
+
+KBabelMW *KBabelMW::emptyWin(QString project)
+{
+ KBabelMW *kb=0;
+
+ KBabelView *v = KBabelView::emptyView(project);
+ if(v)
+ {
+ QObject *p = v->parent();
+ while(p && !p->inherits("KBabelMW"))
+ {
+ p = p->parent();
+ }
+
+ if(p)
+ kb = static_cast<KBabelMW*>(p);
+ }
+
+ return kb;
+}
+
+void KBabelMW::spellcheckMoreFiles(QStringList filelist)
+{
+ if( filelist.isEmpty() ) return;
+ _toSpellcheck = filelist;
+ connect( m_view, SIGNAL( signalSpellcheckDone(int) ), this, SLOT( spellcheckDone(int)));
+ spellcheckDone( KS_IGNORE ); // use something else than KS_STOP
+}
+
+void KBabelMW::spellcheckDone( int result)
+{
+ if( _toSpellcheck.isEmpty() || result == KS_STOP)
+ {
+ disconnect( m_view, SIGNAL( signalSpellcheckDone(int)), this, SLOT(spellcheckDone( int)));
+ KMessageBox::information( this, i18n("MessageBox text", "Spellchecking of multiple files is finished."),
+ i18n("MessageBox caption", "Spellcheck Done"));
+ }
+ else
+ {
+ QString file = _toSpellcheck.first();
+ _toSpellcheck.pop_front();
+ if( m_view->isModified() ) fileSave();
+ open(KURL( file ), QString::null, false);
+ kdDebug(KBABEL) << "Starting another spellcheck" << endl;
+ QTimer::singleShot( 1, m_view, SLOT(spellcheckAllMulti()));
+ }
+}
+
+void KBabelMW::initBookmarks(QPtrList<KBabelBookmark> list)
+{
+ bmHandler->setBookmarks(list);
+}
+
+void KBabelMW::slotAddBookmark()
+{
+ bmHandler->addBookmark(_currentIndex+1, m_view->catalog()->msgid(_currentIndex).first());
+}
+
+void KBabelMW::slotOpenBookmark(int index)
+{
+ DocPosition pos;
+ pos.item=index-1;
+ pos.form=0;
+ m_view->gotoEntry(pos);
+}
+
+void KBabelMW::projectNew()
+{
+ KBabel::Project::Ptr p = KBabel::ProjectWizard::newProject();
+ if( p )
+ {
+ _project = p;
+ m_view->useProject(p);
+ changeProjectActions(p->filename());
+ }
+}
+
+void KBabelMW::projectOpen()
+{
+ QString oldproject = m_view->project();
+ if( oldproject == KBabel::ProjectManager::defaultProjectName() )
+ {
+ oldproject = QString();
+ }
+ const QString file = KFileDialog::getOpenFileName(oldproject, QString::null, this);
+ if (file.isEmpty())
+ {
+ return;
+ }
+
+ projectOpen (file);
+}
+
+void KBabelMW::projectOpenRecent(const KURL& url)
+{
+ projectOpen (url.path());
+ KBabel::Project::Ptr p = KBabel::ProjectManager::open(url.path());
+ if( p )
+ {
+ _project = p;
+ m_view->useProject(p);
+ changeProjectActions(url.path());
+ }
+}
+
+void KBabelMW::projectOpen(const QString& file)
+{
+ QString oldproject = m_view->project();
+ if( oldproject == KBabel::ProjectManager::defaultProjectName() )
+ {
+ oldproject = "";
+ }
+ if (file.isEmpty())
+ {
+ return;
+ }
+ KBabel::Project::Ptr p = KBabel::ProjectManager::open(file);
+ if( p )
+ {
+ _project = p;
+ m_view->useProject(p);
+ changeProjectActions(file);
+ }
+ else
+ {
+ KMessageBox::error( this, i18n("Cannot open project file\n%1").arg(file)
+ , i18n("Project File Error"));
+ _project = ProjectManager::open(KBabel::ProjectManager::defaultProjectName());
+ m_view->useProject(_project);
+ changeProjectActions(KBabel::ProjectManager::defaultProjectName());
+ }
+}
+
+void KBabelMW::projectClose()
+{
+ QString defaultProject = KBabel::ProjectManager::defaultProjectName();
+ m_view->useProject( KBabel::ProjectManager::open(defaultProject) );
+ _project = ProjectManager::open(defaultProject);
+ changeProjectActions(defaultProject);
+}
+
+void KBabelMW::changeProjectActions(const QString& project)
+{
+ bool def = (project == KBabel::ProjectManager::defaultProjectName());
+
+ KAction* saveAction=(KAction*)actionCollection()->action( "project_close" );
+ saveAction->setEnabled( ! def );
+
+ if (!def)
+ {
+ addToRecentProjects(project);
+ }
+
+ // if there is a project dialog, delete it (we have a different project now
+ if (_projectDialog)
+ {
+ delete _projectDialog;
+ _projectDialog = NULL;
+ }
+}
+
+void KBabelMW::projectConfigure()
+{
+ if(!_projectDialog)
+ {
+ _projectDialog = new ProjectDialog(_project);
+ connect (_projectDialog, SIGNAL (settingsChanged())
+ , m_view, SLOT (updateProjectSettings()));
+ }
+
+ int prefHeight=_projectDialog->height();
+ int prefWidth=_projectDialog->width();
+ int width=this->width();
+ int height=this->height();
+
+ int x=width/2-prefWidth/2;
+ int y=height/2-prefHeight/2;
+
+ _projectDialog->move(mapToGlobal(QPoint(x,y)));
+
+ if(!_projectDialog->isVisible())
+ {
+ _projectDialog->show();
+ }
+
+ _projectDialog->raise();
+ KWin::activateWindow(_projectDialog->winId());
+}
+
+void KBabelMW::addToRecentProjects(KURL url)
+{
+ if( url.isValid() && ! url.isEmpty() )
+ a_recentprojects->addURL(url);
+}
+
+
+#include "kbabel.moc"
diff --git a/kbabel/kbabel/kbabel.desktop b/kbabel/kbabel/kbabel.desktop
new file mode 100644
index 00000000..950e0dbd
--- /dev/null
+++ b/kbabel/kbabel/kbabel.desktop
@@ -0,0 +1,83 @@
+[Desktop Entry]
+Name=KBabel
+Name[af]=Kbabel
+Name[eo]=Babelo-tradukilo
+Name[hi]=के-बेबल
+Name[ko]=K바벨
+Name[ne]=केबà¥à¤¯à¤¾à¤¬à¤²
+Name[pa]=ਕੇਬਬੇਲ
+Name[pt_BR]=Editor de POTFiles
+Name[sv]=Kbabel
+Name[ta]=Kபாபேலà¯
+Exec=kbabel %i %m -caption "%c" %U
+Icon=kbabel
+Type=Application
+DocPath=kbabel/index.html
+MimeType=application/x-gettext;
+GenericName=Translation Tool
+GenericName[af]=Vertaling Program
+GenericName[ar]=أداة الترجمة
+GenericName[bg]=ИнÑтрумент за превод
+GenericName[br]=Ostilh troidigezh
+GenericName[bs]=Alat za prevođenje
+GenericName[ca]=Eina de traducció
+GenericName[cs]=Překladatelský nástroj
+GenericName[cy]=Erfyn Cyfieithu
+GenericName[da]=Oversættelsesværktøj
+GenericName[de]=Ãœbersetzungsprogramm
+GenericName[el]=ΕÏγαλείο μετάφÏασης
+GenericName[eo]=Tradukilo por Qt-programoj
+GenericName[es]=Herramienta de traducción
+GenericName[et]=Tõlkimise rakendus
+GenericName[eu]=Itzulpen tresna
+GenericName[fa]=ابزار ترجمه
+GenericName[fi]=Käännöstyökalu
+GenericName[fo]=Umsetingaramboð
+GenericName[fr]=Outil de traduction
+GenericName[ga]=Uirlis Aistriúcháin
+GenericName[gl]=Ferramenta de tradución
+GenericName[he]=כלי תרגו×
+GenericName[hi]=अनà¥à¤µà¤¾à¤¦ औज़ार
+GenericName[hr]=Uslužni program za prevođenje
+GenericName[hu]=Fordítássegítő eszköz
+GenericName[is]=Þýðingaforrit
+GenericName[it]=Strumento di traduzione
+GenericName[ja]=翻訳ツール
+GenericName[ka]=თáƒáƒ áƒ’მნის ხელსáƒáƒ¬áƒ§áƒ
+GenericName[kk]=Ðудару құралы
+GenericName[lt]=Vertimo įrankis
+GenericName[lv]=Tulkošanas Rīks
+GenericName[ms]=Perkakasan Penterjemahan
+GenericName[mt]=Għodda tat-traduzzjoni
+GenericName[nb]=Oversettingsverktøy
+GenericName[nds]=Översettenwarktüüch
+GenericName[ne]=अनà¥à¤¬à¤¾à¤¦ उपकरण
+GenericName[nl]=Vertaalprogramma
+GenericName[nn]=Omsetjingsverktøy
+GenericName[nso]=Sebereka sa Thlathollo
+GenericName[pa]=ਅਨà©à¨µà¨¾à¨¦ ਸੰਦ
+GenericName[pl]=Narzędzie dla tłumaczy
+GenericName[pt]=Ferramenta de Tradução
+GenericName[pt_BR]=Ferramenta de Tradução
+GenericName[ro]=Utilitar de traducere
+GenericName[ru]=Ð›Ð¾ÐºÐ°Ð»Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ð¹
+GenericName[sk]=Prekladací nástroj
+GenericName[sl]=Orodje za prevajanje
+GenericName[sr]=Ðлат за превођење
+GenericName[sr@Latn]=Alat za prevođenje
+GenericName[sv]=Översättningsverktyg
+GenericName[ta]=மொழிபெயரà¯à®ªà¯à®ªà¯ கரà¯à®µà®¿
+GenericName[tg]=Утилитаи маҳалликунонии гузориш
+GenericName[th]=เครื่องมือà¹à¸›à¸¥à¸ à¸²à¸©à¸²
+GenericName[tr]=Çeviri Aracı
+GenericName[uk]=ЗаÑіб Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐºÐ»Ð°Ð´Ñ–Ð²
+GenericName[ven]=Zwishumiswa zwau Dologa
+GenericName[vi]=Công cụ dịch
+GenericName[xh]=Isixhobo Soguqulelo lomsebenzi kolunye ulwimi
+GenericName[zh_CN]=翻译工具
+GenericName[zh_TW]=翻譯工具
+GenericName[zu]=Ithuluzi Lokuguqulela
+Terminal=false
+X-KDE-StartupNotify=true
+X-DCOP-ServiceType=Unique
+Categories=Qt;KDE;Development;Translation;
diff --git a/kbabel/kbabel/kbabel.h b/kbabel/kbabel/kbabel.h
new file mode 100644
index 00000000..4ff184c1
--- /dev/null
+++ b/kbabel/kbabel/kbabel.h
@@ -0,0 +1,325 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2002-2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef KBABEL_H
+#define KBABEL_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <kapplication.h>
+#include <kdeversion.h>
+#include <kdockwidget.h>
+#include <qstringlist.h>
+#include <qptrlist.h>
+#include <kmdimainfrm.h>
+
+#include "kbabelview.h"
+#include "kbproject.h"
+
+class KAction;
+class KRecentFilesAction;
+class KLed;
+class KProgress;
+class QHBox;
+class QLabel;
+class QTimer;
+
+class KBCatalog;
+class KBabelPreferences;
+class DictionaryMenu;
+class KBabelBookmark;
+class KBabelBookmarkHandler;
+class CommentView;
+class CharacterSelectorView;
+
+namespace KBabel
+{
+ class KBabelMailer;
+ class ProjectDialog;
+}
+
+/**
+ * This class serves as the main window for KBabel. It handles the
+ * menus, toolbars, and status bars.
+ *
+ * @short Main window class
+ * @author Matthias Kiefer <matthias.kiefer@gmx.de>
+ * @version 0.1
+ */
+class KBabelMW : public KDockMainWindow
+{
+ Q_OBJECT
+public:
+ /**
+ * Default Constructor
+ */
+ KBabelMW(QString projectFile = QString());
+
+ /** use this contructor, if you just want to create a new view of an existing catalog*/
+ KBabelMW(KBCatalog* catalog, QString projectFile = QString());
+
+ /**
+ * Default Destructor
+ */
+ virtual ~KBabelMW();
+
+ QString project() const { return _project->filename(); }
+
+ void open(const KURL& url, const QString package, bool newWindow);
+ void openTemplate(const KURL& openURL,const KURL& saveURL,const QString& package, bool newWindow=false);
+ void projectOpen(const QString& filename);
+
+ void spellcheckMoreFiles( QStringList filelist);
+
+ void setSettings(KBabel::SaveSettings,KBabel::IdentitySettings);
+ void updateSettings();
+
+ /**
+ * @return A pointer to a KBabel, that has opened file URL or 0 if no
+ * KBabel was found
+ */
+ static KBabelMW *winForURL(const KURL& url, QString projectFile = QString::null);
+
+ /**
+ * @return A pointer to a KBabel, that has opened no file URL or 0 if no
+ * KBabel was found
+ */
+ static KBabelMW *emptyWin(QString projectFile = QString::null);
+
+public slots:
+ void toggleEditMode();
+
+protected:
+ /**
+ * Overridden virtuals for Qt drag 'n drop (XDND)
+ */
+ virtual void dragEnterEvent(QDragEnterEvent *event);
+ virtual void dropEvent(QDropEvent *event);
+
+ /**
+ * Overrriden virtual for wheel event handling to forward to KBabelView
+ */
+ virtual void wheelEvent(QWheelEvent *e);
+
+ /**
+ * This function is called when it is time for the app to save its
+ * properties for session management purposes.
+ */
+ virtual void saveProperties(KConfig *);
+
+ /**
+ * This function is called when this app is restored. The KConfig
+ * object points to the session management config file that was saved
+ * with @ref saveProperties
+ */
+ virtual void readProperties(KConfig *);
+
+ virtual bool queryExit();
+ virtual bool queryClose();
+
+private slots:
+ void quit();
+
+ void open(const KURL& url);
+ void openRecent(const KURL& url);
+ void fileOpen();
+ void fileSave();
+ void fileSave_internal();
+ void fileSaveAs();
+ void fileSaveSpecial();
+ void fileMail();
+ void fileNewView();
+ KBabelMW* fileNewWindow();
+
+ void projectNew();
+ void projectOpen();
+ void projectClose();
+ void projectConfigure();
+ void projectOpenRecent(const KURL& url);
+
+ void addToRecentFiles(KURL url);
+ void addToRecentProjects(KURL url);
+
+ void optionsShowStatusbar(bool);
+ void optionsEditToolbars();
+ void newToolbarConfig();
+ void optionsPreferences();
+
+ /** opens the gettext info page */
+ void gettextHelp();
+
+ void firstEntryDisplayed(bool firstEntry, bool firstForm);
+ void lastEntryDisplayed(bool lastEntry, bool lastForm);
+ void fuzzyDisplayed(bool);
+ void untranslatedDisplayed(bool);
+ void faultyDisplayed(bool);
+ void displayedEntryChanged(const KBabel::DocPosition& pos);
+ void setNumberOfTotal(uint number);
+ void setNumberOfFuzzies(uint number);
+ void setNumberOfUntranslated(uint number);
+ void hasFuzzyAfterwards(bool);
+ void hasFuzzyInFront(bool);
+ void hasUntranslatedAfterwards(bool);
+ void hasUntranslatedInFront(bool);
+ void hasErrorAfterwards(bool);
+ void hasErrorInFront(bool);
+ void updateCursorPosition(int line, int col);
+
+ void enableBackHistory(bool);
+ void enableForwardHistory(bool);
+
+ void enableUndo(bool);
+ void enableRedo(bool);
+ void enableStop(bool);
+
+ void openCatalogManager();
+
+ /**
+ * prepare the window and the progressbar for showing
+ * activity. message is displayed left to the progressbar
+ * and max is the maximum number for the progressbar
+ */
+ void prepareProgressBar(QString message,int max);
+ /**
+ * resets the progressBar and enables the window
+ */
+ void clearProgressBar();
+
+ void changeStatusbar(const QString& text);
+ void clearStatusbarMsg();
+ void changeCaption(const QString& text);
+ void showModified(bool);
+
+ /**
+ * enables menu- and toolbar items that are always enabled when a cat is opened
+ */
+ void enableDefaults(bool readOnly);
+
+ void setLedColor(const QColor& color);
+
+
+ void buildDictMenus();
+
+ /**
+ * used when creating standard toggle actions, because I prefer
+ * using signal toggled(bool)
+ */
+ void dummySlot(){}
+
+ void spellcheckDone( int result);
+
+ /**
+ * Create a new bookmark for the current msgid and add it to the list.
+ */
+ void slotAddBookmark();
+ /**
+ * Open the bookmark whose entry was just clicked in the menu.
+ */
+ void slotOpenBookmark(int index);
+
+private:
+ void init(KBCatalog* catalog);
+ void setupActions();
+ void setupDynamicActions();
+ void changeProjectActions(const QString& project);
+ void setupStatusBar();
+ void saveSettings();
+ void restoreSettings();
+ /**
+ * Init a new view of the current window with this window's bookmarks.
+ *
+ * @param list the list of bookmarks.
+ */
+ void initBookmarks(QPtrList<KBabelBookmark> list);
+
+private:
+ KBabelView *m_view;
+ CharacterSelectorView * const m_charselectorview;
+ CommentView * m_commentview;
+
+ int _currentIndex;
+
+ KProgress* _progressBar;
+ QLabel* _progressLabel;
+ KLed* _fuzzyLed;
+ KLed* _untransLed;
+ KLed* _errorLed;
+
+ QTimer *_statusbarTimer;
+
+ KBabelPreferences* _prefDialog;
+
+ QStringList _toSpellcheck;
+
+ /**
+ * used for updating preferences, that are common in
+ * the whole application
+ */
+ static QPtrList<KBabelPreferences> prefDialogs;
+
+
+ // frequently used actions
+ KAction* a_unsetFuzzy;
+ KAction* a_prevFoU;
+ KAction* a_nextFoU;
+ KAction* a_prevFuzzy;
+ KAction* a_nextFuzzy;
+ KAction* a_prevUntrans;
+ KAction* a_nextUntrans;
+
+ KRecentFilesAction* a_recent;
+ KRecentFilesAction* a_recentprojects;
+
+ DictionaryMenu *dictMenu;
+ DictionaryMenu *selectionDictMenu;
+ DictionaryMenu *configDictMenu;
+ DictionaryMenu *editDictMenu;
+ DictionaryMenu *aboutDictMenu;
+
+ friend class KBabelInterface;
+
+ // project file
+ KBabel::Project::Ptr _project;
+ KSharedConfig::Ptr _config;
+ KBabel::ProjectDialog* _projectDialog;
+
+ QMap<QString,QString> _toolsShortcuts;
+
+ KBabel::KBabelMailer* mailer;
+ KBabelBookmarkHandler* bmHandler;
+};
+
+#endif // KBABEL_H
diff --git a/kbabel/kbabel/kbabel.kcfg b/kbabel/kbabel/kbabel.kcfg
new file mode 100644
index 00000000..0da6949c
--- /dev/null
+++ b/kbabel/kbabel/kbabel.kcfg
@@ -0,0 +1,304 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <group name="Editor">
+ <entry name="AccelColor" type="Color">
+ <label>
+ </label>
+ <default>128,0,128</default>
+ </entry>
+ <entry name="AutoCheckColorError" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="AutoCheckTools" type="StringList">
+ <label>
+ </label>
+ <default></default>
+ </entry>
+ <entry name="AutoDiff" type="Bool">
+ <label>
+ </label>
+ <default>false</default>
+ </entry>
+ <entry name="AutoUnsetFuzzy" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="BackgroundColor" type="Color">
+ <label>
+ </label>
+ <default>255,255,192</default>
+ </entry>
+ <entry name="BeepOnError" type="Bool">
+ <label>
+ </label>
+ <default>false</default>
+ </entry>
+ <entry name="CformatColor" type="Color">
+ <label>
+ </label>
+ <default>0,0,255</default>
+ </entry>
+ <entry name="CleverEditing" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="DiffAddColor" type="Color">
+ <label>
+ </label>
+ <default>192,192,255</default>
+ </entry>
+ <entry name="DiffAddUnderline" type="Enum">
+ <label>
+ </label>
+ <choices>
+ <choice name="Highlighted"/>
+ <choice name="Underlined"/>
+ </choices>
+ <default>Underlined</default>
+ </entry>
+ <entry name="DiffDelColor" type="Color">
+ <label>
+ </label>
+ <default>255,128,128</default>
+ </entry>
+ <entry name="DiffDelStrikeOut" type="Enum">
+ <label>
+ </label>
+ <choices>
+ <choice name="Highlighted"/>
+ <choice name="StrokedOut"/>
+ </choices>
+ <default>StrokedOut</default>
+ </entry>
+ <entry name="EnableQuotes" type="Bool">
+ <label>
+ </label>
+ <default>false</default>
+ </entry>
+ <entry name="ErrorColor" type="Color">
+ <label>
+ </label>
+ <default>255,0,0</default>
+ </entry>
+ <entry name="HighlightBackground" type="Bool">
+ <label>
+ </label>
+ <default>false</default>
+ </entry>
+ <entry name="HighlightSyntax" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="LedColor" type="Color">
+ <label>
+ </label>
+ <default>255,0,0</default>
+ </entry>
+ <entry name="LedInStatusbar" type="Bool">
+ <label>
+ </label>
+ <default>false</default>
+ </entry>
+ <entry name="MsgFont" type="Font">
+ <label>Font for Messages</label>
+ <default code="true">KGlobalSettings::generalFont()</default>
+ </entry>
+ <entry name="OnFlySpellCheck" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="SpellcheckErrorColor" type="Color">
+ <label>
+ </label>
+ <default>255,128,0</default>
+ </entry>
+ <entry name="QuotedColor" type="Color">
+ <label>
+ </label>
+ <default>0,128,0</default>
+ </entry>
+ <entry name="TagColor" type="Color">
+ <label>
+ </label>
+ <default>0,0,128</default>
+ </entry>
+ <entry name="WhitespacePoints" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ </group>
+ <group name="FindDialog">
+ <entry name="Backwards" type="Bool">
+ <label>
+ </label>
+ <default>false</default>
+ </entry>
+ <entry name="CaseSensitive" type="Bool">
+ <label>
+ </label>
+ <default>false</default>
+ </entry>
+ <entry name="FromCursor" type="Bool">
+ <label>
+ </label>
+ <default>false</default>
+ </entry>
+ <entry name="IgnoreAccelMarker" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="IgnoreContextInfo" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="InComment" type="Bool">
+ <label>
+ </label>
+ <default>false</default>
+ </entry>
+ <entry name="InMsgid" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="InMsgstr" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="List" type="String">
+ <label>
+ </label>
+ <default>right as,Record here,sidereal,altitu</default>
+ </entry>
+ <entry name="RegExp" type="Bool">
+ <label>
+ </label>
+ <default>false</default>
+ </entry>
+ <entry name="WholeWords" type="Bool">
+ <label>
+ </label>
+ <default>false</default>
+ </entry>
+ </group>
+ <group name="KBCharSelector">
+ <entry name="SelectedChar" type="String">
+ <label>
+ </label>
+ <default> </default>
+ </entry>
+ <entry name="TableNum" type="UInt">
+ <label>
+ </label>
+ <default>0</default>
+ </entry>
+ </group>
+ <group name="KBabel">
+ <entry name="Version" type="String">
+ <label>
+ </label>
+ <default>1.3</default>
+ </entry>
+ </group>
+ <group name="KFileDialog Settings">
+ <entry name="AutomaticPreview" key="Automatic Preview" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="PreviewSize" key="Preview Size" type="UInt">
+ <label>
+ </label>
+ <default>60</default>
+ </entry>
+ <entry name="RecentFiles" key="Recent Files" type="String">
+ <label>
+ </label>
+ <default></default>
+ </entry>
+ <entry name="ShowPreviews" type="Bool">
+ <label>
+ </label>
+ <default>false</default>
+ </entry>
+ <entry name="ViewMode" type="String">
+ <label>
+ </label>
+ <default>SmallColumns</default>
+ </entry>
+ </group>
+ <group name="KFileDialog Speedbar">
+ <entry name="SpeedbarIconSize" key="Speedbar IconSize" type="UInt">
+ <label>
+ </label>
+ <default>32</default>
+ </entry>
+ </group>
+ <group name="Search">
+ <entry name="AutoSearch" type="Bool">
+ <label>
+ </label>
+ <default>false</default>
+ </entry>
+ <entry name="DefaultModule" type="String">
+ <label>
+ </label>
+ <default>pocompendium</default>
+ </entry>
+ </group>
+ <group name="View">
+ <entry name="Comments" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="EditSplitter" type="IntList">
+ <label>
+ </label>
+ <default>242,257</default>
+ </entry>
+ <entry name="Height768" key="Height 768" type="UInt">
+ <label>
+ </label>
+ <default>624</default>
+ </entry>
+ <entry name="MainSplitter" type="IntList">
+ <label>
+ </label>
+ <default>427,307</default>
+ </entry>
+ <entry name="Toolbox" type="UInt">
+ <label>
+ </label>
+ <default>0</default>
+ </entry>
+ <entry name="ToolboxSplitter" type="IntList">
+ <label>
+ </label>
+ <default>122,377</default>
+ </entry>
+ <entry name="Tools" type="Bool">
+ <label>
+ </label>
+ <default>true</default>
+ </entry>
+ <entry name="Width1024" key="Width 1024" type="UInt">
+ <label>
+ </label>
+ <default>739</default>
+ </entry>
+ </group>
+</kcfg>
diff --git a/kbabel/kbabel/kbabeliface.h b/kbabel/kbabel/kbabeliface.h
new file mode 100644
index 00000000..d03b927d
--- /dev/null
+++ b/kbabel/kbabel/kbabeliface.h
@@ -0,0 +1,81 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2001-2002 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef KBABELIFACE_H
+#define KBABELIFACE_H
+
+#include <dcopobject.h>
+#include <qstringlist.h>
+
+class KBabelIface : virtual public DCOPObject
+{
+ K_DCOP
+public:
+
+k_dcop:
+ virtual void openURL(QCString url, QCString package, WId window, int newWindow) { url = ""; window = 0; newWindow = 0; package= "";}
+ virtual void openURL(QCString url, QCString package, WId window, int newWindow, QCString projectFile)
+ { url = ""; window = 0; newWindow = 0; projectFile=""; package= "";}
+ virtual void openTemplate(QCString openFilename, QCString package, QCString saveFilename, int newWindow) { openFilename = ""; saveFilename = ""; newWindow = 0; package= "";}
+ virtual void openTemplate(QCString openFilename, QCString package, QCString saveFilename, int newWindow, QCString projectFile)
+ { openFilename = ""; saveFilename = ""; newWindow = 0; projectFile=""; package= "";}
+ /**
+ * open file url, if not already opened and goto entry
+ * that is equal msgid
+ */
+ virtual void gotoFileEntry(QCString url, QCString msgid)=0;
+ virtual void gotoFileEntry(QCString url, QCString package, int msgid)=0;
+ virtual void gotoFileEntry(QCString url, QCString package, int msgid, QCString projectFile)=0;
+
+
+ virtual bool findInFile(QCString fileSource, QCString url,
+ QString findStr, int caseSensitive, int wholeWords, int isRegExp,
+ int inMsgid, int inMsgstr, int inComment,
+ int ignoreAccelMarker, int ignoreContextInfo, int askForNextFile, int askForSave)=0;
+ virtual bool replaceInFile(QCString fileSource, QCString url,
+ QString findStr, QString replaceStr, int caseSensitive, int wholeWords, int isRegExp,
+ int inMsgid, int inMsgstr, int inComment, int ignoreAccelMarker,
+ int ignoreContextInfo, int ask, int askForNextFile, int askForSave)=0;
+ virtual bool findInFile(QCString fileSource, QCString url,
+ QString findStr, int caseSensitive, int wholeWords, int isRegExp,
+ int inMsgid, int inMsgstr, int inComment,
+ int ignoreAccelMarker, int ignoreContextInfo, int askForNextFile, int askForSave, QCString project )=0;
+ virtual bool replaceInFile(QCString fileSource, QCString url,
+ QString findStr, QString replaceStr, int caseSensitive, int wholeWords, int isRegExp,
+ int inMsgid, int inMsgstr, int inComment, int ignoreAccelMarker,
+ int ignoreContextInfo, int ask, int askForNextFile, int askForSave, QCString project )=0;
+ virtual void spellcheck(QStringList fileList)=0;
+};
+
+#endif // KBABELIFACE_H
diff --git a/kbabel/kbabel/kbabelpref.cpp b/kbabel/kbabel/kbabelpref.cpp
new file mode 100644
index 00000000..2907f060
--- /dev/null
+++ b/kbabel/kbabel/kbabelpref.cpp
@@ -0,0 +1,198 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2004-2005 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include "kbabelpref.h"
+#include "kbabeldictbox.h"
+#include "kbabelsettings.h"
+#include "fontpreferences.h"
+#include "editordiffpreferences.h"
+#include "editorpreferences.h"
+#include "searchpreferences.h"
+#include "colorpreferences.h"
+#include "toolaction.h"
+#include "toolselectionwidget.h"
+#include "qcombobox.h"
+
+#include <klocale.h>
+#include <kapplication.h>
+
+using namespace KBabel;
+
+KBabelPreferences::KBabelPreferences(QPtrList<ModuleInfo> ml)
+ : KConfigDialog(0, "Preferences", KBabelSettings::self())
+{
+ _editorPage = new EditorPreferences(0, "editor");
+ addPage( _editorPage
+ , i18n("title of page in preferences dialog","Edit")
+ , "edit"
+ , i18n("Options for Editing"));
+
+ // this contains a custom widget for tool selection, set it up
+ QValueList<KDataToolInfo> tools = ToolAction::validationTools();
+ _editorPage->_kcfg_AutoCheckTools->loadTools( "validate", tools );
+ connect( _editorPage->_kcfg_AutoCheckTools, SIGNAL( added( QListBoxItem * ) ),
+ this, SLOT (updateButtons()));
+ connect( _editorPage->_kcfg_AutoCheckTools, SIGNAL( removed( QListBoxItem * ) ),
+ this, SLOT (updateButtons()));
+
+ addPage(_searchPage = new SearchPreferences(0, "search")
+ , i18n("title of page in preferences dialog","Search")
+ , "transsearch"
+ , i18n("Options for Searching Similar Translations"));
+
+ // setup the dictionary combobox contents
+ ModuleInfo *info;
+ for(info = ml.first(); info != 0; info = ml.next())
+ {
+ _searchPage->_kcfg_DefaultModule->insertItem(info->name);
+ }
+ moduleList = ml;
+ connect( _searchPage->_kcfg_DefaultModule, SIGNAL( activated(int) ),
+ this, SLOT (updateButtons()));
+
+ addPage(new EditorDiffPreferences(0, "diff")
+ ,i18n("title of page in preferences dialog","Diff")
+ , "diff"
+ , i18n("Options for Showing Differences"));
+
+ addPage(new FontPreferences(0, "fonts")
+ , i18n("name of page in preferences dialog icon list","Fonts")
+ , "font"
+ , i18n("title of page in preferences dialog","Font Settings"));
+
+ addPage(new ColorPreferences(0, "colors")
+ , i18n("name of page in preferences dialog icon list","Colors")
+ , "colorize"
+ , i18n("title of page in preferences dialog","Color Settings"));
+
+ adjustSize();
+}
+
+
+void KBabelPreferences::slotHelp()
+{
+ //TODO
+ kapp->invokeHelp("Preferences","");
+}
+
+bool KBabelPreferences::hasChanged()
+{
+ ModuleInfo *info = moduleList.at(_searchPage->_kcfg_DefaultModule->currentItem());
+
+ bool module_ret = true;
+ if( info )
+ {
+ module_ret = info->id != KBabelSettings::defaultModule();
+ }
+
+ return KConfigDialog::hasChanged()
+ || (_editorPage->_kcfg_AutoCheckTools->selectedTools() != KBabelSettings::autoCheckTools())
+ || (module_ret);
+}
+
+bool KBabelPreferences::isDefault()
+{
+ bool old_useDefault = KBabelSettings::self()->useDefaults(true);
+
+ ModuleInfo *info = moduleList.at(_searchPage->_kcfg_DefaultModule->currentItem());
+ bool module_ret = ( info && info->id == KBabelSettings::defaultModule() );
+
+ bool ret = KConfigDialog::isDefault()
+ && (_editorPage->_kcfg_AutoCheckTools->selectedTools().empty())
+ && (module_ret);
+
+ KBabelSettings::self()->useDefaults(old_useDefault);
+ return ret;
+}
+
+void KBabelPreferences::updateSettings()
+{
+ KConfigDialog::updateSettings();
+
+ KBabelSettings::setAutoCheckTools(_editorPage->_kcfg_AutoCheckTools->selectedTools());
+
+ int i=_searchPage->_kcfg_DefaultModule->currentItem();
+ ModuleInfo *info = moduleList.at(i);
+
+ if(info)
+ {
+ KBabelSettings::setDefaultModule(info->id);
+ }
+
+ emit settingsChanged();
+}
+
+void KBabelPreferences::updateWidgets()
+{
+ KConfigDialog::updateWidgets();
+ _editorPage->_kcfg_AutoCheckTools->setSelectedTools(KBabelSettings::autoCheckTools());
+
+ int i=0;
+ ModuleInfo *info;
+ for(info = moduleList.first(); info != 0; info = moduleList.next())
+ {
+ if(KBabelSettings::defaultModule() == info->id)
+ break;
+
+ i++;
+ }
+ _searchPage->_kcfg_DefaultModule->setCurrentItem(i);
+}
+
+void KBabelPreferences::updateWidgetsDefault()
+{
+ KConfigDialog::updateWidgetsDefault();
+
+ bool old_useDefault = KBabelSettings::self()->useDefaults(true);
+
+ kdDebug () << "Default tools: " << KBabelSettings::autoCheckTools() << endl;
+
+ _editorPage->_kcfg_AutoCheckTools->setSelectedTools(KBabelSettings::autoCheckTools());
+
+ int i=0;
+ ModuleInfo *info;
+ for(info = moduleList.first(); info != 0; info = moduleList.next())
+ {
+ if(KBabelSettings::defaultModule() == info->id)
+ break;
+
+ i++;
+ }
+
+ _searchPage->_kcfg_DefaultModule->setCurrentItem(i);
+
+ KBabelSettings::self()->useDefaults(old_useDefault);
+}
+
+#include "kbabelpref.moc"
diff --git a/kbabel/kbabel/kbabelpref.h b/kbabel/kbabel/kbabelpref.h
new file mode 100644
index 00000000..a275e11e
--- /dev/null
+++ b/kbabel/kbabel/kbabelpref.h
@@ -0,0 +1,69 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef KBABELPREF_H
+#define KBABELPREF_H
+
+#include <kconfigdialog.h>
+#include <qptrlist.h>
+
+class SearchPreferences;
+class EditorPreferences;
+struct ModuleInfo;
+
+class KBabelPreferences : public KConfigDialog
+{
+ Q_OBJECT
+public:
+ KBabelPreferences(QPtrList<ModuleInfo>);
+
+protected slots:
+ virtual void slotHelp();
+ virtual void updateSettings();
+ virtual void updateWidgets();
+ virtual void updateWidgetsDefault();
+
+protected:
+ virtual bool hasChanged(); // reimplemented from KConfigDialog for our ToolSelectionWidget
+ virtual bool isDefault(); // reimplemented from KConfigDialog for our ToolSelectionWidget
+
+private:
+ SearchPreferences* _searchPage;
+ EditorPreferences* _editorPage;
+
+ QPtrList<ModuleInfo> moduleList;
+};
+
+
+#endif // KBABELPREF_H
diff --git a/kbabel/kbabel/kbabelsettings.kcfgc b/kbabel/kbabel/kbabelsettings.kcfgc
new file mode 100644
index 00000000..93c75552
--- /dev/null
+++ b/kbabel/kbabel/kbabelsettings.kcfgc
@@ -0,0 +1,5 @@
+File=kbabel.kcfg
+ClassName=KBabelSettings
+Singleton=true
+Mutators=true
+
diff --git a/kbabel/kbabel/kbabelsplash.cpp b/kbabel/kbabel/kbabelsplash.cpp
new file mode 100644
index 00000000..a13d8cd7
--- /dev/null
+++ b/kbabel/kbabel/kbabelsplash.cpp
@@ -0,0 +1,73 @@
+/*
+ *
+ * $Id$
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ * 2003 Stanislav Visnovsky <visnovsky@kde.org>
+ *
+ * This file is part of the KBabel project. It's taken from the K3b project,
+ * Copyright (C) 1998-2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * 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.
+ * See the file "COPYING" for the exact licensing terms.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+ */
+
+#include "kbabelsplash.h"
+
+#include <qapplication.h>
+#include <qlabel.h>
+#include <qpixmap.h>
+#include <qevent.h>
+#include <qstring.h>
+#include <qfontmetrics.h>
+#include <qpainter.h>
+
+#include <kstandarddirs.h>
+
+KBabelSplash* KBabelSplash::instance = 0;
+
+KBabelSplash::KBabelSplash( QWidget* parent, const char* name )
+ : QVBox( parent, name, WType_Dialog|WShowModal|WStyle_Customize|WStyle_NoBorder|WDestructiveClose )
+{
+ setMargin( 0 );
+ setSpacing( 0 );
+
+ QLabel* picLabel = new QLabel( this );
+ QPixmap pixmap;
+ if( pixmap.load( locate( "data", "kbabel/pics/splash.png" ) ) )
+ picLabel->setPixmap( pixmap );
+
+ picLabel->setFrameStyle(QFrame::WinPanel | QFrame::Raised);
+
+ // Set geometry, with support for Xinerama systems
+ QRect r;
+ r.setSize(sizeHint());
+ int ps = QApplication::desktop()->primaryScreen();
+ r.moveCenter( QApplication::desktop()->screenGeometry(ps).center() );
+ setGeometry(r);
+
+ delete instance;
+ instance = this;
+}
+
+
+void KBabelSplash::mousePressEvent( QMouseEvent* )
+{
+ close();
+}
+
+#include "kbabelsplash.moc"
diff --git a/kbabel/kbabel/kbabelsplash.h b/kbabel/kbabel/kbabelsplash.h
new file mode 100644
index 00000000..3ae14c9a
--- /dev/null
+++ b/kbabel/kbabel/kbabelsplash.h
@@ -0,0 +1,55 @@
+/*
+ *
+ * $Id$
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ * 2003 Stanislav Visnovsky <visnovsky@kde.org>
+ *
+ * This file is part of the KBabel project. It's taken from the K3b project,
+ * Copyright (C) 1998-2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * 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.
+ * See the file "COPYING" for the exact licensing terms.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+ */
+
+
+#ifndef KBABELSPLASH_H
+#define KBABELSPLASH_H
+
+#include <qvbox.h>
+
+class QLabel;
+class QMouseEvent;
+class QPaintEvent;
+class QString;
+
+
+class KBabelSplash : public QVBox
+{
+Q_OBJECT
+
+ public:
+ KBabelSplash( QWidget* parent = 0, const char* name = 0 );
+ ~KBabelSplash() { instance = 0; }
+
+ static KBabelSplash* instance;
+
+ protected:
+ void mousePressEvent( QMouseEvent* );
+};
+
+#endif
diff --git a/kbabel/kbabel/kbabelui.rc b/kbabel/kbabel/kbabelui.rc
new file mode 100644
index 00000000..40b52241
--- /dev/null
+++ b/kbabel/kbabel/kbabelui.rc
@@ -0,0 +1,235 @@
+<!DOCTYPE kpartgui>
+<kpartgui name="kbabel" version="21">
+ <MenuBar>
+ <Menu name="file"><text>&amp;File</text>
+ <Action name="save_special" append="save_merge"/>
+ <Action name="set_package" append="open_merge"/>
+ <Action name="file_new_view"/>
+ <Action name="file_new_window"/>
+ </Menu>
+ <Menu name="edit"><text>&amp;Edit</text>
+ <Action name="clear"/>
+ <Action name="msgid2msgstr"/>
+ <Action name="search2msgstr"/>
+ <Action name="plural2msgstr"/>
+ <Action name="char2msgstr"/>
+ <Action name="edit_toggle_fuzzy"/>
+ <Separator/>
+ <Action name="insert_next_tag"/>
+ <Action name="insert_next_tag_msgid"/>
+ <Action name="insert_tag"/>
+ <Action name="move_to_next_tag"/>
+ <Action name="move_to_prev_tag"/>
+ <Separator/>
+ <Action name="insert_next_arg"/>
+ <Action name="insert_arg"/>
+ <Separator/>
+ <Action name="edit_edit_header"/>
+ </Menu>
+ <Menu noMerge="1" name="go_document"><text>&amp;Go</text>
+ <Action name="go_prev_entry"/>
+ <Action name="go_next_entry"/>
+ <Action name="go_goto"/>
+ <Separator/>
+ <Action name="go_first"/>
+ <Action name="go_last"/>
+ <Separator/>
+ <Action name="go_prev_fuzzyUntr"/>
+ <Action name="go_next_fuzzyUntr"/>
+ <Action name="go_prev_fuzzy"/>
+ <Action name="go_next_fuzzy"/>
+ <Action name="go_prev_untrans"/>
+ <Action name="go_next_untrans"/>
+ <Separator/>
+ <Action name="go_prev_error"/>
+ <Action name="go_next_error"/>
+ <Separator/>
+ <Action name="go_back_history"/>
+ <Action name="go_forward_history"/>
+ </Menu>
+ <Menu name="projects"><text>&amp;Project</text>
+ <Action name="project_new"/>
+ <Action name="project_open"/>
+ <Action name="project_close"/>
+ <Action name="project_settings"/>
+ <Action name="recent_projects"/>
+ </Menu>
+ <Menu name="tools"><text>&amp;Tools</text>
+ <Menu name="spellcheck" icon="spellcheck"><text>&amp;Spelling</text>
+ <Action name="spellcheck_common"/>
+ <Separator/>
+ <Action name="spellcheck_all"/>
+ <Action name="spellcheck_from_cursor"/>
+ <Action name="spellcheck_current"/>
+ <Action name="spellcheck_from_current" />
+ <Action name="spellcheck_marked"/>
+ </Menu>
+ <Action name="dynamic_validation_tools"/>
+ <Menu name="diff" icon="diff"><text>D&amp;iff</text>
+ <Action name="diff_diff"/>
+ <Action name="diff_showOrig"/>
+ <Action name="diff_openFile"/>
+ <Separator/>
+ <Action name="diff_toggleDiff"/>
+ </Menu>
+ <Action name="dynamic_modify_tools"/>
+ <Separator/>
+ <Action name="rough_translation"/>
+ <Action name="word_count"/>
+ <Separator/>
+ <Action name="open_catalog_manager"/>
+ </Menu>
+ <Menu name="dictionaries"><text>&amp;Dictionaries</text>
+ <Action name="dict_search_all"/>
+ <Action name="dict_search_selected"/>
+ <Action name="dict_edit"/>
+ </Menu>
+ <Menu name="settings"><text>&amp;Settings</text>
+ <Action name="dict_configure" append="configure_merge"/>
+ </Menu>
+ <Menu name="bookmark"><text>&amp;Bookmarks</text>
+ <Action name="add_bookmark"/>
+ <Action name="clear_bookmarks"/>
+ <Separator/>
+ </Menu>
+ <Menu name="help"><text>&amp;Help</text>
+ <Action name="help_gettext"/>
+ <Action name="dict_about" append="about_merge"/>
+ </Menu>
+ </MenuBar>
+ <ToolBar name="mainToolBar"><text>Main</text>
+ <Action name="msgid2msgstr"/>
+ <Action name="search2msgstr"/>
+ <Action name="insert_tag"/>
+ <Action name="insert_arg"/>
+ <Separator/>
+ <Action name="spellcheck_common"/>
+ <Action name="diff_toggleDiff"/>
+ <Action name="dict_search_selected"/>
+ <Action name="stop_search"/>
+ <Separator/>
+ <Action name="open_catalog_manager"/>
+ </ToolBar>
+ <ToolBar name="navigationbar"><text>Navigationbar</text>
+ <Action name="go_prev_entry"/>
+ <Action name="go_next_entry"/>
+ <Separator/>
+ <Action name="go_first"/>
+ <Action name="go_last"/>
+ <Action name="go_prev_fuzzyUntr"/>
+ <Action name="go_next_fuzzyUntr"/>
+ <Action name="go_prev_fuzzy"/>
+ <Action name="go_next_fuzzy"/>
+ <Action name="go_prev_untrans"/>
+ <Action name="go_next_untrans"/>
+ <Separator/>
+ <Action name="go_prev_error"/>
+ <Action name="go_next_error"/>
+ <Separator/>
+ <Action name="go_back_history"/>
+ <Action name="go_forward_history"/>
+ </ToolBar>
+ <Menu name="rmb_edit">
+ <Action name="edit_undo"/>
+ <Action name="edit_redo"/>
+ <Separator/>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <Action name="edit_select_all"/>
+ <Separator/>
+ <Action name="msgid2msgstr"/>
+ <Action name="search2msgstr"/>
+ <Action name="edit_unset_fuzzy"/>
+ <Separator/>
+ <Action name="insert_next_tag"/>
+ <Action name="insert_tag"/>
+ <Separator/>
+ <Action name="dict_search_all"/>
+ <Action name="dict_search_selected"/>
+ </Menu>
+ <Menu name="rmb_search">
+ <Action name="edit_copy"/>
+ <Action name="search2msgstr"/>
+ <Separator/>
+ <Action name="dict_search_all"/>
+ <Action name="dict_search_selected"/>
+ <Separator/>
+ <Action name="dict_edit"/>
+ <Action name="dict_configure"/>
+ <Separator/>
+ <Action name="stop_search"/>
+ </Menu>
+ <State name="readonly">
+ <Disable>
+ <Action name="file_save"/>
+ <Action name="file_revert"/>
+ <Action name="edit_undo"/>
+ <Action name="edit_redo"/>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <Action name="edit_replace"/>
+ <Action name="insert_next_tag"/>
+ <Action name="insert_next_tag_msgid"/>
+ <Action name="insert_tag"/>
+ <Action name="insert_next_arg"/>
+ <Action name="insert_arg"/>
+ <Action name="plural2msgstr"/>
+ <Action name="char2msgstr"/>
+ <Action name="clear"/>
+ <Action name="msgid2msgstr"/>
+ <Action name="search2msgstr"/>
+ <Action name="edit_edit_header"/>
+ <Action name="edit_toggle_fuzzy"/>
+ <Action name="spellcheck_common"/>
+ <Action name="spellcheck_all"/>
+ <Action name="spellcheck_from_cursor"/>
+ <Action name="spellcheck_current"/>
+ <Action name="spellcheck_from_current" />
+ <Action name="spellcheck_marked"/>
+ <Action name="rough_translation"/>
+ </Disable>
+ </State>
+ <State name="fileopened">
+ <Enable>
+ <Action name="file_save_as"/>
+ <Action name="save_special"/>
+ <Action name="set_package"/>
+ <Action name="file_mail"/>
+ <Action name="edit_find"/>
+ <Action name="edit_find_next"/>
+ <Action name="edit_find_last"/>
+ <Action name="edit_select_all"/>
+ <Action name="move_to_next_tag"/>
+ <Action name="move_to_prev_tag"/>
+ <Action name="go_goto"/>
+ <Action name="go_prev_entry"/>
+ <Action name="go_next_entry"/>
+ <Action name="go_first"/>
+ <Action name="go_last"/>
+ <Action name="go_prev_fuzzyUntr"/>
+ <Action name="go_next_fuzzyUntr"/>
+ <Action name="go_prev_fuzzy"/>
+ <Action name="go_next_fuzzy"/>
+ <Action name="go_prev_untrans"/>
+ <Action name="go_next_untrans"/>
+ <Action name="go_prev_error"/>
+ <Action name="go_next_error"/>
+ <Action name="go_back_history"/>
+ <Action name="go_forward_history"/>
+ <Action name="dict_search_selected"/>
+ <Action name="dict_search_all"/>
+ <Action name="diff_toggleDiff"/>
+ <Action name="diff_diff"/>
+ <Action name="diff_showOrig"/>
+ <Action name="diff_openFile"/>
+ <Action name="check_syntax"/>
+ <Action name="check_all"/>
+ <Action name="dynamic_validation_tools"/>
+ <Action name="dynamic_modify_tools"/>
+ <Action name="add_bookmark"/>
+ <Action name="word_found"/>
+ </Enable>
+ </State>
+</kpartgui>
diff --git a/kbabel/kbabel/kbabelview.cpp b/kbabel/kbabel/kbabelview.cpp
new file mode 100644
index 00000000..2e9ebfa3
--- /dev/null
+++ b/kbabel/kbabel/kbabelview.cpp
@@ -0,0 +1,4473 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer <matthias.kiefer@gmx.de>
+ 2002-2005 by Stanislav Visnovsky <visnovsky@kde.org>
+ Copyright (C) 2006 by Nicolas GOUTTE <goutte@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#include "kbabelview.h"
+
+#include "catalogfileplugin.h"
+#include "toolaction.h"
+#include "kbabelsettings.h"
+#include "kbprojectsettings.h"
+
+#include <qlayout.h>
+
+#include <qlabel.h>
+#include <qframe.h>
+#include <qfileinfo.h>
+#include <qvariant.h>
+#include <qwhatsthis.h>
+#include <qdragobject.h>
+#include <qpopupmenu.h>
+#include <qstylesheet.h>
+#include <qtabwidget.h>
+#include <qtextview.h>
+#include <qtextstream.h>
+#include <qtimer.h>
+#include <qvbox.h>
+
+#include <dcopclient.h>
+#include <kdeversion.h>
+#include <kcharsets.h>
+#include <kcmenumngr.h>
+#include <kconfigdialog.h>
+#include <kdatatool.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kcursor.h>
+#include <kfiledialog.h>
+#include <kconfig.h>
+#include <kapplication.h>
+#include <kled.h>
+#include <klistbox.h>
+#include <kio/netaccess.h>
+#include <knotifyclient.h>
+#include <ktempfile.h>
+#include <kspell.h>
+#include <kwin.h>
+#include <kstdaccel.h>
+#include <kurldrag.h>
+#include <kglobalsettings.h>
+
+#include "resources.h"
+
+#include "editcmd.h"
+#include "finddialog.h"
+#include "gotodialog.h"
+#include "headereditor.h"
+#include "hidingmsgedit.h"
+#include "kbabeldictbox.h"
+#include "kbcatalog.h"
+#include "msgfmt.h"
+#include "spelldlg.h"
+#include "regexpextractor.h"
+#include "projectprefwidgets.h"
+#include "kbabel.h"
+#include "kbprojectmanager.h"
+
+#include "commentview.h"
+#include "contextview.h"
+#include "kbcataloglistview.h"
+#include "charselectview.h"
+#include "taglistview.h"
+#include "sourceview.h"
+#include "errorlistview.h"
+
+#include "version.h"
+
+
+#define ID_DROP_OPEN 1
+#define ID_DROP_OPEN_TEMPLATE 2
+
+#define MAX_HISTORY 50
+
+using namespace KBabel;
+
+QPtrList<KBabelView> *KBabelView::viewList = 0;
+
+KBabelView::KBabelView(KBCatalog* catalog,KBabelMW *parent, Project::Ptr project)
+ : QWidget(parent)
+ , _redirectedBackSearch (false)
+ , _project (project)
+ , m_mainwindow (parent)
+ , m_sourceview (0)
+{
+ if(!viewList)
+ viewList = new QPtrList<KBabelView>;
+
+ viewList->append(this);
+
+ if (catalog == 0)
+ kdFatal(KBABEL) << "catalog==0" << endl;
+
+ _catalog=catalog;
+ _catalog->registerView(this);
+
+ _config = KSharedConfig::openConfig ("kbabelrc");
+
+ KConfigGroupSaver gs(_config,"Editor");
+ bool buildLeds=! KBabelSettings::ledInStatusbar();
+
+ _fuzzyLed=0;
+ _untransLed=0;
+ _errorLed=0;
+ _currentIndex=0;
+ _currentPos.item=1; // to ensure update
+ _currentPos.form=0;
+ _gotoDialog=0;
+ _findDialog=0;
+ _replaceDialog=0;
+ _replaceAskDialog=0;
+ _tagsMenu=0;
+ _argsMenu=0;
+ _autoSearchTempDisabled=false;
+ _diffEnabled=false;
+ _loadingDiffFile=false;
+ _diffing=false;
+ _dontBeep=false;
+
+ m_overwrite = false;
+
+ autoSaveTimer = 0;
+
+ _showTryLaterBox=true;
+ _tagExtractor = new RegExpExtractor( catalog->tagSettings().tagExpressions );
+ _argExtractor = new RegExpExtractor( catalog->tagSettings().argExpressions );
+
+ _editingDocumentation=false;
+
+ _autocheckTools.clear();
+ _autocheckTools.setAutoDelete(true);
+
+ spell.posDict.setAutoDelete(true);
+ spell.active=false;
+
+ spell2.kspell = 0;
+ spell2.config = 0;
+
+ setAcceptDrops(true);
+
+ // this widget does not contain anything, we should hide it
+ hide();
+
+ dictBox = new KBabelDictBox(this,"dictBox");
+ QWhatsThis::add(dictBox,
+ i18n("<qt><p><b>Search results</b></p>"
+ "<p>This part of the window shows the results of searching in "
+ "dictionaries.<p>"
+ "<p>In the top is displayed the number of entries found and "
+ "where the currently displayed entry is found. Use the buttons "
+ "at the bottom to navigate through the search results.</p>"
+ "<p>Search is either started automatically when switching to "
+ "another entry in the editor window or by choosing the desired "
+ "dictionary in <b>Dictionaries->Find...</b>.</p>"
+ "<p>The common options can be configured in the preferences dialog "
+ "in section <b>Search</b> and the options for the different "
+ "dictionaries can be changed with "
+ "<b>Settings->Configure Dictionary</b>.</p></qt>"));
+
+ initDockWidgets();
+
+ msgstrEdit->setReadOnly(true);
+ dictBox->setEnabled(false);
+
+ connect(this, SIGNAL(signalNewFileOpened(KURL)),
+ m_cataloglistview, SLOT(slotNewFileOpened()));
+
+ connect(msgstrEdit,SIGNAL(signalUndoCmd(KBabel::EditCommand*)),this,SLOT(forwardMsgstrEditCmd(KBabel::EditCommand*)));
+ connect(msgstrEdit,SIGNAL(textChanged()),this
+ ,SIGNAL(signalMsgstrChanged()));
+
+ connect(msgstrEdit,SIGNAL(textChanged(const QString&)),m_cataloglistview
+ ,SLOT(msgstrChanged(const QString&)));
+
+ connect(this,SIGNAL(signalMsgstrChanged()),this,SLOT(autoCheck()));
+ connect(msgstrEdit,SIGNAL(currentFormChanged(uint)), this
+ ,SLOT(msgstrPluralFormChanged(uint)));
+
+ connect(msgidLabel,SIGNAL(cursorPositionChanged(int,int))
+ , this, SIGNAL(signalCursorPosChanged(int,int)));
+ connect(msgstrEdit,SIGNAL(cursorPositionChanged(int,int))
+ , this, SIGNAL(signalCursorPosChanged(int,int)));
+
+ connect(dictBox,SIGNAL(searchStarted()),this
+ ,SLOT(forwardSearchStart()));
+ connect(dictBox, SIGNAL(progressStarts(const QString&)), this
+ ,SLOT(forwardProgressStart(const QString&)));
+ connect(dictBox,SIGNAL(progressed(int)),this
+ ,SIGNAL(signalProgress(int)));
+ connect(dictBox,SIGNAL(searchStopped()),this
+ ,SLOT(forwardSearchStop()));
+ connect(dictBox,SIGNAL(progressEnds()),this
+ ,SIGNAL(signalClearProgressBar()));
+
+ connect(dictBox,SIGNAL(modulesChanged()),this,
+ SIGNAL(signalDictionariesChanged()));
+ connect(dictBox,SIGNAL(errorInModule(const QString&)),this
+ ,SLOT(showError(const QString&)));
+
+ connect(_catalog,SIGNAL(signalSettingsChanged(KBabel::IdentitySettings)),
+ this, SLOT(setNewLanguage()));
+
+ connect(_catalog,SIGNAL(signalNumberOfFuzziesChanged(uint)),
+ this, SLOT(checkFuzzies()));
+ connect(_catalog,SIGNAL(signalNumberOfUntranslatedChanged(uint)),
+ this, SLOT(checkUntranslated()));
+
+ if(buildLeds)
+ {
+ connect(this,SIGNAL(signalFuzzyDisplayed(bool))
+ ,this,SLOT(toggleFuzzyLed(bool)));
+ connect(this,SIGNAL(signalUntranslatedDisplayed(bool))
+ ,this,SLOT(toggleUntransLed(bool)));
+ connect(this,SIGNAL(signalFaultyDisplayed(bool))
+ ,this,SLOT(toggleErrorLed(bool)));
+ }
+
+ _dropMenu = new QPopupMenu(this);
+ _dropMenu->insertItem(i18n("Menu item", "Open"),ID_DROP_OPEN);
+ _dropMenu->insertItem(i18n("Open Template"),ID_DROP_OPEN_TEMPLATE);
+
+ readSettings(_config);
+ readProject(_project);
+
+ connect (project, SIGNAL(signalSpellcheckSettingsChanged()),
+ this, SLOT(updateProjectSettings()));
+
+ if(!_catalog->currentURL().isEmpty())
+ {
+ newFileOpened(_catalog->isReadOnly());
+ }
+
+ // take over the language settings from the catalog
+ setNewLanguage();
+}
+
+KBabelView::~KBabelView()
+{
+ viewList->remove(this);
+ if(viewList->isEmpty())
+ {
+ delete viewList;
+ viewList=0;
+ }
+
+ _catalog->removeView(this);
+
+ // check if this view was the last view and delete the catalog if necessary
+ if(!_catalog->hasView())
+ {
+ delete _catalog;
+ }
+
+ delete _argExtractor;
+ delete _tagExtractor;
+
+ if( spell2.kspell )
+ {
+ spell2.kspell = 0;
+ delete spell2.config;
+ spell2.config = 0;
+ }
+}
+
+void KBabelView::initDockWidgets()
+{
+ // setup main dock widget - original text
+ QWidget *tempWidget=new QWidget(this,"msgidWidget");
+ tempWidget->setMinimumSize(350,150);
+
+ QVBoxLayout *layout=new QVBoxLayout(tempWidget);
+
+ msgidLabel = new HidingMsgEdit(2, this, 0, tempWidget,"msgidLabel");
+ msgidLabel->installEventFilter(this);
+ msgidLabel->setReadOnly(true);
+ msgidLabel->setDiffMode(true);
+ KCursor::setAutoHideCursor(msgidLabel,true);
+
+ msgidLabel->setText(i18n("KBabel Version %1\n"
+"Copyright 1999-%2 by KBabel developers.\n"
+" Matthias Kiefer <kiefer@kde.org>\n"
+" Stanislav Visnovsky <visnovsky@kde.org>\n"
+" Marco Wegner <dubbleu@web.de>\n"
+" Dwayne Bailey <dwayne@translate.org.za>\n"
+" Andrea Rizzi <rizzi@kde.org>\n\n"
+"Any comments, suggestions, etc. should be sent to the mailing list <kbabel@kde.org>.\n\n"
+"This program is licensed under the terms of the GNU GPL.\n\n"
+"Special thanks to Thomas Diehl for many hints to the GUI\n"
+"and the behavior of KBabel and to Stephan Kulow, who always\n"
+"lends me a helping hand.\n\n"
+"Many good ideas, especially for the Catalog Manager, are taken\n"
+"from KTranslator by Andrea Rizzi.").arg(VERSION).arg(2006));
+
+ QLabel *label=new QLabel(msgidLabel,i18n("O&riginal string (msgid):"),tempWidget);
+
+ QHBoxLayout* hb=new QHBoxLayout(layout);
+ hb->addSpacing(KDialog::marginHint());
+ hb->addWidget(label);
+
+ layout->addWidget(msgidLabel);
+ layout->setStretchFactor(msgidLabel,1);
+
+ QWhatsThis::add(tempWidget,
+ i18n("<qt><p><b>Original String</b></p>\n\
+<p>This part of the window shows the original message\n\
+of the currently displayed entry.</p></qt>"));
+
+ KDockWidget* mainDock;
+ mainDock = m_mainwindow->createDockWidget( "Original", QPixmap ());
+ //i18n: translators: Dock window caption
+ mainDock->setCaption(i18n("Original Text"));
+ mainDock->setGeometry(50, 50, 100, 100);
+ // forbit docking abilities of mainDock itself
+ mainDock->setEnableDocking(KDockWidget::DockFullSite);
+
+ mainDock->setWidget(tempWidget);
+ m_mainwindow->setMainDockWidget(mainDock); // master dockwidget
+ mainDock->show ();
+ m_mainwindow->setView (mainDock);
+ connect (this, SIGNAL (signalCopy ()), this, SLOT (textCopy ()));
+ connect (this, SIGNAL (signalCut ()), this, SLOT (textCut ()));
+ connect (this, SIGNAL (signalPaste ()), this, SLOT (textPaste ()));
+ connect (this, SIGNAL (signalSelectAll ()), this, SLOT (selectAll ()));
+
+ KDockWidget* comment_dock = m_mainwindow->createDockWidget( "Comment", QPixmap ());
+ //i18n: translators: Dock window caption
+ comment_dock->setCaption(i18n("Comment"));
+ comment_dock->setGeometry(50, 50, 100, 100);
+ comment_dock->setEnableDocking(KDockWidget::DockCorner);
+ m_commentview = new CommentView(_catalog, comment_dock, _project);
+ comment_dock->setWidget(m_commentview);
+ comment_dock->manualDock( mainDock, // dock target
+ KDockWidget::DockRight, // dock site
+ 20 ); // relation target/this (in percent)
+ comment_dock->show ();
+ connect (this, SIGNAL (signalCopy ()), m_commentview, SLOT (textCopy ()));
+ connect (this, SIGNAL (signalCut ()), m_commentview, SLOT (textCut ()));
+ connect (this, SIGNAL (signalPaste ()), m_commentview, SLOT (textPaste ()));
+ connect (this, SIGNAL (signalSelectAll ()), m_commentview, SLOT (textSelectAll ()));
+ m_commentview->installEventFilter( this );
+
+ // build the msgstr widget
+ tempWidget=new QWidget(this,"msgstrWidget");
+ tempWidget->setMinimumSize(350,150);
+
+ layout=new QVBoxLayout(tempWidget);
+
+ // if undefined number of plural forms, use 1
+ int pf = _catalog->defaultNumberOfPluralForms();
+ if( pf < 1 )
+ pf = 1;
+
+ msgstrEdit = new HidingMsgEdit( pf,this,spell2.kspell,tempWidget,"msgstrEdit");
+ msgstrEdit->installEventFilter(this);
+ KCursor::setAutoHideCursor(msgstrEdit,true);
+
+ label=new QLabel(msgstrEdit,i18n("Trans&lated string (msgstr):"),tempWidget);
+
+ hb=new QHBoxLayout(layout);
+ hb->setSpacing(KDialog::spacingHint());
+
+ hb->addSpacing(KDialog::marginHint());
+ hb->addWidget(label);
+ hb->addStretch(1);
+
+ if(! KBabelSettings::ledInStatusbar())
+ {
+ _fuzzyLed = new KLed(Qt::red,KLed::Off,KLed::Sunken,KLed::Rectangular
+ ,tempWidget);
+ _fuzzyLed->setFixedSize(15,12);
+ label = new QLabel(i18n("fuzzy"),tempWidget);
+ hb->addWidget(_fuzzyLed);
+ hb->addWidget(label);
+
+ hb->addSpacing(KDialog::spacingHint());
+
+ _untransLed = new KLed(Qt::red,KLed::Off,KLed::Sunken,KLed::Rectangular
+ ,tempWidget);
+ _untransLed->setFixedSize(15,12);
+ label = new QLabel(i18n("untranslated"),tempWidget);
+ hb->addWidget(_untransLed);
+ hb->addWidget(label);
+
+ hb->addSpacing(KDialog::marginHint());
+
+ _errorLed = new KLed(Qt::red,KLed::Off,KLed::Sunken,KLed::Rectangular
+ ,tempWidget);
+ _errorLed->setFixedSize(15,12);
+ label = new QLabel(i18n("faulty"),tempWidget);
+ hb->addWidget(_errorLed);
+ hb->addWidget(label);
+
+ hb->addSpacing(KDialog::marginHint());
+
+ hb->addStretch(1);
+
+ // ### TODO: perhaps it should be moreprecise where the setting can be changed
+ QString ledMsg=i18n("<qt><p><b>Status LEDs</b></p>\n"
+ "<p>These LEDs display the status of the currently displayed message.\n"
+ "You can change their color in the preferences dialog section\n"
+ "<b>Editor</b> on page <b>Appearance</b></p></qt>");
+ QWhatsThis::add(_fuzzyLed,ledMsg);
+ QWhatsThis::add(_untransLed,ledMsg);
+ QWhatsThis::add(_errorLed,ledMsg);
+ }
+
+ layout->addWidget(msgstrEdit);
+ layout->setStretchFactor(msgstrEdit,1);
+
+ QWhatsThis::add(tempWidget,
+ i18n("<qt><p><b>Translation Editor</b></p>\n\
+<p>This editor displays and lets you edit the translation of the currently displayed message.<p></qt>"));
+
+
+ KDockWidget* msgstr_dock = m_mainwindow->createDockWidget( "Msgstr", QPixmap ());
+ //i18n: translators: Dock window caption
+ msgstr_dock->setCaption(i18n("Translated String"));
+ msgstr_dock->setEnableDocking(KDockWidget::DockCorner);
+ msgstr_dock->setWidget(tempWidget);
+ msgstr_dock->manualDock( mainDock, // dock target
+ KDockWidget::DockBottom, // dock site
+ 50 ); // relation target/this (in percent)
+ msgstr_dock->show ();
+
+ KDockWidget* dock = m_mainwindow->createDockWidget( "Search", QPixmap ());
+ //i18n: translators: Dock window caption
+ dock->setCaption(i18n("the search (noun)","Search"));
+ //i18n: translators: Dock tab caption
+ dock->setTabPageLabel(i18n("the search (noun)","Se&arch"));
+ dock->setGeometry(50, 50, 100, 100);
+ dock->setWidget(dictBox);
+ dock->manualDock( comment_dock, // dock target
+ KDockWidget::DockBottom, // dock site
+ 20 ); // relation target/this (in percent)
+ dock->show ();
+
+ KDockWidget* tools = dock;
+
+ dock = m_mainwindow->createDockWidget( "PO context", QPixmap ());
+ //i18n: translators: Dock window caption
+ dock->setCaption(i18n("PO Context"));
+ //i18n: translators: Dock tab caption
+ dock->setTabPageLabel(i18n("PO C&ontext"));
+ dock->setGeometry(50, 50, 100, 100);
+ ContextView * m_contextview = new ContextView(_catalog, dock, _project);
+ dock->setWidget(m_contextview);
+ dock->manualDock( tools, // dock target
+ KDockWidget::DockCenter, // dock site
+ 20 ); // relation target/this (in percent)
+ dock->show ();
+
+ dock = m_mainwindow->createDockWidget( "Charselector", QPixmap ());
+ //i18n: translators: Dock window caption
+ dock->setCaption(i18n("Character Table"));
+ //i18n: translators: Dock tab caption
+ dock->setTabPageLabel(i18n("C&hars"));
+ dock->setGeometry(50, 50, 100, 100);
+ m_charselectorview = new CharacterSelectorView(_catalog, dock, _project);
+ dock->setWidget(m_charselectorview);
+ dock->manualDock( tools, // dock target
+ KDockWidget::DockCenter, // dock site
+ 20 ); // relation target/this (in percent)
+ dock->show ();
+
+
+ dock = m_mainwindow->createDockWidget( "Tag List", QPixmap ());
+ //i18n: translators: Dock window caption
+ dock->setCaption(i18n("Tag List"));
+ //i18n: translators: Dock tab caption
+ dock->setTabPageLabel(i18n("Tags"));
+ dock->setGeometry(50, 50, 100, 100);
+ TagListView* m_taglistview = new TagListView(_catalog, dock, _project);
+ dock->setWidget(m_taglistview);
+ dock->manualDock( tools, // dock target
+ KDockWidget::DockCenter, // dock site
+ 20 ); // relation target/this (in percent)
+ dock->show ();
+
+ dock = m_mainwindow->createDockWidget( "Source Context", QPixmap ());
+ //i18n: translators: Dock window caption
+ dock->setCaption(i18n("Source Context"));
+ //i18n: translators: Dock tab caption
+ dock->setTabPageLabel(i18n("Source"));
+ dock->setGeometry(50, 50, 100, 100);
+ m_sourceview = new SourceView(_catalog, dock, _project);
+ dock->setWidget(m_sourceview);
+ dock->manualDock( tools, // dock target
+ KDockWidget::DockCenter, // dock site
+ 20 ); // relation target/this (in percent)
+ dock->show ();
+
+ KDockWidget* translist_dock = m_mainwindow->createDockWidget( "Translation List", QPixmap ());
+ translist_dock->setCaption(i18n("Translation List"));
+ translist_dock->setGeometry(50, 50, 100, 100);
+ translist_dock->setEnableDocking(KDockWidget::DockFullSite);
+ m_cataloglistview = new KBCatalogListView(_catalog, translist_dock, _project);
+ translist_dock->setWidget(m_cataloglistview);
+ translist_dock->manualDock( mainDock, KDockWidget::DockTop,100);
+ translist_dock->show ();
+
+ dock = m_mainwindow->createDockWidget( "Error List", QPixmap ());
+ //i18n: translators: Dock window caption
+ dock->setCaption(i18n("Error List"));
+ //i18n: translators: Dock tab caption
+ dock->setTabPageLabel(i18n("Errors"));
+ dock->setGeometry(50, 50, 100, 100);
+ ErrorListView* m_errorlistview = new ErrorListView(_catalog, dock, _project);
+ dock->setWidget(m_errorlistview);
+ dock->manualDock( tools, // dock target
+ KDockWidget::DockCenter, // dock site
+ 20 );
+ dock->show ();
+
+ connect(m_cataloglistview,SIGNAL(signalSelectionChanged(const KBabel::DocPosition&))
+ ,this,SLOT(gotoEntry(const KBabel::DocPosition&)));
+ connect(this,SIGNAL(signalDisplayed(const KBabel::DocPosition&))
+ ,m_commentview,SLOT(gotoEntry(const KBabel::DocPosition&)));
+ connect(this,SIGNAL(signalDisplayed(const KBabel::DocPosition&))
+ ,m_contextview,SLOT(gotoEntry(const KBabel::DocPosition&)));
+ connect(this,SIGNAL(signalDisplayed(const KBabel::DocPosition&))
+ ,m_taglistview,SLOT(gotoEntry(const KBabel::DocPosition&)));
+ connect(this,SIGNAL(signalDisplayed(const KBabel::DocPosition&))
+ ,m_sourceview,SLOT(gotoEntry(const KBabel::DocPosition&)));
+ connect(this,SIGNAL(signalDisplayed(const KBabel::DocPosition&))
+ ,m_errorlistview,SLOT(gotoEntry(const KBabel::DocPosition&)));
+ connect(this,SIGNAL(signalFaultyDisplayed(bool))
+ ,m_errorlistview,SLOT(updateView()));
+ connect(m_charselectorview, SIGNAL( characterDoubleClicked(QChar) )
+ ,this, SLOT( insertChar(QChar) ));
+ connect(m_taglistview,SIGNAL(signalTagSelected(const QString&))
+ , this, SLOT(insertTagFromTool(const QString&)));
+ connect(m_taglistview,SIGNAL(signalHighlightedTagChanged(int))
+ , this, SLOT(skipToTagFromTool(int)));
+ connect(this, SIGNAL(signalNextTag(int))
+ , m_taglistview, SLOT(highlightTag(int)));
+ connect(m_commentview,SIGNAL(signalCursorPosChanged(int,int))
+ , m_mainwindow, SLOT(updateCursorPosition(int,int)));
+}
+
+KBabelView *KBabelView::viewForURL(const KURL& url, const QString project)
+{
+ if(url.isEmpty())
+ return 0;
+
+ if(!viewList)
+ return 0;
+
+ KURL u = url;
+ u.cleanPath();
+
+ QPtrListIterator<KBabelView> it(*viewList);
+ KBabelView *view=0;
+ while( it.current() && !view)
+ {
+ KURL cu = it.current()->currentURL();
+ cu.cleanPath();
+
+ if(cu == u && it.current()->project()==project)
+ {
+ view = it.current();
+ }
+
+ ++it;
+ }
+
+ return view;
+}
+
+KBabelView *KBabelView::emptyView(const QString)
+{
+ if(!viewList)
+ return 0;
+
+ QPtrListIterator<KBabelView> it(*viewList);
+ KBabelView *view=0;
+ while( it.current() && !view)
+ {
+ KURL cu = it.current()->currentURL();
+ if( cu.isEmpty() )
+ return it.current();
+ ++it;
+ }
+
+ return 0;
+}
+
+KURL KBabelView::currentURL() const
+{
+ return _catalog->currentURL();
+}
+
+bool KBabelView::isLastView() const
+{
+ return _catalog->isLastView();
+}
+
+bool KBabelView::isModified() const
+{
+ return _catalog->isModified();
+}
+
+bool KBabelView::isReadOnly() const
+{
+ return _catalog->isReadOnly();
+}
+
+bool KBabelView::isOverwriteMode() const
+{
+ return m_overwrite;
+}
+
+
+void KBabelView::setOverwriteMode(bool ovr)
+{
+ m_overwrite = ovr;
+ msgstrEdit->setOverwriteMode(ovr);
+ m_commentview->setOverwriteMode(ovr);
+}
+
+
+bool KBabelView::isSearching() const
+{
+ return dictBox->isSearching();
+}
+
+
+void KBabelView::update(EditCommand* cmd, bool undo)
+{
+ if((int)_currentIndex==cmd->index())
+ {
+ emitEntryState();
+
+ if(cmd->part()==Msgstr)
+ {
+ msgstrEdit->processCommand(cmd,undo);
+ emit signalMsgstrChanged();
+ }
+ }
+}
+
+
+
+void KBabelView::readSettings(KConfig* config)
+{
+
+ if(KBabelSettings::autoUnsetFuzzy())
+ {
+ connect(msgstrEdit,SIGNAL(textChanged())
+ ,this,SLOT(autoRemoveFuzzyStatus()));
+ }
+
+ setupAutoCheckTools();
+
+ KConfigGroupSaver saver(config,"Editor");
+
+ _diffEnabled = config->readBoolEntry("AutoDiff", false);
+ emit signalDiffEnabled(_diffEnabled);
+
+ if(_fuzzyLed)
+ {
+ _fuzzyLed->setColor(KBabelSettings::ledColor());
+ }
+ if(_untransLed)
+ {
+ _untransLed->setColor(KBabelSettings::ledColor());
+ }
+ if(_errorLed)
+ {
+ _errorLed->setColor(KBabelSettings::ledColor());
+ }
+
+ msgstrEdit->setCleverEditing(KBabelSettings::cleverEditing());
+
+ msgstrEdit->setHighlightBg(KBabelSettings::highlightBackground());
+ msgidLabel->setHighlightBg(KBabelSettings::highlightBackground());
+
+ msgstrEdit->setHighlightSyntax(KBabelSettings::highlightSyntax());
+ msgidLabel->setHighlightSyntax(KBabelSettings::highlightSyntax());
+
+ msgstrEdit->setQuotes(KBabelSettings::enableQuotes());
+ msgidLabel->setQuotes(KBabelSettings::enableQuotes());
+
+ msgstrEdit->setSpacePoints(KBabelSettings::whitespacePoints());
+ msgidLabel->setSpacePoints(KBabelSettings::whitespacePoints());
+
+ msgstrEdit->setFont(KBabelSettings::msgFont());
+ msgidLabel->setFont(KBabelSettings::msgFont());
+
+ msgstrEdit->setBgColor(KBabelSettings::backgroundColor());
+ msgidLabel->setBgColor(KBabelSettings::backgroundColor());
+
+ msgstrEdit->setHighlightColors(KBabelSettings::quotedColor(),KBabelSettings::errorColor()
+ ,KBabelSettings::cformatColor(),KBabelSettings::accelColor(),KBabelSettings::tagColor());
+ msgidLabel->setHighlightColors(KBabelSettings::quotedColor(),KBabelSettings::errorColor()
+ ,KBabelSettings::cformatColor(),KBabelSettings::accelColor(),KBabelSettings::tagColor());
+
+ msgidLabel->setDiffDisplayMode( KBabelSettings::diffAddUnderline()
+ ,KBabelSettings::diffDelStrikeOut() );
+ msgidLabel->setDiffColors(KBabelSettings::diffAddColor(), KBabelSettings::diffDelColor() );
+}
+
+void KBabelView::updateProjectSettings()
+{
+ readProject(_project);
+}
+
+void KBabelView::readProject(Project::Ptr project)
+{
+ _spellcheckSettings = project->spellcheckSettings();
+
+ if( _spellcheckSettings.onFlySpellcheck )
+ {
+
+ // if there is a spellchecker already, free it
+ if( spell2.kspell )
+ {
+ // ensure the spellchecker is not used anymore
+ msgstrEdit->setSpellChecker(0L);
+
+ // free it
+ spell2.kspell->cleanUp();
+
+ delete spell2.kspell;
+ spell2.kspell = 0;
+ }
+
+ spell2.config = new KSpellConfig(0L, "tempSpellConfig");
+ spell2.config->setNoRootAffix(_spellcheckSettings.noRootAffix);
+ spell2.config->setRunTogether(_spellcheckSettings.runTogether);
+ spell2.config->setClient(_spellcheckSettings.spellClient);
+ spell2.config->setEncoding(_spellcheckSettings.spellEncoding);
+ spell2.config->setDictionary(_spellcheckSettings.spellDict);
+
+ spell2.kspell= new KSpell(this, "", this, SLOT(dummy(KSpell *)),
+ spell2.config, false, false);
+ if(spell2.kspell->status() == KSpell::Error)
+ kdWarning(KBABEL) << "Something's wrong with KSpell, can't start on-the-fly checking" << endl;
+ else
+ {
+ kdDebug() << "On the fly spellchecker: "
+ << spell2.kspell << endl;
+ msgstrEdit->setSpellChecker(spell2.kspell);
+ }
+
+ // spell2.kspell->setAutoDelete(true); // let KSpell handle delete
+ //on-the-fly spellcheck end
+ }
+ else
+ {
+ // turn off spellchecker
+ msgstrEdit->setSpellChecker(0);
+ // invalidate the current settings, to make sure they are updated when needed
+ _spellcheckSettings.valid = false;
+ }
+
+ dictBox->readSettings(project->config());
+
+ m_sourceview->setProject(project);
+}
+
+void KBabelView::saveSettings()
+{
+ KConfigGroupSaver saver(_config,"Editor");
+
+ _config->writeEntry("AutoDiff",_diffEnabled);
+
+ dictBox->saveSettings( _project->config() );
+
+ _catalog->savePreferences();
+
+ _config->sync();
+ _project->config()->sync();
+
+ KBabelSettings::writeConfig();
+}
+
+void KBabelView::updateSettings()
+{
+ msgstrEdit->setFont(KBabelSettings::msgFont());
+ msgidLabel->setFont(KBabelSettings::msgFont());
+
+ msgidLabel->setDiffDisplayMode( KBabelSettings::diffAddUnderline()
+ ,KBabelSettings::diffDelStrikeOut());
+ msgidLabel->setDiffColors(KBabelSettings::diffAddColor(), KBabelSettings::diffDelColor());
+
+ if( _diffEnabled && !_catalog->currentURL().isEmpty() )
+ {
+ diffShowOrig ();
+ diff();
+ }
+
+ msgstrEdit->setBgColor(KBabelSettings::backgroundColor());
+ msgidLabel->setBgColor(KBabelSettings::backgroundColor());
+
+ msgstrEdit->setHighlightColors(KBabelSettings::quotedColor(),KBabelSettings::errorColor()
+ ,KBabelSettings::cformatColor(),KBabelSettings::accelColor(),KBabelSettings::tagColor());
+ msgidLabel->setHighlightColors(KBabelSettings::quotedColor(),KBabelSettings::errorColor()
+ ,KBabelSettings::cformatColor(),KBabelSettings::accelColor(),KBabelSettings::tagColor());
+
+ msgidLabel->setDiffDisplayMode( KBabelSettings::diffAddUnderline()
+ ,KBabelSettings::diffDelStrikeOut());
+ msgidLabel->setDiffColors(KBabelSettings::diffAddColor(), KBabelSettings::diffDelColor());
+
+ if(_fuzzyLed)
+ {
+ _fuzzyLed->setColor(KBabelSettings::ledColor());
+ }
+ if(_untransLed)
+ {
+ _untransLed->setColor(KBabelSettings::ledColor());
+ }
+ if(_errorLed)
+ {
+ _errorLed->setColor(KBabelSettings::ledColor());
+ }
+
+ disconnect(msgstrEdit,SIGNAL(textChanged())
+ ,this,SLOT(autoRemoveFuzzyStatus()));
+
+ if(KBabelSettings::autoUnsetFuzzy())
+ {
+ connect(msgstrEdit,SIGNAL(textChanged())
+ ,this,SLOT(autoRemoveFuzzyStatus()));
+ }
+
+ msgstrEdit->setCleverEditing(KBabelSettings::cleverEditing());
+
+ msgstrEdit->setHighlightBg(KBabelSettings::highlightBackground());
+ msgidLabel->setHighlightBg(KBabelSettings::highlightBackground());
+ msgstrEdit->setHighlightSyntax(KBabelSettings::highlightSyntax());
+ msgidLabel->setHighlightSyntax(KBabelSettings::highlightSyntax());
+
+ msgstrEdit->setQuotes(KBabelSettings::enableQuotes());
+ msgidLabel->setQuotes(KBabelSettings::enableQuotes());
+
+ msgstrEdit->setSpacePoints(KBabelSettings::whitespacePoints());
+ msgidLabel->setSpacePoints(KBabelSettings::whitespacePoints());
+
+ msgstrEdit->setFont(KBabelSettings::msgFont());
+ msgidLabel->setFont(KBabelSettings::msgFont());
+
+ msgstrEdit->setBgColor(KBabelSettings::backgroundColor());
+ msgidLabel->setBgColor(KBabelSettings::backgroundColor());
+
+ msgstrEdit->setHighlightColors(KBabelSettings::quotedColor(),KBabelSettings::errorColor()
+ ,KBabelSettings::cformatColor(),KBabelSettings::accelColor(),KBabelSettings::tagColor());
+ msgidLabel->setHighlightColors(KBabelSettings::quotedColor(),KBabelSettings::errorColor()
+ ,KBabelSettings::cformatColor(),KBabelSettings::accelColor(),KBabelSettings::tagColor());
+
+ msgidLabel->setDiffDisplayMode( KBabelSettings::diffAddUnderline()
+ ,KBabelSettings::diffDelStrikeOut());
+ msgidLabel->setDiffColors(KBabelSettings::diffAddColor(), KBabelSettings::diffDelColor());
+
+ // if errors should not use special color, reset the color of the text
+ if(! KBabelSettings::autoCheckColorError())
+ {
+ msgstrEdit->setCurrentColor( MsgMultiLineEdit::NormalColor);
+ }
+
+ if(_fuzzyLed)
+ {
+ _fuzzyLed->setColor(KBabelSettings::ledColor());
+ }
+ if(_untransLed)
+ {
+ _untransLed->setColor(KBabelSettings::ledColor());
+ }
+ if(_errorLed)
+ {
+ _errorLed->setColor(KBabelSettings::ledColor());
+ }
+
+ emit ledColorChanged(KBabelSettings::ledColor());
+
+ setupAutoCheckTools();
+
+ if( _catalog->numberOfEntries() > 0 )
+ autoCheck(false);
+
+}
+
+void KBabelView::setupAutoCheckTools()
+{
+ _autocheckTools.clear();
+
+ kdDebug () << "Autocheck tools: " << KBabelSettings::autoCheckTools().join(",") << endl;
+
+ if(!KBabelSettings::autoCheckTools().isEmpty() )
+ {
+ QValueList<KDataToolInfo> tools = ToolAction::validationTools();
+
+ QValueList<KDataToolInfo>::Iterator it;
+ for( it=tools.begin(); it!=tools.end() ; ++it )
+ {
+ if(KBabelSettings::autoCheckTools().contains((*it).service()->library()) )
+ {
+ // maybe we can reuse the tools
+ KDataTool* t = (*it).createTool();
+
+ if( t ) _autocheckTools.append( t );
+ }
+ }
+ }
+}
+
+void KBabelView::setRMBEditMenu(QPopupMenu* popup)
+{
+ msgidLabel->setContextMenu( popup );
+ msgstrEdit->setContextMenu( popup );
+ KContextMenuManager::insert(this,popup);
+}
+
+void KBabelView::setRMBSearchMenu(QPopupMenu* popup)
+{
+ dictBox->setRMBMenu(popup);
+}
+
+
+void KBabelView::saveView(KConfig *)
+{
+}
+
+void KBabelView::restoreView(KConfig *)
+{
+}
+
+void KBabelView::saveSession(KConfig* config)
+{
+ QString focus;
+ int line=0,col=0;
+ if(msgstrEdit->hasFocus())
+ {
+ focus="msgstr";
+ msgstrEdit->getCursorPosition(&line,&col);
+ }
+ else if(msgidLabel->hasFocus())
+ {
+ focus="msgid";
+ msgidLabel->getCursorPosition(&line,&col);
+ }
+ else if(dictBox->hasFocus())
+ {
+ focus="searchbox";
+ }
+
+ config->writeEntry("Focus",focus);
+ config->writeEntry("CursorLine",line);
+ config->writeEntry("CursorCol",col);
+ config->writeEntry("Index",_currentIndex);
+ config->writeEntry("PluralForm",_currentPos.form);
+
+ config->writePathEntry("URL",currentURL().url());
+
+ config->writeEntry("AutoDiff",_diffEnabled);
+
+ if( _spellcheckSettings.valid )
+ {
+ KConfigGroupSaver (config, "Spellcheck");
+ config->writeEntry("NoRootAffix",_spellcheckSettings.noRootAffix);
+ config->writeEntry("RunTogether",_spellcheckSettings.runTogether);
+ config->writeEntry("SpellEncoding",_spellcheckSettings.spellEncoding);
+ config->writeEntry("SpellClient",_spellcheckSettings.spellClient);
+ config->writeEntry("SpellDictionary",_spellcheckSettings.spellDict);
+ config->writeEntry("RememberIgnored",_spellcheckSettings.rememberIgnored);
+ config->writePathEntry("IgnoreURL",_spellcheckSettings.ignoreURL);
+ }
+
+ saveView(config);
+}
+
+void KBabelView::restoreSession(KConfig* config)
+{
+ QString url=config->readPathEntry("URL");
+
+ if(!url.isEmpty())
+ {
+ open(KURL( url ), QString::null, false,true);
+ }
+
+
+ _diffEnabled = config->readBoolEntry("AutoDiff", false);
+ emit signalDiffEnabled(_diffEnabled);
+
+ msgidLabel->setDiffDisplayMode( KBabelSettings::diffAddUnderline()
+ , KBabelSettings::diffDelStrikeOut() );
+ msgidLabel->setDiffColors( KBabelSettings::diffAddColor()
+ , KBabelSettings::diffDelColor() );
+
+ // go to last displayed entry
+ DocPosition pos;
+ pos.item=config->readNumEntry("Index");
+ pos.form=config->readNumEntry("PluralForm");
+ gotoEntry(pos);
+
+ QString focus=config->readEntry("Focus");
+ int line=config->readNumEntry("CursorLine");
+ int col=config->readNumEntry("CursorCol");
+ if(focus=="msgstr")
+ {
+ msgstrEdit->setFocus();
+ msgstrEdit->setCursorPosition(line,col);
+ }
+ else if(focus=="msgid")
+ {
+ msgidLabel->setFocus();
+ msgstrEdit->setCursorPosition(line,col);
+ }
+ else if(focus=="searchbox")
+ {
+ dictBox->setFocus();
+ }
+
+ restoreView(config);
+}
+
+void KBabelView::newFileOpened(bool readOnly)
+{
+ // disable editing for empty files
+ if(_catalog->numberOfEntries() == 0)
+ readOnly = true;
+
+ if(_gotoDialog)
+ {
+ _gotoDialog->setMax(_catalog->numberOfEntries());
+ }
+
+ dictBox->setDisabled(readOnly);
+ msgstrEdit->setReadOnly(readOnly);
+ msgstrEdit->setFocus();
+
+ QString caption=_catalog->package();
+ if(readOnly)
+ caption+=i18n(" [readonly]");
+ emit signalChangeCaption(caption);
+ emit signalNewFileOpened(_catalog->currentURL());
+
+ dictBox->setEditedPackage(_catalog->packageDir()+_catalog->packageName());
+ dictBox->setEditedFile(_catalog->currentURL().url());
+
+ _editingDocumentation = _catalog->isGeneratedFromDocbook();
+
+ _backHistory.clear();
+ emit signalBackHistory(false);
+ _forwardHistory.clear();
+ emit signalForwardHistory(false);
+
+ DocPosition pos;
+ pos.item=0;
+ pos.form=0;
+ _autoSearchTempDisabled=true;
+ gotoEntry(pos,false);
+ _autoSearchTempDisabled=false;
+
+ emit signalDisplayed(pos);
+
+ if(isActiveWindow() && KBabelSettings::autoSearch())
+ {
+ startSearch(true);
+ }
+}
+
+void KBabelView::open()
+{
+ open(KURL());
+}
+
+void KBabelView::open(const KURL& _url, const QString & package, bool checkIfModified, bool newView)
+{
+#if KDE_IS_VERSION( 3, 5, 0)
+ KURL url = KIO::NetAccess::mostLocalURL(_url,this);
+#else
+ KURL url = _url;
+#endif
+ url.cleanPath();
+
+ KURL cu = currentURL();
+ cu.cleanPath();
+ if(checkIfModified && !url.isEmpty() && cu==url)
+ {
+ KWin::activateWindow(topLevelWidget()->winId());
+ return;
+ }
+
+ stopSearch();
+
+ if(!checkIfModified || checkModified())
+ {
+ if(url.isEmpty())
+ {
+ QString filename;
+ if ((url = KFileDialog::getOpenURL(currentURL().url(), CatalogImportPlugin::availableImportMimeTypes().join(" ")
+ ,this)).isEmpty())
+ {
+ return;
+ }
+ }
+ // deactive editor
+ /*setEnabled(false);
+ setCursor(KCursor::waitCursor());*/
+
+ KBabelView *v = viewForURL(url,_project->filename());
+
+ if(v && v != this)
+ {
+ if( newView )
+ {
+ // unregister old catalog
+ _catalog->removeView(this);
+ if( !_catalog->hasView() )
+ delete _catalog;
+
+ // setup new one
+ _catalog = v->catalog();
+ _catalog->registerView(this);
+ newFileOpened(_catalog->isReadOnly());
+ return;
+ }
+ else {
+ KWin::activateWindow(v->topLevelWidget()->winId());
+ return;
+ }
+ }
+
+ ConversionStatus stat=_catalog->openURL(url, package);
+
+ switch(stat)
+ {
+ case OK:
+ {
+ break;
+ }
+ case RECOVERED_HEADER_ERROR: // Old name HEADER_ERROR
+ {
+ KMessageBox::sorry(this,
+ i18n("There was an error while reading the file header. "
+ "Please check the header." ));
+ editHeader();
+ break;
+ }
+ case PARSE_ERROR:
+ {
+ KMessageBox::error(this
+ ,i18n("Error while trying to read file:\n %1\n"
+ "Maybe it is not a valid PO file.").arg(url.prettyURL()));
+ break;
+ }
+ case NO_ENTRY_ERROR:
+ {
+ KMessageBox::error(this
+ ,i18n("Error while reading the file:\n %1\n"
+ "No entry found.").arg(url.prettyURL()));
+ break;
+ }
+ case RECOVERED_PARSE_ERROR:
+ {
+ QString msg=i18n(
+ "The file contained syntax errors and an attempt has been "
+ "made to recover it.\n"
+ "Please check the questionable entries by using "
+ "Go->Next error");
+ KMessageBox::sorry(this,msg);
+ emitEntryState();
+ break;
+ }
+ case NO_PERMISSIONS:
+ {
+ KMessageBox::error(this,i18n(
+ "You do not have permissions to read file:\n %1").arg(url.prettyURL()));
+ break;
+ }
+ case NO_FILE:
+ {
+ KMessageBox::error(this,i18n(
+ "You have not specified a valid file:\n %1").arg(url.prettyURL()));
+ break;
+ }
+ case NO_PLUGIN:
+ {
+ KMessageBox::error(this,i18n(
+ "KBabel cannot find a corresponding plugin for the MIME type of the file:\n %1").arg(url.prettyURL()));
+ break;
+ }
+ case UNSUPPORTED_TYPE:
+ {
+ KMessageBox::error(this,i18n(
+ "The import plugin cannot handle this type of the file:\n %1").arg(url.prettyURL()));
+ break;
+ }
+ case STOPPED:
+ break;
+ default:
+ {
+ KMessageBox::error(this,i18n(
+ "Error while trying to open file:\n %1").arg(url.prettyURL()));
+ break;
+ }
+
+ }
+ /*
+ //activate editor
+ setEnabled(true);
+ setCursor(KCursor::arrowCursor());*/
+
+ _autoSaveDelay = _catalog->saveSettings( ).autoSaveDelay;
+ if ( _autoSaveDelay ) {
+ if ( !autoSaveTimer ) {
+ autoSaveTimer = new QTimer( this, "AUTOSAVE TIMER" );
+ connect( autoSaveTimer, SIGNAL( timeout( ) ), this, SLOT( slotAutoSaveTimeout( ) ) );
+ }
+ autoSaveTimer->stop( );
+ autoSaveTimer->start( 1000 * 60 * _autoSaveDelay );
+ }
+
+ }
+}
+
+void KBabelView::revertToSaved()
+{
+ if(isModified())
+ {
+ // ### TODO: "Cancel" should be the default
+ if(KMessageBox::warningContinueCancel(this
+ ,i18n("All changes will be lost if the file "
+ "is reverted to its last saved state.")
+ ,i18n("Warning"),i18n("&Revert"))
+ == KMessageBox::Cancel)
+ {
+ return;
+ }
+ }
+
+ open(_catalog->currentURL(),QString::null,false);
+}
+
+void KBabelView::openTemplate(const KURL& openURL, const KURL& saveURL)
+{
+ stopSearch();
+
+ if(checkModified())
+ {
+ // deactive editor
+ /*setEnabled(false);
+ setCursor(KCursor::waitCursor());*/
+
+
+ ConversionStatus stat=_catalog->openURL(openURL,saveURL);
+
+ switch(stat)
+ {
+ case OK:
+ {
+ break;
+ }
+ case RECOVERED_HEADER_ERROR:
+ {
+ // For a template, recoverable errors are disqualifying
+ KMessageBox::sorry(this,
+ i18n("There was an error while reading the file header of file:\n %1")
+ .arg(openURL.prettyURL()));
+ break;
+ }
+ case PARSE_ERROR:
+ {
+ KMessageBox::error(this
+ ,i18n("Error while trying to read file:\n %1\n"
+ "Maybe it is not a valid PO file.").arg(openURL.prettyURL()));
+ break;
+ }
+ case NO_ENTRY_ERROR:
+ {
+ KMessageBox::error(this
+ ,i18n("Error while reading the file:\n %1\n"
+ "No entry found.").arg(openURL.prettyURL()));
+ break;
+ }
+ case RECOVERED_PARSE_ERROR:
+ {
+ // For a template, recoverable errors are disqualifying
+ KMessageBox::sorry(this,
+ i18n("Minor syntax errors were found while reading file:\n %1")
+ .arg(openURL.prettyURL()));
+ break;
+ }
+ case NO_PERMISSIONS:
+ {
+ KMessageBox::error(this,i18n("You do not have permissions to read file:\n %1").arg(openURL.prettyURL()));
+ break;
+ }
+ case NO_FILE:
+ {
+ KMessageBox::error(this,i18n("You have not specified a valid file:\n %1").arg(openURL.prettyURL()));
+ break;
+ }
+ case NO_PLUGIN:
+ {
+ KMessageBox::error(this,i18n(
+ "KBabel cannot find a corresponding plugin for the MIME type of the file:\n %1").arg(openURL.prettyURL()));
+ break;
+ }
+ case UNSUPPORTED_TYPE:
+ {
+ KMessageBox::error(this,i18n(
+ "The import plugin cannot handle this type of the file:\n %1").arg(openURL.prettyURL()));
+ break;
+ }
+ case STOPPED:
+ break;
+ default:
+ {
+ KMessageBox::error(this,i18n("Error while trying to open file:\n %1").arg(openURL.prettyURL()));
+ break;
+ }
+
+ }
+
+ /*
+ //activate editor
+ setEnabled(true);
+
+ setCursor(KCursor::arrowCursor());*/
+ }
+}
+
+bool KBabelView::saveFile(bool syntaxCheck)
+{
+ if(_catalog->isReadOnly())
+ {
+ return saveFileAs();
+ }
+ else
+ {
+ ConversionStatus stat=_catalog->saveFile();
+
+ int whatToDo = -1;
+
+ switch(stat)
+ {
+ case OK:
+ {
+ informDictionary();
+ if(syntaxCheck && _catalog->saveSettings().autoSyntaxCheck )
+ return checkSyntax(true,false);
+ else
+ return true;
+ }
+ case NO_PERMISSIONS:
+ {
+ whatToDo=KMessageBox::warningContinueCancel(this,
+ i18n("You do not have permission to write to file:\n%1\n"
+ "Do you want to save to another file or cancel?").arg(_catalog->currentURL().prettyURL()),
+ i18n("Error"),KStdGuiItem::save());
+ break;
+ }
+ case NO_PLUGIN:
+ {
+ KMessageBox::error(this,i18n(
+ "KBabel cannot find a corresponding plugin for the MIME type of file:\n %1").arg(_catalog->currentURL().prettyURL()));
+ break;
+ }
+ case UNSUPPORTED_TYPE:
+ {
+ KMessageBox::error(this,i18n(
+ "The export plugin cannot handle this type of file:\n %1").arg(_catalog->currentURL().prettyURL()));
+ break;
+ }
+ case BUSY:
+ {
+ KMessageBox::error(this,i18n(
+ "KBabel has not finished the last operation yet.\n"
+ "Please wait."));
+ break;
+ }
+ case STOPPED:
+ break;
+ default:
+ {
+ whatToDo=KMessageBox::warningContinueCancel(this,
+ i18n("An error occurred while trying to write to file:\n%1\n"
+ "Do you want to save to another file or cancel?").arg(_catalog->currentURL().prettyURL()),
+ i18n("Error"),KStdGuiItem::save());
+ break;
+ }
+ }
+ switch(whatToDo)
+ {
+ case KMessageBox::Continue:
+ return saveFileAs();
+ default:
+ return false;
+
+ }
+
+ }
+
+ return true;
+}
+
+bool KBabelView::saveFileAs(KURL url, bool syntaxCheck)
+{
+ bool newName=false;
+ if(url.isEmpty())
+ {
+ if((url = KFileDialog::getSaveURL(currentURL().url(), CatalogExportPlugin::availableExportMimeTypes().join(" "),this)).isEmpty())
+ {
+ return false;
+ }
+ newName=true;
+ }
+
+ if (KIO::NetAccess::exists(url, false, this))
+ {
+ if(KMessageBox::warningContinueCancel(this,QString("<qt>%1</qt>").arg(i18n("The file %1 already exists. "
+ "Do you want to overwrite it?").arg(url.prettyURL())),i18n("Warning"),i18n("&Overwrite"))==KMessageBox::Cancel)
+ {
+ return false;
+ }
+
+ }
+
+ bool wasReadOnly=_catalog->isReadOnly();
+
+ ConversionStatus stat=_catalog->saveFileAs(url,true);
+
+
+ // if the file was not saved sucessfully ask for saving to another file
+ if(stat!=OK)
+ {
+ bool cancelLoop=false; // flag, if the saving loop should be canceled
+ do
+ {
+ // select the right error message
+ QString message;
+ switch(stat)
+ {
+ case NO_PERMISSIONS:
+ {
+ message=i18n("You do not have permission to write to file:\n%1\n"
+ "Do you want to save to another file or cancel?").arg(url.prettyURL());
+ break;
+ }
+ case NO_FILE:
+ {
+ message=i18n("You have specified a folder:\n%1\n"
+ "Do you want to save to another file or cancel?").arg(url.prettyURL());
+ break;
+ }
+ case NO_PLUGIN:
+ {
+ message=i18n("KBabel cannot find a corresponding plugin for the MIME type of the file:\n %1").arg(url.prettyURL());
+ break;
+ }
+ case UNSUPPORTED_TYPE:
+ {
+ message=i18n(
+ "The export plugin cannot handle this type of the file:\n %1").arg(url.prettyURL());
+ break;
+ }
+ default:
+ {
+ message=i18n("An error occurred while trying to write to file:\n%1\n"
+ "Do you want to save to another file or cancel?").arg(url.prettyURL());
+ break;
+ }
+ }
+
+ // now ask, if the user wants to save to another file or cancel
+ switch(KMessageBox::warningContinueCancel(this,message,i18n("Error"),KStdGuiItem::save()))
+ {
+ // save to another file
+ case KMessageBox::Continue:
+ {
+ // ask for new filename
+ if ((url = KFileDialog::getSaveURL(currentURL().url(), CatalogExportPlugin::availableExportMimeTypes().join(" "), this)).isEmpty())
+ {
+ // if no filename was given cancel all
+ return false;
+ }
+
+ if (KIO::NetAccess::exists(url, false, this))
+ {
+ if(KMessageBox::warningContinueCancel(this,i18n("The file %1 already exists.\n"
+ "Do you want to overwrite it?").arg(url.prettyURL()),i18n("Warning"),i18n("&Overwrite"))==KMessageBox::Continue)
+ {
+ stat=_catalog->saveFileAs(url);
+ if(stat!=OK)
+ cancelLoop=false;
+ else
+ cancelLoop=true;
+ }
+ }
+ else
+ {
+ stat=_catalog->saveFileAs(url);
+ if(stat!=OK)
+ cancelLoop=false;
+ else
+ cancelLoop=true;
+ }
+ break;
+ }
+ default: // the user do not want to save to another file
+ return false;
+ }
+ }
+ while(!cancelLoop);
+ }
+
+
+ if(wasReadOnly)
+ {
+ msgstrEdit->setReadOnly(false);
+ }
+
+ emit signalChangeCaption(_catalog->package());
+
+ if(newName)
+ {
+ dictBox->setEditedPackage(_catalog->packageName());
+ dictBox->setEditedFile(_catalog->currentURL().url());
+ }
+
+ // after save put current edit into dictionary as well
+ informDictionary();
+
+ if(syntaxCheck && _catalog->saveSettings().autoSyntaxCheck)
+ return checkSyntax(true,false);
+ else
+ return true;
+}
+
+bool KBabelView::saveFileSpecial()
+{
+ QString tmpname;
+ bool result = false;
+
+ {
+ // generate temporary name
+ KTempFile tmp;
+ tmp.setAutoDelete (true);
+ tmpname = tmp.name ();
+ }
+
+ {
+ // make sure the project is freed (pointer going out of scope)
+ KBabel::Project::Ptr project = KBabel::ProjectManager::open (tmpname);
+
+ project->setSettings( _catalog->saveSettings() );
+ KConfigDialog *_prefDialog = new KConfigDialog(this, "project dialog", project->settings(),
+ KDialogBase::IconList, KDialogBase::Cancel|KDialogBase::Ok|KDialogBase::Help);
+
+ _prefDialog->setCaption( i18n("Special Save Settings") );
+ _prefDialog->setHelp("preferences_save");
+
+ SavePreferences* _prefWidget = new SavePreferences(_prefDialog);
+ _prefWidget->setAutoSaveVisible(false);
+ _prefDialog->addPage(_prefWidget, i18n("title of page in preferences dialog","Save")
+ , "filesave"
+ , i18n("Options for File Saving"));
+
+ if( _prefDialog->exec() == QDialog::Accepted )
+ {
+ SaveSettings settings = project->saveSettings();
+ SaveSettings originalSettings = _catalog->saveSettings();
+ _catalog->setSettings(settings);
+ result = saveFileAs();
+
+ _catalog->setSettings(originalSettings);
+ }
+ }
+
+ QFile::remove( tmpname );
+
+ return result;
+}
+
+bool KBabelView::checkSyntax()
+{
+ return checkSyntax(false,false);
+}
+
+bool KBabelView::checkSyntax(bool msgOnlyAtError,bool question)
+{
+ if(currentURL().isEmpty())
+ return false;
+
+ bool returnCode=true;
+ QString output;
+
+ Msgfmt::Status result=_catalog->checkSyntax( output );
+
+ const QStringList outputLines = QStringList::split("\n",output);
+
+ switch(result)
+ {
+ case Msgfmt::Ok:
+ {
+ if(!msgOnlyAtError)
+ {
+ KMessageBox::informationList( this, i18n("The file is syntactically correct.\n\n"
+ "Output of \"msgfmt --statistics\":\n"), outputLines );
+ }
+ returnCode=true;
+ break;
+ }
+ case Msgfmt::Unsupported:
+ {
+ if(!msgOnlyAtError)
+ {
+ KMessageBox::sorry(this
+ ,i18n("You can use gettext tools only for checking PO files."));
+ }
+ returnCode=true;
+ break;
+ }
+ case Msgfmt::HeaderError:
+ case Msgfmt::SyntaxError:
+ {
+ QString msg = ( result == Msgfmt::SyntaxError )
+ ? i18n("msgfmt detected a syntax error.\n")
+ : i18n("msgfmt detected a header syntax error.\n");
+
+ if(question)
+ {
+ msg += i18n("\nDo you want to continue or cancel and edit the file again?");
+ msg += "\n\n";
+ msg += i18n("Output of \"msgfmt --statistics\":\n");
+ switch( KMessageBox::warningContinueCancelList( this, msg,
+ outputLines, i18n("Warning"), KStdGuiItem::cont()) )
+ {
+ case KMessageBox::Continue:
+ returnCode=true;
+ break;
+ default:
+ returnCode=false;
+ }
+ }
+ else
+ {
+#if KDE_IS_VERSION ( 3, 4, 0 )
+ msg += "\n";
+ msg += i18n("Please edit the file again.");
+ msg += "\n\n";
+ msg += i18n("Output of \"msgfmt --statistics\":\n");
+ KMessageBox::errorList( this, msg, outputLines );
+#else
+ msg += i18n("Output of \"msgfmt --statistics\":\n");
+ msg += output;
+ msg += "\n\n";
+ msg += i18n("Please edit the file again.");
+ KMessageBox::error( this, msg );
+#endif
+ returnCode=false;
+ }
+ break;
+ }
+ case Msgfmt::NoExecutable:
+ case Msgfmt::Error:
+ {
+ QString msg = i18n("While trying to check syntax with msgfmt an error occurred.\n"
+ "Please make sure that you have installed\n"
+ "the GNU gettext package properly.");
+ if(question)
+ {
+ msg += i18n("\nDo you want to continue or cancel and edit the file again?");
+ switch( KMessageBox::warningContinueCancelList( this, msg,
+ outputLines, i18n("Warning"), KStdGuiItem::cont() ))
+ {
+ case KMessageBox::Continue:
+ returnCode=true;
+ break;
+ default:
+ returnCode=false;
+ }
+ }
+ else
+ {
+#if KDE_IS_VERSION ( 3, 4, 0 )
+ msg += "\n";
+ msg += i18n("Please edit the file again.");
+ KMessageBox::errorList( this, msg, outputLines );
+#else
+ msg += output;
+ msg += "\n\n";
+ msg += i18n("Please edit the file again.");
+ KMessageBox::error( this, msg );
+#endif
+ returnCode=false;
+ }
+
+ break;
+ }
+ }
+
+ emitEntryState();
+
+ return returnCode;
+}
+
+bool KBabelView::checkAll()
+{
+ if(currentURL().isEmpty())
+ return false;
+
+ bool a,badresult=false;
+
+ QValueList<KDataToolInfo> tools = ToolAction::validationTools();
+
+ QValueList<KDataToolInfo>::ConstIterator entry = tools.begin();
+ for( ; entry != tools.end(); ++entry )
+ {
+ KDataTool* tool = (*entry).createTool();
+ if( tool )
+ {
+ a = _catalog->checkUsingTool(tool,entry==tools.begin());
+ badresult = badresult || !a;
+ delete tool;
+ }
+ }
+
+ QString output;
+
+ a = (_catalog->checkSyntax(output, false)!=Msgfmt::Ok);
+ badresult=badresult||a;
+
+ emitEntryState();
+
+ if(!badresult)
+ {
+ KMessageBox::information(this
+ ,i18n("No mismatch has been found.")
+ , i18n("Title in Dialog: Perform all checks","Perform All Checks"));
+ }
+ else
+ {
+ int index=0;
+ DocPosition pos;
+ if(!_catalog->hasError(0,pos))
+ index = _catalog->nextError(0, pos);
+ if(index>=0)
+ {
+ gotoEntry(pos);
+ }
+
+ KMessageBox::error(this
+ ,i18n("Some mismatches have been found.\n"
+ "Please check the questionable entries by using "
+ "Go->Next error")
+ , i18n("Title in Dialog: Perform all checks","Perform All Checks"));
+
+ }
+
+ return !badresult;
+}
+
+
+
+bool KBabelView::checkModified()
+{
+ bool flag=true;
+
+ if(isModified())
+ {
+ switch(KMessageBox::warningYesNoCancel(this,
+ i18n("The document contains unsaved changes.\n"
+ "Do you want to save your changes or discard them?"),i18n("Warning"),
+ KStdGuiItem::save(),KStdGuiItem::discard()))
+ {
+ case KMessageBox::Yes:
+ {
+ flag = saveFile(false);
+ if(flag && _catalog->saveSettings().autoSyntaxCheck)
+ {
+ flag = checkSyntax(true,true);
+ }
+ break;
+ }
+ case KMessageBox::No:
+ flag = true;
+ break;
+ default: // canceled
+ flag = false;
+ break;
+ }
+ }
+
+ return flag;
+}
+
+void KBabelView::updateEditor(int form, bool delay)
+{
+ msgstrEdit->blockSignals(true);
+
+ if(KBabelSettings::autoUnsetFuzzy() && !msgstrEdit->isModified())
+ {
+ disconnect(msgstrEdit,SIGNAL(textChanged()),this,SLOT(autoRemoveFuzzyStatus()));
+ }
+
+ msgidLabel->setText(_catalog->msgid(_currentIndex), _catalog->msgctxt(_currentIndex));
+ msgidLabel->repaint();
+
+ msgstrEdit->setText(_catalog->msgstr(_currentIndex));
+ msgstrEdit->showForm( form );
+ msgstrEdit->repaint();
+ m_cataloglistview->setSelectedItem(_currentIndex);
+
+ if(KBabelSettings::autoUnsetFuzzy() && _catalog->isFuzzy(_currentIndex))
+ {
+ connect(msgstrEdit,SIGNAL(textChanged()),this,SLOT(autoRemoveFuzzyStatus()));
+ }
+
+ msgstrEdit->blockSignals(false);
+
+ autoCheck(false);
+
+ // no need to display diff if this message wasn't translated
+ if(_diffEnabled && !(_catalog->isUntranslated(_currentIndex)))
+ {
+ autoDiff();
+ }
+
+ if(isActiveWindow() && KBabelSettings::autoSearch()
+ && !_autoSearchTempDisabled)
+ {
+ if (delay)
+ {
+ QTimer::singleShot(0, this, SLOT (startSearch()));
+ }
+ else
+ {
+ startSearch();
+ }
+ }
+
+ msgstrEdit->setFocus();
+ msgstrEdit->setModified(false);
+}
+
+
+void KBabelView::undo()
+{
+ if(!_catalog->isUndoAvailable())
+ return;
+
+ int newIndex=_catalog->undo();
+
+ if(newIndex != (int)_currentIndex)
+ {
+ DocPosition pos;
+ pos.item=newIndex;
+ pos.form=0;
+ gotoEntry(pos);
+ }
+}
+
+void KBabelView::redo()
+{
+ if(!_catalog->isRedoAvailable())
+ return;
+
+ int newIndex=_catalog->redo();
+
+ if(newIndex != (int)_currentIndex)
+ {
+ DocPosition pos;
+ pos.item=newIndex;
+ pos.form=0;
+ gotoEntry(pos);
+ }
+}
+
+void KBabelView::textCut()
+{
+ if(msgstrEdit->hasFocus())
+ {
+ msgstrEdit->cut();
+ }
+}
+
+void KBabelView::textCopy()
+{
+ if(msgstrEdit->hasSelectedText())
+ {
+ msgstrEdit->copy();
+ }
+ else if(msgidLabel->hasSelectedText())
+ {
+ msgidLabel->copy();
+ }
+ else if(dictBox->isVisible() && dictBox->hasSelectedText())
+ {
+ dictBox->copy();
+ }
+}
+
+void KBabelView::textPaste()
+{
+ msgstrEdit->paste();
+}
+
+
+bool KBabelView::findNext()
+{
+ if(!_findDialog)
+ return false;
+
+ if( !_redirectedBackSearch && _findDialog->findOpts().backwards )
+ {
+ _redirectedBackSearch = true;
+ bool res = findPrev();
+ _redirectedBackSearch = false;
+ return res;
+ }
+
+ DocPosition pos;
+ pos.item=_currentIndex;
+ pos.form=0;
+
+ if( m_commentview->hasFocus() ) {
+ pos.part = Comment;
+ pos.offset = m_commentview->currentIndex();
+ }
+ else
+ if(msgidLabel->hasFocus() ) {
+ pos.part = Msgid;
+ pos.offset = msgidLabel->currentIndex();
+ }
+ else {
+ pos.part = Msgstr;
+ pos.offset = msgstrEdit->currentIndex();
+ pos.form = msgstrEdit->currentForm();
+ }
+
+ _findStartPos=pos;
+ _findBreakAtEnd=false;
+
+ return findNext_internal(pos);
+}
+
+bool KBabelView::findPrev()
+{
+ if(!_findDialog)
+ return false;
+
+ if( !_redirectedBackSearch && _findDialog->findOpts().backwards )
+ {
+ _redirectedBackSearch = true;
+ bool res = findNext();
+ _redirectedBackSearch = false;
+ return res;
+ }
+
+ DocPosition pos;
+ pos.item=_currentIndex;
+
+ if( m_commentview->hasFocus()) {
+ pos.part = Comment;
+ pos.offset = m_commentview->currentIndex();
+ }
+ else
+ if(msgidLabel->hasFocus() ) {
+ pos.part = Msgid;
+ pos.offset = msgidLabel->currentIndex();
+ }
+ else {
+ pos.part = Msgstr;
+ pos.offset = msgstrEdit->currentIndex();
+ pos.form = msgstrEdit->currentForm();
+ }
+
+ _findStartPos=pos;
+ _findBreakAtEnd=false;
+
+ return findPrev_internal(pos);
+}
+
+
+bool KBabelView::findNext_internal(DocPosition& pos, bool forReplace, bool gui)
+{
+ FindOptions opts;
+ if(forReplace)
+ opts = _replaceDialog->replaceOpts();
+ else
+ opts = _findDialog->findOpts();
+ int len=0;
+ deselectAll();
+
+ bool success=false;
+ if( !opts.askFile ) // for find in all files ignore return to the beginning
+ if(!_findBreakAtEnd && !(success=_catalog->findNext(&opts,pos,len))) {
+ int r;
+ if(forReplace) {
+ _replaceWasAtEnd=true;
+ _findBreakAtEnd=true;
+ if(gui) {
+ r = KMessageBox::questionYesNo(this,
+ i18n("<qt>%n replacement made.<br>End of document reached.<br>Continue from the beginning?</qt>",
+ "<qt>%n replacements made.<br>End of document reached.<br>Continue from the beginning?</qt>",
+ _replacesTotal), QString::null, KStdGuiItem::cont(), KStdGuiItem::cancel());
+ }
+ else {
+ r = KMessageBox::Yes;
+ }
+ }
+ else {
+ r = KMessageBox::questionYesNo(this,i18n("End of document reached.\n"
+ "Continue from the beginning?"), QString::null, KStdGuiItem::cont(), KStdGuiItem::cancel());
+ }
+ if(r == KMessageBox::Yes) {
+ if(opts.inMsgid && !forReplace)
+ pos.part = Msgid;
+ else if(opts.inComment)
+ pos.part = Comment;
+ else
+ pos.part = Msgstr;
+
+ pos.item = 0;
+ pos.offset = 0;
+ pos.form = 0;
+
+ }
+ else
+ return false;
+ }
+
+
+ if(!success && !_catalog->findNext(&opts,pos,len)) { // reached end the second time
+ if( !opts.askFile )
+ {
+ if(forReplace) {
+ KMessageBox::information(this,i18n("%n replacement made","%n replacements made",_replacesTotal));
+ }
+ else {
+ KMessageBox::information(this,i18n("Search string not found."));
+ }
+ return false;
+ }
+ else
+ {
+ if( opts.askForNextFile )
+ {
+ int r = KMessageBox::questionYesNo(this,i18n("End of document reached.\n"
+ "Continue in the next file?"), QString::null, KStdGuiItem::cont(), KStdGuiItem::cancel());
+ if( r != KMessageBox::Yes ) return false;
+
+ }
+ if( isModified() && !opts.askForSave ) saveFile();
+ DCOPClient *client = kapp->dcopClient();
+ QByteArray data, replyData;
+ QCString replyType;
+ bool morefiles = false; // more files to lookup in
+ if( !client->call( _fileSource,"CatalogManagerIFace",
+ "findNextFile()", data, replyType, replyData) ) kdDebug(KBABEL) << "unable to call, reply type is " << replyType << endl;
+ else if( replyType == "QCString" )
+ {
+ QDataStream rep( replyData, IO_ReadOnly);
+ QCString f;
+ rep >> f;
+ QString foundFile = QString::fromUtf8(f);
+ morefiles = !f.isEmpty() && !f.isNull();
+ if( morefiles )
+ {
+ emit open( KURL(foundFile) );
+ pos.item = 0;
+ pos.part = Msgid;
+ pos.offset = 0;
+ _catalog->findNext(&opts,pos,len);
+ } else {
+ if( f.isNull() ) // is there possibility to get a new file?
+ {
+ // no, this is the end finally
+ if( forReplace )
+ KMessageBox::information(this,i18n("%n replacement made","%n replacements made",_replacesTotal));
+ else
+ KMessageBox::information(this,i18n("Search string not found."));
+ return false;
+ }
+ else
+ {
+ // there can be a new file, let user know
+ showTryLaterMessageBox();
+ if( forReplace ) return true; // let replace dialog stay
+ else return false;
+ }
+ }
+ } else {
+ KMessageBox::error(this,i18n("DCOP communication with Catalog Manager failed."));
+ return false;
+ }
+ }
+ }
+ if(gui) {
+ if( _currentIndex != pos.item
+ || (pos.part==Msgstr && msgstrEdit->currentForm() != pos.form) )
+ {
+ gotoEntry(pos);
+ }
+
+ int line,col,endline,endcol;
+ switch(pos.part) {
+ case Msgid:
+ msgidLabel->selectAll(false);
+ msgidLabel->setFocus();
+ msgidLabel->offset2Pos(pos.offset,line,col);
+ msgidLabel->offset2Pos(pos.offset+len,endline,endcol);
+
+ msgidLabel->setSelection(line,col,endline,endcol);
+ msgidLabel->setCursorPosition(endline,endcol);
+
+ _lastFoundString=msgidLabel->selectedText();
+ break;
+ case Msgstr:
+ msgstrEdit->selectAll(false);
+ msgstrEdit->setFocus();
+ msgstrEdit->offset2Pos(pos.offset,line,col);
+ msgstrEdit->offset2Pos(pos.offset+len,endline,endcol);
+
+ msgstrEdit->setSelection(line,col,endline,endcol);
+ msgstrEdit->setCursorPosition(endline,endcol);
+
+ _lastFoundString=msgstrEdit->selectedText();
+ break;
+ case Comment:
+ {
+ m_mainwindow->makeWidgetDockVisible (m_commentview);
+ _lastFoundString= m_commentview->selectText (pos.offset, pos.offset+len);
+ break;
+ }
+ case UndefPart:
+ break;
+ }
+ }
+
+ if(forReplace) {
+ kdDebug(KBABEL) << "This is forReplace" << endl;
+ _replaceLen=len;
+
+ bool finished=false;
+ // check if we had reached the beginning before and now are before our starting position
+ if(_replaceWasAtEnd) {
+ if( pos.item > _findStartPos.item ) {
+ finished=true;
+ }
+ else if(pos.item == _findStartPos.item) {
+ if(pos.part==Msgstr && !opts.inComment && pos.offset >= _findStartPos.offset+_replaceExtraOffset)
+ finished=true;
+ else if(pos.part==Comment && pos.offset >= _findStartPos.offset+_replaceExtraOffset)
+ finished=true;
+ }
+ }
+
+ if(finished) {
+ KMessageBox::information(this,i18n("%n replacement made","%n replacements made",_replacesTotal));
+ return false;
+ }
+
+ }
+
+ return true;
+}
+
+bool KBabelView::findPrev_internal(DocPosition& pos, bool forReplace, bool gui)
+{
+ FindOptions opts;
+ if(forReplace)
+ opts = _replaceDialog->replaceOpts();
+ else
+ opts = _findDialog->findOpts();
+
+ int len=0;
+
+ deselectAll();
+ bool success=false;
+ if(!_findBreakAtEnd && !(success=_catalog->findPrev(&opts,pos,len))) {
+ int r;
+
+ if(forReplace) {
+ _replaceWasAtEnd=true;
+ _findBreakAtEnd=true;
+ if(gui) {
+ r = KMessageBox::questionYesNo(this,
+ i18n("<qt>%n replacement made.<br>Beginning of document reached.<br>Continue from the end?</qt>",
+ "<qt>%n replacements made.<br>Beginning of document reached.<br>Continue from the end?</qt>",
+ _replacesTotal),QString::null, KStdGuiItem::cont(), KStdGuiItem::cancel());
+ }
+ else {
+ r = KMessageBox::Yes;
+ }
+
+ }
+ else {
+ r = KMessageBox::questionYesNo(this,i18n("Beginning of document reached.\n"
+ "Continue from the end?"), QString::null, KStdGuiItem::cont(), KStdGuiItem::cancel());
+ }
+ if(r == KMessageBox::Yes) {
+ pos.item = _catalog->numberOfEntries()-1;
+
+ if(opts.inComment) {
+ pos.part = Comment;
+ pos.offset = _catalog->comment(pos.item).length();
+ }
+ else if(opts.inMsgstr || forReplace) {
+ pos.part = Msgstr;
+ if( _catalog->msgstr(pos.item).empty() ) pos.offset=0;
+ else pos.offset = _catalog->msgstr(pos.item).last().length();
+ pos.form = _catalog->msgstr(pos.item).count()-1;
+ }
+ else {
+ pos.part = Msgid;
+ //FIXME: we should search in msgid plural forms
+ pos.offset = _catalog->msgid(pos.item).first().length();
+ }
+ }
+ else
+ return false;
+ }
+
+ // start at the end
+ if(!success && !_catalog->findPrev(&opts,pos,len)) {
+ if(forReplace) {
+ KMessageBox::information(this,i18n("%n replacement made","%n replacements made",_replacesTotal));
+ }
+ else {
+ KMessageBox::information(this,i18n("Search string not found."));
+ }
+ return false;
+ }
+ else if(gui) {
+ if(_currentIndex != pos.item
+ || (pos.part==Msgstr && msgstrEdit->currentForm() != pos.form) )
+ gotoEntry(pos);
+
+ int line,col,endline,endcol;
+ switch(pos.part) {
+ case Msgid:
+ msgidLabel->selectAll(false);
+ msgidLabel->setFocus();
+ msgidLabel->offset2Pos(pos.offset+len,line,col);
+ msgidLabel->offset2Pos(pos.offset,endline,endcol);
+
+ msgidLabel->setSelection(line,col,endline,endcol);
+ msgidLabel->setCursorPosition(endline,endcol);
+
+ _lastFoundString=msgidLabel->selectedText();
+ break;
+ case Msgstr:
+ msgstrEdit->selectAll(false);
+ msgstrEdit->setFocus();
+ msgstrEdit->offset2Pos(pos.offset+len,line,col);
+ msgstrEdit->offset2Pos(pos.offset,endline,endcol);
+
+ msgstrEdit->setSelection(line,col,endline,endcol);
+ msgstrEdit->setCursorPosition(endline,endcol);
+
+ _lastFoundString=msgstrEdit->selectedText();
+ break;
+ case Comment:
+ m_mainwindow->makeWidgetDockVisible (m_commentview);
+ _lastFoundString=m_commentview->
+ selectText(pos.offset, pos.offset+len);
+ break;
+ case UndefPart:
+ break;
+ }
+ }
+
+ if(forReplace) {
+ _replaceLen=len;
+
+ bool finished=false;
+ // check if we had reached the beginning before and now are before our starting position
+ if(_replaceWasAtEnd) {
+ if( pos.item < _findStartPos.item ) {
+ finished=true;
+ }
+ else if(pos.item == _findStartPos.item) {
+ if(pos.part==Comment && !opts.inMsgstr && pos.offset < _findStartPos.offset+_replaceExtraOffset)
+ finished=true;
+ else if(pos.part==Msgstr && pos.offset < _findStartPos.offset+_replaceExtraOffset)
+ finished=true;
+ }
+ }
+
+ if(finished) {
+ KMessageBox::information(this,i18n("%n replacement made","%n replacements made",_replacesTotal));
+ return false;
+ }
+
+ }
+
+
+ return true;
+}
+
+
+void KBabelView::find()
+{
+ Part hadFocus;
+ if(msgidLabel->hasFocus())
+ hadFocus=Msgid;
+ else if(m_commentview->hasFocus())
+ hadFocus=Comment;
+ else
+ hadFocus=Msgstr;
+
+ if( !_findDialog ) {
+ _findDialog = new FindDialog(false,this);
+ }
+
+ QString marked;
+ if(msgstrEdit->hasFocus()) {
+ marked=msgstrEdit->selectedText();
+ msgstrEdit->selectAll(false);
+ }
+ else if(m_commentview->hasFocus()) {
+ marked=m_commentview->selectedText();
+ m_commentview->textDeselectAll();
+ }
+ else if(msgidLabel->hasFocus()) {
+ marked=msgidLabel->selectedText();
+ msgidLabel->selectAll(false);
+ }
+
+
+ if(marked==_lastFoundString)
+ marked="";
+
+ if( _findDialog->exec(marked) == QDialog::Accepted ) {
+ DocPosition pos;
+ FindOptions opts=_findDialog->findOpts();
+ opts.askFile = false; // do not search in more files
+ _findDialog->setFindOpts(opts);
+
+ if(opts.fromCursor) {
+ _findBreakAtEnd=false;
+ pos.item=_currentIndex;
+
+ if(hadFocus == Comment && opts.inComment) {
+ pos.part = Comment;
+ pos.offset = m_commentview->currentIndex();
+ }
+ else
+ if( hadFocus == Msgid && opts.inMsgid) {
+ pos.part = Msgid;
+ pos.offset = msgidLabel->currentIndex();
+ }
+ else {
+ pos.part = Msgstr;
+ pos.offset = msgstrEdit->currentIndex();
+ }
+ }
+ else {
+ _findBreakAtEnd=true;
+
+ if(opts.backwards) {
+ pos.item=_catalog->numberOfEntries();
+ if(opts.inComment)
+ pos.part=Comment;
+ else if(opts.inMsgstr)
+ pos.part=Msgstr;
+ else
+ pos.part=Msgid;
+
+ pos.offset=1000; // set to a high number
+ }
+ else {
+ pos.item=0;
+ if(opts.inMsgid)
+ pos.part=Msgid;
+ else if(opts.inMsgstr)
+ pos.part=Msgstr;
+ else
+ pos.part=Comment;
+
+ pos.offset=0;
+ }
+ }
+
+ if( opts.backwards ) {
+ _findStartPos=pos;
+ findPrev_internal(pos);
+ }
+ else {
+ _findStartPos=pos;
+ findNext_internal(pos);
+ }
+ }
+}
+
+void KBabelView::replace()
+{
+ _replacesTotal=0;
+ _replaceLen=0;
+ _replaceWasAtEnd=false;
+ _replaceExtraOffset=0;
+
+ Part hadFocus;
+ if(msgidLabel->hasFocus())
+ hadFocus=Msgid;
+ else if(m_commentview->hasFocus())
+ hadFocus=Comment;
+ else
+ hadFocus=Msgstr;
+
+ if( !_replaceDialog ) {
+ _replaceDialog = new FindDialog(true,this);
+ }
+ QString marked;
+ if(msgstrEdit->hasFocus()) {
+ marked=msgstrEdit->selectedText();
+ msgstrEdit->selectAll(false);
+ }
+ else if(m_commentview->hasFocus()) {
+ marked=m_commentview->selectedText();
+ m_commentview->textDeselectAll();
+ }
+ else if(msgidLabel->hasFocus()) {
+ marked=msgidLabel->selectedText();
+ msgidLabel->selectAll(false);
+ }
+
+ if(marked==_lastFoundString)
+ marked="";
+
+ if( _replaceDialog->exec(marked) == QDialog::Accepted ) {
+ KBabel::ReplaceOptions opts=_replaceDialog->replaceOpts();
+ if(opts.fromCursor) {
+ _findBreakAtEnd=false;
+ _replacePos.item=_currentIndex;
+
+ if(hadFocus==Comment && opts.inComment) {
+ _replacePos.part = Comment;
+ _replacePos.offset = m_commentview->currentIndex();
+ }
+ else
+ {
+ _replacePos.part = Msgstr;
+ _replacePos.offset = msgstrEdit->currentIndex();
+ }
+ }
+ else {
+ _findBreakAtEnd=true;
+ if(opts.backwards) {
+ _replacePos.item=_catalog->numberOfEntries();
+ if(opts.inComment)
+ _replacePos.part=Comment;
+ else
+ _replacePos.part=Msgstr;
+
+ _replacePos.offset=1000; // set to a high number
+ }
+ else {
+ _replacePos.item=0;
+ if(opts.inMsgstr)
+ _replacePos.part=Msgstr;
+ else
+ _replacePos.part=Comment;
+
+ _replacePos.offset=0;
+ }
+ }
+
+ // do not ask for next file from catalog manager
+ opts.askFile = false;
+ _replaceDialog->setReplaceOpts(opts);
+
+ bool success;
+
+ if( opts.backwards ) {
+ _findStartPos=_replacePos;
+ success = findPrev_internal(_replacePos,true,opts.ask);
+ }
+ else {
+ _findStartPos=_replacePos;
+ success = findNext_internal(_replacePos,true,opts.ask);
+ }
+
+
+
+ if(success) {
+ if(!_replaceAskDialog) {
+ _replaceAskDialog = new ReplaceDialog(this);
+ connect(_replaceAskDialog,SIGNAL(replace()),this,SLOT(replaceNext()));
+ connect(_replaceAskDialog,SIGNAL(next()),this,SLOT(findNextReplace()));
+ connect(_replaceAskDialog,SIGNAL(replaceAll()),this,SLOT(replaceAll()));
+ }
+
+ if(opts.ask) {
+ _replaceAskDialog->exec();
+ }
+ else
+ replaceAll();
+ }
+
+ }
+}
+
+
+void KBabelView::replaceNext()
+{
+ _replacesTotal++;
+
+ KBabel::ReplaceOptions opts=_replaceDialog->replaceOpts();
+
+ // calculate the diff to original offset due to replacing a string
+ // in the starting item
+ if(_findStartPos.item == _replacePos.item ) {
+ if((opts.backwards && !_replaceWasAtEnd)
+ || (!opts.backwards && _replaceWasAtEnd)) {
+ _replaceExtraOffset += (opts.replaceStr.length()-_replaceLen);
+ }
+ }
+
+ Part part;
+ uint form = 0;
+ QString str;
+
+ if(_replacePos.part==Msgstr) {
+ part=Msgstr;
+ str = _catalog->msgstr(_replacePos.item).first()
+ .mid(_replacePos.offset,_replaceLen);
+ form=_replacePos.form;
+ }
+ else if(_replacePos.part==Comment) {
+ part = Comment;
+ str = _catalog->comment(_replacePos.item)
+ .mid(_replacePos.offset,_replaceLen);
+ }
+ else {
+ kdWarning() << "msgid can not be changed in KBabelView::replaceNext()"
+ << endl;
+ return;
+}
+
+ _catalog->applyBeginCommand( _replacePos.item,part,this);
+
+ DelTextCmd* delCmd = new DelTextCmd(_replacePos.offset,str,form);
+ delCmd->setPart(part);
+ delCmd->setIndex(_replacePos.item);
+ _catalog->applyEditCommand(delCmd,0);
+
+ InsTextCmd* insCmd = new InsTextCmd(_replacePos.offset,opts.replaceStr,form);
+ insCmd->setPart(part);
+ insCmd->setIndex(_replacePos.item);
+ _catalog->applyEditCommand(insCmd,0);
+
+ _catalog->applyEndCommand( _replacePos.item,part,this);
+
+ // now find next string
+ bool success;
+
+ if( opts.backwards ) {
+ success = findPrev_internal(_replacePos,true);
+ }
+ else {
+ _replacePos.offset+=opts.replaceStr.length();
+ success = findNext_internal(_replacePos,true);
+ }
+
+ if(!success) {
+ if(_replaceAskDialog && _replaceAskDialog->isVisible())
+ _replaceAskDialog->hide();
+ }
+
+}
+
+
+void KBabelView::replaceAll()
+{
+ if(_replaceAskDialog && _replaceAskDialog->isVisible())
+ _replaceAskDialog->hide();
+
+ KBabel::ReplaceOptions opts=_replaceDialog->replaceOpts();
+ bool success=true;
+
+ _catalog->applyBeginCommand(_replacePos.item,Msgstr,this);
+
+ while(success)
+ {
+ kapp->processEvents(100);
+
+ _replacesTotal++;
+
+ // calculate the diff to original offset due to replacing a string
+ // in the starting item
+ if(_findStartPos.item == _replacePos.item ) {
+ if((opts.backwards && !_replaceWasAtEnd) || (!opts.backwards && _replaceWasAtEnd)) {
+ _replaceExtraOffset += (opts.replaceStr.length()-_replaceLen);
+ }
+ }
+
+ Part part;
+ uint form=0;
+ QString str;
+
+ if(_replacePos.part==Msgstr) {
+ part=Msgstr;
+ form=_replacePos.form;
+ str = _catalog->msgstr(_replacePos.item).first().mid(_replacePos.offset,_replaceLen);
+ }
+ else if(_replacePos.part==Comment) {
+ part = Comment;
+ str = _catalog->comment(_replacePos.item).mid(_replacePos.offset,_replaceLen);
+ }
+ else {
+ kdWarning() << "msgid can not be changed in KBabelView::replaceNext()" << endl;
+ return;
+ }
+
+ DelTextCmd* delCmd = new DelTextCmd(_replacePos.offset,str,form);
+ delCmd->setPart(part);
+ delCmd->setIndex(_replacePos.item);
+ _catalog->applyEditCommand(delCmd,0);
+
+ InsTextCmd* insCmd = new InsTextCmd(_replacePos.offset,opts.replaceStr,form);
+ insCmd->setPart(part);
+ insCmd->setIndex(_replacePos.item);
+ _catalog->applyEditCommand(insCmd,0);
+
+
+ // now find next string
+ if( opts.backwards ) {
+ success = findPrev_internal(_replacePos,true,false);
+ }
+ else {
+ _replacePos.offset+=opts.replaceStr.length();
+ success = findNext_internal(_replacePos,true,false);
+ }
+ }
+
+ _catalog->applyEndCommand(_replacePos.item,Msgstr,this);
+}
+
+void KBabelView::findNextReplace()
+{
+ bool success;
+ KBabel::ReplaceOptions opts=_replaceDialog->replaceOpts();
+
+ if( opts.backwards ) {
+ success = findPrev_internal(_replacePos,true);
+ }
+ else {
+ _replacePos.offset++;
+ success = findNext_internal(_replacePos,true);
+ }
+
+ if(!success) {
+ if(_replaceAskDialog && _replaceAskDialog->isVisible())
+ _replaceAskDialog->hide();
+ }
+
+}
+
+void KBabelView::findInFile(QCString fileSource, FindOptions options)
+{
+ DocPosition pos;
+ pos.item=0;
+ pos.part=Msgid;
+ pos.offset=0;
+ _findStartPos=pos;
+ _findBreakAtEnd=true; // do not start from the beginning at the end
+ _showTryLaterBox=true;
+
+ // delete dontDisplayAgain from configuration
+ KConfig* config = KGlobal::config();
+ KConfigGroupSaver saver(config,"Notification Messages");
+ config->writeEntry("waitForNextFile",true);
+
+ // set that there can be more files
+ options.askFile = true;
+
+ _fileSource = fileSource;
+
+ if( !_findDialog ) _findDialog = new FindDialog(false,this);
+ _findDialog->setFindOpts(options);
+ findNext_internal(pos);
+}
+
+void KBabelView::replaceInFile(QCString fileSource, KBabel::ReplaceOptions options)
+{
+ _replacePos.item=0;
+ _replacePos.part=Msgid;
+ _replacePos.offset=0;
+
+ _replacesTotal=0;
+ _replaceLen=0;
+ _replaceWasAtEnd=false;
+ _replaceExtraOffset=0;
+
+ _findBreakAtEnd=true;
+ _showTryLaterBox=true;
+
+ // delete dontDisplayAgain from configuration
+ KConfig* config = KGlobal::config();
+ KConfigGroupSaver saver(config,"Notification Messages");
+ config->writeEntry("waitForNextFile",true);
+
+ // set that there can be more files
+ options.askFile = true;
+
+ _fileSource = fileSource;
+
+ if( !_replaceDialog ) _replaceDialog = new FindDialog(true,this);
+ _replaceDialog->setReplaceOpts(options);
+
+ bool success;
+
+ success = findNext_internal(_replacePos,true);
+
+ if(!success) kdDebug(KBABEL) << "Not found in file where catalog manager told us. This should not happen" << endl;
+ else {
+ if(!_replaceAskDialog) {
+ _replaceAskDialog = new ReplaceDialog(this);
+ connect(_replaceAskDialog,SIGNAL(replace()),this,SLOT(replaceNext()));
+ connect(_replaceAskDialog,SIGNAL(next()),this,SLOT(findNextReplace()));
+ connect(_replaceAskDialog,SIGNAL(replaceAll()),this,SLOT(replaceAll()));
+ }
+
+ if(options.ask) {
+ _replaceAskDialog->exec();
+ }
+ else replaceAll();
+ }
+}
+
+
+void KBabelView::deselectAll()
+{
+ msgstrEdit->selectAll(false);
+// FIXME: commentEdit->selectAll(false);
+ msgidLabel->selectAll(false);
+}
+
+void KBabelView::selectAll()
+{
+ if(msgstrEdit->hasFocus())
+ {
+ msgstrEdit->selectAll();
+ }
+// FIXME: else if(commentEdit->hasFocus())
+// FIXME: {
+// FIXME: commentEdit->selectAll();
+// FIXME: }
+ else if(msgidLabel->hasFocus())
+ {
+ msgidLabel->selectAll();
+ }
+}
+
+void KBabelView::clear()
+{
+ if(msgstrEdit->hasFocus())
+ {
+ msgstrEdit->clear();
+ }
+// FIXME: else if(commentEdit->hasFocus())
+// FIXME: {
+// FIXME: commentEdit->clear();
+// FIXME: }
+}
+
+void KBabelView::msgid2msgstr()
+{
+ // FIXME: should care about plural forms
+ QString text = _catalog->msgid(_currentIndex).first();
+
+ // this is KDE specific:
+ if(text.find("_: NAME OF TRANSLATORS\\n")==0)
+ {
+ text=_catalog->identitySettings().authorLocalizedName;
+ }
+ else if(text.find("_: EMAIL OF TRANSLATORS\\n")==0)
+ {
+ text=_catalog->identitySettings().authorEmail;
+ }
+ else if(_catalog->isGeneratedFromDocbook() && text.find("ROLES_OF_TRANSLATORS")==0)
+ {
+ text="<othercredit role=\\\"translator\\\">\n"
+ "<firstname></firstname><surname></surname>\n"
+ "<affiliation><address><email>"+_catalog->identitySettings().authorEmail+"</email></address>\n"
+ "</affiliation><contrib></contrib></othercredit>";
+ }
+ else if(_catalog->isGeneratedFromDocbook() && text.find("CREDIT_FOR_TRANSLATORS")==0)
+ {
+ text="<para>"+_catalog->identitySettings().authorLocalizedName+"\n"+
+ "<email>"+_catalog->identitySettings().authorEmail+"</email></para>";
+ }
+ else if(text.contains(_catalog->miscSettings().singularPlural))
+ {
+ text.replace(_catalog->miscSettings().singularPlural,"");
+ }
+ // end of KDE specific part
+
+
+ QRegExp reg=_catalog->miscSettings().contextInfo;
+ if(text.contains(reg))
+ {
+ text.replace(reg,"");
+ }
+
+ modifyMsgstrText(0,text,true);
+
+ msgstrEdit->setCursorPosition(0,0);
+}
+
+void KBabelView::search2msgstr()
+{
+ modifyMsgstrText(0,dictBox->translation(),true);
+
+ msgstrEdit->setCursorPosition(0,0);
+}
+
+
+void KBabelView::gotoFirst()
+{
+ DocPosition pos;
+ pos.item=0;
+ pos.form=0;
+ gotoEntry(pos);
+}
+
+void KBabelView::gotoLast()
+{
+ DocPosition pos;
+ pos.item=_catalog->numberOfEntries()-1;
+ pos.form=0;
+ gotoEntry(pos);
+}
+
+void KBabelView::gotoNext()
+{
+ DocPosition pos;
+ pos.item=_currentIndex;
+ pos.form=msgstrEdit->currentForm();
+
+ if( (int)pos.form+1 < _catalog->defaultNumberOfPluralForms()
+ && _catalog->pluralForm(_currentIndex)==Gettext )
+ {
+ pos.form++;
+ }
+ else
+ {
+ // check, if we are already showing the last entry
+ if(_currentIndex>=_catalog->numberOfEntries()-1)
+ {
+ return;
+ }
+ else
+ {
+ pos.item++;
+ pos.form=0;
+ }
+ }
+
+ gotoEntry(pos);
+}
+
+void KBabelView::gotoPrev()
+{
+ DocPosition pos;
+ pos.item=_currentIndex;
+ pos.form=msgstrEdit->currentForm();
+ // check, if we are already showing the first entry
+ if(_currentIndex==0 && pos.form==0)
+ {
+ return;
+ }
+ else
+ {
+ if( pos.form==0 )
+ {
+ pos.item--;
+ if( _catalog->pluralForm(pos.item)==Gettext )
+ pos.form=_catalog->defaultNumberOfPluralForms()-1;
+ } else pos.form--;
+
+ gotoEntry(pos);
+ }
+
+}
+
+void KBabelView::gotoEntry()
+{
+ if( !_gotoDialog )
+ {
+ _gotoDialog = new GotoDialog(_catalog->numberOfEntries(),this);
+ }
+
+ _gotoDialog->exec();
+ if( _gotoDialog->result() )
+ {
+ int number=_gotoDialog->number()-1;
+ int max=_catalog->numberOfEntries()-1;
+
+ if(number>max)
+ number=max;
+ else
+ if(number<0)
+ number=0;
+
+ DocPosition pos;
+ pos.item=number;
+ pos.form=0;
+ gotoEntry(pos);
+ }
+
+}
+
+void KBabelView::gotoNextFuzzy()
+{
+ DocPosition pos;
+ if( _catalog->nextFuzzy(_currentIndex,pos) >= 0 )
+ {
+ gotoEntry(pos);
+ }
+}
+
+void KBabelView::gotoPrevFuzzy()
+{
+ DocPosition pos;
+ if( _catalog->prevFuzzy(_currentIndex,pos) >= 0 )
+ {
+ gotoEntry(pos);
+ }
+}
+
+void KBabelView::gotoNextError()
+{
+ DocPosition pos;
+ if(_catalog->nextError(_currentIndex,pos) >= 0 )
+ {
+ _dontBeep=true;
+ gotoEntry(pos);
+ _dontBeep=false;
+ }
+}
+
+void KBabelView::gotoPrevError()
+{
+ DocPosition pos;
+ if(_catalog->prevError(_currentIndex,pos) >= 0)
+ {
+ _dontBeep=true;
+ gotoEntry(pos);
+ _dontBeep=false;
+ }
+}
+
+void KBabelView::gotoNextFuzzyOrUntrans()
+{
+ DocPosition fuzzyPos,untransPos;
+
+ int fuzzyIndex=_catalog->nextFuzzy(_currentIndex,fuzzyPos);
+ int untransIndex=_catalog->nextUntranslated(_currentIndex,untransPos);
+
+ if(fuzzyIndex<0 && untransIndex<0 ) return;
+
+ if(fuzzyIndex<0)
+ {
+ gotoEntry(untransPos);
+ return;
+ }
+ if(untransIndex<0)
+ {
+ gotoEntry(fuzzyPos);
+ return;
+ }
+
+ if( fuzzyIndex<untransIndex
+ || (fuzzyIndex==untransIndex && fuzzyPos.form<untransPos.form))
+ {
+ gotoEntry(fuzzyPos);
+ }
+ else
+ {
+ gotoEntry(untransPos);
+ }
+}
+
+void KBabelView::gotoPrevFuzzyOrUntrans()
+{
+ DocPosition fuzzyPos,untransPos;
+
+ int fuzzyIndex=_catalog->prevFuzzy(_currentIndex,fuzzyPos);
+ int untransIndex=_catalog->prevUntranslated(_currentIndex,untransPos);
+
+ if(fuzzyIndex<0 && untransIndex<0 ) return;
+
+ if(fuzzyIndex<0)
+ {
+ gotoEntry(untransPos);
+ return;
+ }
+ if(untransIndex<0)
+ {
+ gotoEntry(fuzzyPos);
+ return;
+ }
+
+ if( fuzzyIndex>untransIndex
+ || (fuzzyIndex==untransIndex && fuzzyPos.form>untransPos.form))
+ {
+ gotoEntry(fuzzyPos);
+ }
+ else
+ {
+ gotoEntry(untransPos);
+ }
+}
+
+void KBabelView::gotoNextUntranslated()
+{
+ DocPosition pos;
+ if(_catalog->nextUntranslated(_currentIndex,pos)>=0)
+ {
+ gotoEntry(pos);
+ }
+}
+
+void KBabelView::gotoPrevUntranslated()
+{
+ DocPosition pos;
+ if(_catalog->prevUntranslated(_currentIndex,pos)>=0)
+ {
+ gotoEntry(pos);
+ }
+}
+
+
+void KBabelView::gotoEntry(const DocPosition& pos, bool updateHistory)
+{
+ // clear up statusbar
+ emit signalChangeStatusbar("");
+
+ if(updateHistory)
+ {
+ if(_forwardHistory.count()>0)
+ {
+ emit signalForwardHistory(false);
+ }
+ _forwardHistory.clear();
+ _backHistory.append(_currentIndex);
+
+ if(_backHistory.count()==1)
+ {
+ emit signalBackHistory(true);
+ }
+ else if(_backHistory.count()>MAX_HISTORY)
+ {
+ _backHistory.remove(_backHistory.begin());
+ }
+ }
+
+ informDictionary();
+
+ _currentPos=pos;
+ _currentIndex=pos.item;
+ updateEditor(pos.form,true);
+ emitEntryState();
+ updateTags();
+ updateArgs();
+}
+
+void KBabelView::msgstrPluralFormChanged ( uint index )
+{
+ _currentPos.form = index;
+ emit signalDisplayed (_currentPos);
+}
+
+void KBabelView::backHistory()
+{
+ if(_backHistory.isEmpty())
+ {
+ kdDebug(KBABEL) << "KBabelView::backHistory called without any history." << endl;
+ return;
+ }
+
+ _forwardHistory.append(_currentIndex);
+ uint index=_backHistory.last();
+ _backHistory.remove(_backHistory.fromLast());
+
+ DocPosition pos;
+ pos.item=index;
+ pos.form=0;
+ gotoEntry(pos,false);
+
+ if(_backHistory.count()==0)
+ {
+ emit signalBackHistory(false);
+ }
+ if(_forwardHistory.count()==1)
+ {
+ emit signalForwardHistory(true);
+ }
+}
+
+void KBabelView::forwardHistory()
+{
+ if(_forwardHistory.isEmpty())
+ {
+ kdDebug(KBABEL) << "KBabelView::forwardHistory called without any history." << endl;
+ return;
+ }
+
+ _backHistory.append(_currentIndex);
+ uint index=_forwardHistory.last();
+ _forwardHistory.remove(_forwardHistory.fromLast());
+
+ DocPosition pos;
+ pos.item=index;
+ pos.form=0;
+ gotoEntry(pos,false);
+
+ if(_forwardHistory.count()==0)
+ {
+ emit signalForwardHistory(false);
+ }
+ if(_backHistory.count()==1)
+ {
+ emit signalBackHistory(true);
+ }
+}
+
+void KBabelView::removeFuzzyStatus()
+{
+ bool newState = !_catalog->isFuzzy(_currentIndex);
+ _catalog->setFuzzy(_currentIndex,newState);
+
+ // ensure we will update the translation memory as needed
+ msgstrEdit->setModified (true);
+ emit signalFuzzyDisplayed(newState);
+}
+
+
+void KBabelView::editHeader()
+{
+ HeaderEditor* editor=_catalog->headerEditor();
+
+ int editHeight=editor->height();
+ int editWidth=editor->width();
+ int w=width();
+ int h=height();
+
+ int x=w/2-editWidth/2;
+ int y=h/2-editHeight/2;
+
+ editor->move(mapToGlobal(QPoint(x,y)));
+
+ editor->show();
+ editor->raise();
+
+}
+
+
+void KBabelView::stopSearch()
+{
+ dictBox->stopSearch();
+}
+
+void KBabelView::startSearch()
+{
+ startSearch(false);
+}
+
+void KBabelView::startSearch(bool delay)
+{
+ QString msg = _catalog->msgid(_currentIndex,true).first();
+ QRegExp reg=_catalog->miscSettings().contextInfo;
+ if(msg.contains(reg))
+ {
+ msg.replace(reg,"");
+ }
+
+ dictBox->setActiveModule(KBabelSettings::defaultModule());
+ if(delay)
+ {
+ dictBox->startDelayedSearch(msg);
+ }
+ else
+ {
+ dictBox->startSearch(msg);
+ }
+}
+
+void KBabelView::startSearch(const QString module)
+{
+ // FIXME: should care about plural forms
+ QString msg = _catalog->msgid(_currentIndex,true).first();
+ QRegExp reg=_catalog->miscSettings().contextInfo;
+ if(msg.contains(reg))
+ {
+ msg.replace(reg,"");
+ }
+
+ dictBox->setActiveModule(module);
+ dictBox->startSearch(msg);
+
+}
+
+void KBabelView::startSelectionSearch()
+{
+ startSelectionSearch(KBabelSettings::defaultModule());
+}
+
+void KBabelView::startSelectionSearch(const QString module)
+{
+ dictBox->setActiveModule(module);
+
+ if(msgidLabel->hasSelectedText())
+ {
+ // TODO: should we care about end of lines?
+ dictBox->startSearch(msgidLabel->selectedText());
+ }
+ else if(msgstrEdit->hasSelectedText())
+ {
+ dictBox->startTranslationSearch(msgstrEdit->selectedText());
+ }
+ else
+ {
+ // should care about plural forms
+ QString msg = _catalog->msgid(_currentIndex,true).first();
+ QRegExp reg=_catalog->miscSettings().contextInfo;
+ if(msg.contains(reg))
+ {
+ msg.replace(reg,"");
+ }
+
+ dictBox->startSearch(msg);
+ }
+}
+
+
+void KBabelView::emitEntryState()
+{
+ // flag, so I don't have to always change the color of the text
+ static bool isError=false;
+
+ emit signalDisplayed(_currentPos);
+
+ emit signalFirstDisplayed(_currentIndex==0, msgstrEdit->currentForm()==0);
+ emit signalLastDisplayed((unsigned)(_currentIndex+1)==_catalog->numberOfEntries(), (signed)(msgstrEdit->currentForm())==_catalog->numberOfPluralForms(_currentIndex)-1);
+
+ bool fuzzy=_catalog->isFuzzy(_currentIndex);
+ bool untrans=_catalog->isUntranslated(_currentIndex);
+ emit signalFuzzyDisplayed(fuzzy);
+ emit signalUntranslatedDisplayed(untrans);
+ emit signalFuzzyAfterwards(_catalog->hasFuzzyAfterwards(_currentIndex));
+ emit signalUntranslatedAfterwards(_catalog->hasUntranslatedAfterwards(_currentIndex));
+ emit signalFuzzyInFront(_catalog->hasFuzzyInFront(_currentIndex));
+ emit signalUntranslatedInFront(_catalog->hasUntranslatedInFront(_currentIndex));
+
+ emit signalErrorAfterwards(_catalog->hasErrorAfterwards(_currentIndex));
+ emit signalErrorInFront(_catalog->hasErrorInFront(_currentIndex));
+
+ DocPosition pos;
+ if( _catalog->hasError(_currentIndex,pos) != isError )
+ {
+ isError = !isError;
+
+ emit signalFaultyDisplayed(isError);
+
+ if(isError)
+ {
+ QPalette palette=msgstrEdit->palette();
+ palette.setColor( QColorGroup::Text, red );
+
+ if( _catalog->itemStatus(_currentIndex).contains("syntax error"))
+ {
+ msgstrEdit->setCurrentColor( MsgMultiLineEdit::ErrorColor );
+ }
+ else
+ if( !_catalog->itemStatus(_currentIndex).isEmpty() && KBabelSettings::autoCheckColorError())
+ {
+ msgstrEdit->setCurrentColor( MsgMultiLineEdit::ErrorColor );
+ }
+ }
+ else
+ {
+ msgstrEdit->setCurrentColor( MsgMultiLineEdit::NormalColor );
+ }
+ }
+
+}
+
+void KBabelView::checkFuzzies()
+{
+ emit signalFuzzyAfterwards(_catalog->hasFuzzyAfterwards(_currentIndex));
+ emit signalFuzzyInFront(_catalog->hasFuzzyInFront(_currentIndex));
+}
+
+void KBabelView::checkUntranslated()
+{
+ emit signalUntranslatedAfterwards(_catalog->hasUntranslatedAfterwards(_currentIndex));
+ emit signalUntranslatedInFront(_catalog->hasUntranslatedInFront(_currentIndex));
+}
+
+void KBabelView::autoRemoveFuzzyStatus()
+{
+ // only at first text change remove fuzzy status
+ disconnect(msgstrEdit,SIGNAL(textChanged()),this,SLOT(autoRemoveFuzzyStatus()));
+
+ //removeFuzzyStatus();
+}
+
+void KBabelView::toggleFuzzyLed(bool on)
+{
+ if(!_fuzzyLed)
+ return;
+
+ if(on)
+ {
+ if(_fuzzyLed->state()==KLed::Off)
+ {
+ _fuzzyLed->on();
+ }
+ }
+ else
+ {
+ if(_fuzzyLed->state()==KLed::On)
+ _fuzzyLed->off();
+ }
+}
+
+void KBabelView::toggleUntransLed(bool on)
+{
+ if(!_untransLed)
+ return;
+
+ if(on)
+ {
+ if(_untransLed->state()==KLed::Off)
+ _untransLed->on();
+ }
+ else
+ {
+ if(_untransLed->state()==KLed::On)
+ _untransLed->off();
+ }
+}
+
+void KBabelView::toggleErrorLed(bool on)
+{
+ if(!_errorLed)
+ return;
+
+ if(on)
+ {
+ if(_errorLed->state()==KLed::Off)
+ {
+ _errorLed->on();
+ }
+ }
+ else
+ {
+ if(_errorLed->state()==KLed::On)
+ _errorLed->off();
+ }
+}
+
+
+
+
+void KBabelView::showError(const QString& message)
+{
+ KMessageBox::error(this,message);
+}
+
+void KBabelView::dragEnterEvent(QDragEnterEvent *event)
+{
+ // accept uri drops only
+ event->accept(KURLDrag::canDecode(event));
+}
+
+void KBabelView::dropEvent(QDropEvent *event)
+{
+ KURL::List uri;
+
+ // see if we can decode a URI.. if not, just ignore it
+ if (KURLDrag::decode(event, uri))
+ {
+ processUriDrop(uri , mapToGlobal(event->pos()));
+ }
+}
+
+
+bool KBabelView::eventFilter( QObject* object, QEvent* event)
+{
+ if(event->type() == QEvent::DragEnter)
+ {
+ QDragEnterEvent* e = (QDragEnterEvent*) event;
+ if(KURLDrag::canDecode(e))
+ {
+ e->accept(true);
+ return true;
+ }
+ }
+ else if(event->type() == QEvent::Drop)
+ {
+ KURL::List uri;
+ // see if we can decode a URI.. if not, just ignore it
+ if (KURLDrag::decode((QDropEvent*)event, uri))
+ {
+ processUriDrop(uri ,( (QWidget*)object)->mapToGlobal( ( (QDropEvent*)event )->pos()));
+ return true;
+ }
+ }
+ else if(event->type() == QEvent::KeyPress)
+ {
+ // This is a little workaround to use CTRL+ALT+Home, CTRL+ALT+End, Undo keys
+ // to go to the first and the last entry. Because otherwise
+ // CTRL+Home and CTRL+End and Undo are caught by QTextEdit
+ QKeyEvent *ke = (QKeyEvent*)event;
+
+ if(ke->key() == Key_Home && ke->state() == (AltButton | ControlButton))
+ {
+ gotoFirst();
+ return true;
+ }
+ else if(ke->key() == Key_End
+ && ke->state() == (AltButton | ControlButton))
+ {
+ gotoLast();
+ return true;
+ }
+ else if( KShortcut(KKey(ke)) == KStdAccel::undo() )
+ {
+ undo();
+ return true;
+ }
+ else if( KShortcut(KKey(ke)) == KStdAccel::redo() )
+ {
+ redo();
+ return true;
+ }
+ else if( ke->key() == Key_Insert )
+ {
+ m_mainwindow->toggleEditMode();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void KBabelView::processUriDrop(KURL::List& uriList, const QPoint& pos)
+{
+ // if we have two entries, the chance is high, that it
+ // is a drag from the catalog manager
+ if(uriList.count() == 2)
+ {
+ int result = _dropMenu->exec(pos);
+ switch(result)
+ {
+ case ID_DROP_OPEN:
+ {
+ KURL first(uriList.first());
+ KURL second(uriList.last());
+
+ if( KIO::NetAccess::exists(first, true, this) )
+ {
+ open(first);
+ }
+ else
+ {
+ openTemplate(second,first);
+ }
+ break;
+ }
+ case ID_DROP_OPEN_TEMPLATE:
+ {
+ open(uriList.last());
+ break;
+ }
+ }
+ }
+ else
+ {
+ // okay, we have one URI.. process it
+ KURL url( uriList.first() );
+
+ // load in the file
+ open(url);
+ }
+}
+
+void KBabelView::forwardMsgstrEditCmd(EditCommand* cmd)
+{
+/*
+ if(cmd->terminator()!=0)
+ {
+ kdDebug(KBABEL) << QString::number(cmd->terminator()) << endl;
+ }
+ else
+ {
+ DelTextCmd* delcmd = (DelTextCmd*) cmd;
+ kdDebug(KBABEL) << QString::number(delcmd->offset)+":"+delcmd->str+"|" << endl;
+ }
+*/
+ bool fuzzyRemoved=false;
+ if(KBabelSettings::autoUnsetFuzzy() && _catalog->isFuzzy(_currentIndex) )
+ {
+ fuzzyRemoved=true;
+
+ _catalog->applyBeginCommand(_currentIndex,Msgstr,this);
+
+ removeFuzzyStatus();
+ }
+
+ cmd->setPart(Msgstr);
+ cmd->setIndex(_currentIndex);
+
+ bool wasUntranslated=_catalog->isUntranslated(_currentIndex);
+
+ _catalog->applyEditCommand(cmd,this);
+
+ if( fuzzyRemoved )
+ {
+ _catalog->applyEndCommand(_currentIndex,Msgstr,this);
+ }
+
+
+ bool isUntranslated=_catalog->isUntranslated(_currentIndex);
+
+ if(wasUntranslated && !isUntranslated)
+ emit signalUntranslatedDisplayed(false);
+ else if(!wasUntranslated && isUntranslated)
+ emit signalUntranslatedDisplayed(true);
+
+}
+
+void KBabelView::autoCheck()
+{
+ autoCheck(true);
+}
+
+
+void KBabelView::autoCheck(bool onlyWhenChanged)
+{
+ if( !_autocheckTools.isEmpty() )
+ {
+ QStringList oldStatus = _catalog->itemStatus(_currentIndex);
+
+ QStringList status = _catalog->itemStatus( _currentIndex,true, _autocheckTools );
+
+ // if there is more than one view, the status changes only in
+ // one view, so we have to update always.
+ if(_catalog->isLastView() && onlyWhenChanged && oldStatus == status)
+ return;
+
+ if( !status.isEmpty() )
+ {
+ QString msg = "";
+
+ // ### TODO: whynot use i18n("context",text) directly?
+ KLocale* locale=KGlobal::locale();
+
+ for( QStringList::iterator it=status.begin() ; it != status.end() ; ++it )
+ {
+ if( msg.isEmpty() ) msg = locale->translate("what check found errors",(*it).utf8());
+ else msg += ", "+locale->translate("what check found errors",(*it).utf8());
+ }
+
+ //i18n: translators: Status bar text that automatic checks have found some errors
+ emit signalChangeStatusbar(i18n("1 error: %1", "%n errors: %1", status.size ()).arg(msg));
+ emit signalFaultyDisplayed(true);
+
+ if(KBabelSettings::autoCheckColorError())
+ {
+ msgstrEdit->setCurrentColor( MsgMultiLineEdit::ErrorColor );
+ }
+
+ if(KBabelSettings::beepOnError() && !_dontBeep)
+ {
+ if(onlyWhenChanged)
+ {
+ if(oldStatus != status && oldStatus.isEmpty() )
+ {
+ KNotifyClient::beep();
+ }
+ }
+ else if(isActiveWindow())
+ {
+ KNotifyClient::beep();
+ }
+ }
+ }
+ else if( _catalog->itemStatus(_currentIndex).isEmpty() )
+ {
+ _catalog->removeFromErrorList(_currentIndex);
+
+ emit signalFaultyDisplayed(false);
+
+ if(KBabelSettings::autoCheckColorError())
+ {
+ msgstrEdit->setCurrentColor( MsgMultiLineEdit::NormalColor );
+ }
+ }
+ }
+}
+
+void KBabelView::spellcheckAll()
+{
+ spell.what2Check=All;
+ spellcheck();
+}
+
+void KBabelView::spellcheckAllMulti()
+{
+ spell.what2Check=AllMulti;
+ spellcheck();
+}
+
+
+void KBabelView::spellcheckFromCursor()
+{
+ spell.what2Check=End;
+ spellcheck();
+}
+
+
+void KBabelView::spellcheckCurrent()
+{
+ spell.what2Check=Current;
+ spellcheck();
+}
+
+void KBabelView::spellcheckFromCurrent()
+{
+ spell.what2Check=BeginCurrent;
+ spellcheck();
+}
+
+
+void KBabelView::spellcheckMarked()
+{
+ if(!msgstrEdit->hasSelectedText())
+ {
+ return;
+ }
+
+ spell.what2Check=Marked;
+ spellcheck();
+}
+
+
+void KBabelView::spellcheckCommon()
+{
+ SpellDlg *spellDlg = new SpellDlg(msgstrEdit->hasSelectedText(),this
+ ,"SpellDlg");
+
+ if(spellDlg->exec())
+ {
+ if(spellDlg->all())
+ spell.what2Check=All;
+ else if(spellDlg->current())
+ spell.what2Check=Current;
+ else if(spellDlg->begin())
+ spell.what2Check=Begin;
+ else if(spellDlg->end())
+ spell.what2Check=End;
+ else if(spellDlg->marked())
+ spell.what2Check=Marked;
+ else if(spellDlg->beginCurrent())
+ spell.what2Check=BeginCurrent;
+ else
+ {
+ kdError() << "unhandled option in spell dialog" << endl;
+ return;
+ }
+
+ spellcheck();
+ }
+
+ delete spellDlg;
+}
+
+void KBabelView::addSpellcheckWords( uint pos, QString text, uint index, uint form )
+{
+ // special format chars
+ QString spclChars="abfnrtv'\"?\\";
+ QChar accelMarker=_catalog->miscSettings().accelMarker;
+
+ uint textLength=text.length();
+ do
+ {
+ QString word="";
+ bool wordBegin=false;
+ while(!wordBegin && pos < textLength)
+ {
+ QChar c=text[pos];
+ if(c.isLetter() || c==accelMarker)
+ {
+ wordBegin=true;
+ }
+ else if( c == '\\')
+ {
+ if(pos+1 < textLength && spclChars.contains(text[pos+1]) )
+ {
+ pos+=2;
+ }
+ else
+ {
+ // consider it to be unnecessary escaped character
+ pos++;
+ }
+ }
+ else
+ {
+ pos++;
+ }
+ }
+ int begin=pos;
+
+ bool wordEnd=false;
+ while(!wordEnd && pos < textLength)
+ {
+ if(text[pos].isLetter() || text[pos]=='-' || (text[pos]=='\'' && !spell.config->dictionary().startsWith("malti")))
+ {
+ word+=text[pos];
+ pos++;
+ }
+ else if(text[pos]==accelMarker)
+ {
+ pos++;
+ }
+ else if(text[pos]=='\n')
+ {
+ // newline without \n counts as nothing
+ pos++;
+ }
+ else
+ {
+ wordEnd=true;
+ }
+ }
+
+ int end=pos;
+
+ // remove '-' and accelMarker at the end of a word
+ while(text[end]=='-' || (text[pos]=='\'' && !spell.config->dictionary().startsWith("malti"))
+ || text[end]==accelMarker)
+ {
+ end--;
+ word.truncate(word.length()-1);
+ }
+
+ if(!word.isEmpty())
+ {
+ spell.wordList.append(word);
+ Position *pos = new Position;
+ pos->index=index;
+ pos->form=form;
+ pos->pos=begin;
+ pos->end=end;
+ spell.posDict.append(pos);
+ }
+ }
+ while(pos < textLength);
+}
+
+void KBabelView::spellcheck()
+{
+ if(isReadOnly() || spell.active)
+ return;
+
+ spell.wordList.clear();
+ spell.posDict.clear();
+ spell.ignoreList.clear();
+ spell.newIgnoreList.clear();
+
+ spell.misspelled=0;
+ spell.replaced=0;
+ spell.lastIndex=0;
+ spell.posCorrection=0;
+ spell.lastPos=0;
+ spell.inWordCorrection=0;
+
+ if( !_spellcheckSettings.valid )
+ {
+ _spellcheckSettings = _project->spellcheckSettings();
+ }
+
+ spell.config = new KSpellConfig(this,"tempSpellConfig");
+ spell.config->setNoRootAffix(_spellcheckSettings.noRootAffix);
+ spell.config->setRunTogether(_spellcheckSettings.runTogether);
+ spell.config->setClient(_spellcheckSettings.spellClient);
+ spell.config->setEncoding(_spellcheckSettings.spellEncoding);
+ spell.config->setDictionary(_spellcheckSettings.spellDict);
+
+ if(spell.what2Check==Marked)
+ {
+ spell.lastIndex=_currentIndex;
+
+ _tagExtractor->setString(msgstrEdit->selectedText());
+ QString marked=_tagExtractor->plainString(true);
+
+ addSpellcheckWords(msgstrEdit->beginOfMarkedText(),marked
+ ,_currentIndex,msgstrEdit->currentForm());
+ }
+ else
+ {
+ uint first=0;
+ uint last=_catalog->numberOfEntries()-1;
+ QString text;
+
+ bool emitProgress=false;
+
+ if(spell.what2Check==All || spell.what2Check==Begin
+ || spell.what2Check==End || spell.what2Check==AllMulti
+ || spell.what2Check==BeginCurrent)
+ {
+ emitProgress=true;
+ }
+
+ if(spell.what2Check==Begin)
+ {
+ first=0;
+ last=_currentIndex-1;
+ }
+ else if(spell.what2Check==End)
+ {
+ first=_currentIndex+1;
+ last=_catalog->numberOfEntries()-1;
+
+ int pos=msgstrEdit->currentIndex();
+ int form=msgstrEdit->currentForm();
+
+ QStringList msgs = _catalog->msgstr(_currentIndex);
+ _tagExtractor->setString((*msgs.at(form)));
+ text=_tagExtractor->plainString(true);
+ addSpellcheckWords( pos, text, _currentIndex, form++ );
+
+ for( QStringList::Iterator i=msgs.at(form++) ; i!=msgs.end(); i++)
+ {
+ _tagExtractor->setString(*i);
+ text=_tagExtractor->plainString(true);
+ addSpellcheckWords( pos, text, _currentIndex, form++ );
+ }
+ }
+ else if(spell.what2Check==BeginCurrent)
+ {
+ first=_currentIndex;
+ last=_catalog->numberOfEntries()-1;
+ }
+ else if(spell.what2Check!=All && spell.what2Check!=AllMulti)
+ {
+ first=last=_currentIndex;
+ }
+
+ if(emitProgress)
+ {
+ emit signalResetProgressBar(i18n("Preparing spell check"),100);
+ kapp->processEvents(100);
+ }
+
+ uint total=last-first+1;
+ uint lastPercent=0;
+ for(uint i=first; i <= last; i++)
+ {
+ if(emitProgress && 100*i/ QMAX(total,1) > lastPercent)
+ {
+ lastPercent++;
+ emit signalProgress(lastPercent);
+
+ kapp->processEvents(100);
+ }
+
+ QStringList msgs=_catalog->msgstr(i);
+ uint formCounter=0;
+ for(QStringList::Iterator j=msgs.begin() ; j!=msgs.end() ; ++j)
+ {
+ _tagExtractor->setString(*j);
+ text=_tagExtractor->plainString(true);
+ addSpellcheckWords(0,text,i,formCounter++);
+ }
+ }
+
+ if(spell.what2Check==Begin)
+ {
+ int pos=msgstrEdit->currentIndex();
+ int form=msgstrEdit->currentForm();
+
+ QStringList msgs = _catalog->msgstr(_currentIndex);
+ _tagExtractor->setString((*msgs.at(form)).left(pos));
+ text=_tagExtractor->plainString(true);
+ addSpellcheckWords( 0, text, _currentIndex, form++ );
+
+ for( QStringList::Iterator i=msgs.at(form++) ; i!=msgs.end(); i++)
+ {
+ _tagExtractor->setString(*i);
+ text=_tagExtractor->plainString(true);
+ addSpellcheckWords( 0, text, _currentIndex, form++ );
+ }
+ }
+
+ if(emitProgress)
+ {
+ emit signalClearProgressBar();
+ }
+ }
+
+ if(!spell.wordList.isEmpty())
+ {
+ spell.active=true;
+ _dontBeep=true;
+
+ spell.kspell= new KSpell (this, i18n("Spellcheck"),
+ this, SLOT(spellStart(KSpell *)), spell.config, true, true);
+ if( spell.kspell->status() == KSpell::Error )
+ {
+ KMessageBox::error( this, i18n("KBabel cannot start spell checker. "
+ "Please verify your KDE installation.") );
+ return;
+ }
+
+ connect(spell.kspell, SIGNAL(death()),this, SLOT(spellCleanDone()));
+
+ connect(spell.kspell, SIGNAL(misspelling(const QString &, const QStringList &
+ , unsigned int)), this
+ , SLOT(spellMisspelled(const QString &, const QStringList &, unsigned int)));
+
+ connect(spell.kspell, SIGNAL(corrected(const QString &, const QString &, unsigned int))
+ , this, SLOT(spellCorrected(const QString &, const QString &, unsigned int)));
+
+ connect(spell.kspell,SIGNAL(ignoreall(const QString &))
+ , this, SLOT(spellAddIgnore(const QString &)));
+
+ connect(spell.kspell, SIGNAL(done(bool))
+ , this, SLOT(spellResult(bool)));
+
+ spell.kspell->setAutoDelete(true); // let KSpell handle delete
+ }
+ else
+ {
+ KMessageBox::information(this,i18n(
+ "No relevant text has been found for spell checking."));
+ }
+}
+
+void KBabelView::spellStart(KSpell *)
+{
+ // set ignored words
+ if(_spellcheckSettings.rememberIgnored)
+ {
+ QString urlString = _spellcheckSettings.ignoreURL;
+ if(urlString.contains("@PACKAGE@"))
+ {
+ urlString.replace("@PACKAGE@",_catalog->packageName());
+ }
+ // ### TODO: correctly set the URL; support for MostLocalURL
+ KURL url(urlString);
+ if(url.isLocalFile())
+ {
+ QFile file(url.path());
+ if(file.open(IO_ReadOnly))
+ {
+ QTextStream stream(&file);
+ stream.setEncoding(QTextStream::UnicodeUTF8);
+ QString contents = stream.read();
+ file.close();
+
+ spell.ignoreList = QStringList::split('\n',contents);
+ }
+ else if(file.exists())
+ {
+ KMessageBox::sorry(this,
+ i18n("Error opening the file that contains words "
+ "to ignore during spell checking:\n"
+ "%1").arg(file.name()));
+ }
+ }
+ else
+ {
+ KMessageBox::sorry(this,
+ i18n("Only local files are allowed for saving "
+ "ignored words to during spell checking:\n"
+ "%1").arg(urlString));
+ }
+
+ if(spell.ignoreList.count() > 0)
+ {
+ emit signalResetProgressBar(i18n("Preparing spell check"),100);
+ kapp->processEvents(100);
+
+ uint total = spell.ignoreList.count();
+ uint oldPercent=0;
+ uint counter=0;
+ QStringList::Iterator it;
+ for(it=spell.ignoreList.begin(); it != spell.ignoreList.end(); ++it)
+ {
+ counter++;
+ if(counter/total > oldPercent)
+ {
+ oldPercent++;
+ emit signalProgress(oldPercent);
+ kapp->processEvents(100);
+ }
+
+ spell.kspell->ignore(*it);
+ }
+
+ emit signalClearProgressBar();
+ }
+ }
+
+ spell.kspell->checkList(&spell.wordList);
+}
+
+
+bool KBabelView::markMisspelled(const QString &orig, unsigned int pos)
+{
+ Position *p = spell.posDict.at(pos);
+ if(!p)
+ {
+ kdError() << "not a valid position: " << pos << endl;
+ return false;
+ }
+
+ if(p->index != _currentIndex || (p->index==_currentIndex && p->form!=msgstrEdit->currentForm()))
+ {
+ DocPosition pos;
+ pos.item=p->index;
+ pos.form=p->form;
+ gotoEntry(pos);
+ }
+
+
+ if(p->index != spell.lastIndex)
+ {
+ spell.lastIndex=p->index;
+ spell.posCorrection=0;
+ }
+ if(pos != spell.lastPos)
+ {
+ spell.lastPos=pos;
+ spell.inWordCorrection=0;
+ }
+
+ int x=0;
+ int y=0;
+
+ int begin=p->pos+spell.posCorrection-spell.inWordCorrection;
+ int end=p->end+spell.posCorrection-spell.inWordCorrection;
+
+ // check if this is the correct word
+ QString text = *_catalog->msgstr(p->index).at(p->form);
+ text=text.mid(begin,end-begin);
+ QChar accelMarker=_catalog->miscSettings().accelMarker;
+
+ if(text.contains(accelMarker))
+ {
+ text.replace(accelMarker,"");
+ }
+ if(text.contains('\n'))
+ {
+ text.replace("\n","");
+ }
+
+ bool textOk=true;
+ if(text != orig)
+ {
+ // if text and orig are not the same,
+ // maybe it was a word with hyphens
+ int n=text.contains('-');
+ n+=text.contains('\'');
+ if( n > 0 )
+ {
+ // re-get the original text since we replace some things above
+ QString text = *_catalog->msgstr(p->index).at(p->form);
+ text=text.mid(begin,end-begin);
+
+ bool textFound=false;
+ int i = 0;
+ int e=-1;
+ while(!textFound && i <= n)
+ {
+ int lastPos=e+1;
+ e = text.find('-',lastPos);
+ int tmp = text.find('\'',lastPos);
+ if(e < 0 && tmp > 0)
+ {
+ e=tmp;
+ }
+ else if(e > 0 && tmp > 0 && tmp < e)
+ {
+ e=tmp;
+ }
+
+ if(e<0) e=text.length();
+
+ QString w=text.mid(lastPos,e-lastPos);
+ if(w.contains(accelMarker))
+ {
+ w.replace(accelMarker,"");
+ }
+ if(text.contains('\n'))
+ {
+ text.replace("\n","");
+ }
+ if( w == orig)
+ {
+ textFound=true;
+ end=begin+e;
+ begin=begin+lastPos;
+ }
+
+ i++;
+ }
+
+ if(!textFound)
+ {
+ textOk=false;
+ }
+ }
+ else
+ {
+ textOk=false;
+ }
+ }
+
+ int beginx, beginy;
+
+ msgstrEdit->offset2Pos(end,y,x);
+ msgstrEdit->offset2Pos(begin,beginy,beginx);
+ msgstrEdit->setSelection(beginy,beginx,y,x);
+
+ if(!textOk)
+ {
+ text = *_catalog->msgstr(p->index).at(p->form);
+ text=text.mid(begin,end-begin);
+ kdDebug(KBABEL) << "Sync error: given: " << orig << " have: " << text << endl;
+ cancelSpellcheck();
+
+ KMessageBox::error(this,i18n(
+ "There seems to be an error with the synchronization "
+ "of the spell checking process and KBabel.\n"
+ "Please check that you have set the correct settings for "
+ "your language for spell checking.\n"
+ "If you have, and this problem is reproducible, please "
+ "send a detailed bug report (your spell checking options, "
+ "what file you have checked and what to do to reproduce "
+ "the problem) by using Help->Report Bug..."));
+ }
+
+ return textOk;
+}
+
+void KBabelView::spellMisspelled(const QString &orig, const QStringList &, unsigned int pos)
+{
+ kdDebug(KBABEL) << "misspelled: " << orig << " pos: " << pos << endl;
+
+ spell.misspelled++;
+
+ markMisspelled(orig,pos);
+}
+
+void KBabelView::spellCorrected(const QString &orig, const QString &word, unsigned int pos)
+{
+ if(orig != word)
+ {
+ QString newWord(word);
+ kdDebug(KBABEL) << "corrected: " << orig << " " << newWord
+ << " pos: " << pos << endl;
+
+ if(spell.replaced==0)
+ {
+ // handle the spell check as one action
+ int index;
+ Position *p = spell.posDict.at(pos);
+ if(p)
+ {
+ index=p->index;
+ }
+ else
+ {
+ index=_currentIndex;
+ }
+
+ _catalog->applyBeginCommand(index,Msgstr,this);
+ }
+
+ spell.replaced++;
+
+
+ if(markMisspelled(orig,pos))
+ {
+ QString marked=msgstrEdit->selectedText();
+ spell.origWords.append(marked);
+
+ if(marked.contains("\n") && !newWord.contains('\n'))
+ {
+ QString s1=newWord;
+ s1.replace(" ","\n");
+
+ // if only a newline has been replaced with a white space
+ if(s1==marked)
+ {
+ newWord.replace(" "," \n");
+ }
+
+ }
+ // check if the old word had an accelerator. If yes and the new
+ // word has no accelerator, try to add the accelerator for
+ // the same char else add in at the same position
+ QChar accelMarker=_catalog->miscSettings().accelMarker;
+ if(marked.contains(accelMarker) && !newWord.contains(accelMarker))
+ {
+ int b=marked.find(accelMarker);
+ QChar accel=marked[b+1];
+ int nb=newWord.find(accel,0,false);
+ if(nb>=0)
+ {
+ newWord.insert(nb,accelMarker);
+ }
+ // if the new word does not contain the old accel char
+ // set the accelerator to the same position as the old
+ else
+ {
+ if((uint)b >= newWord.length())
+ b = 0;
+ newWord.insert(b,accelMarker);
+ }
+ }
+
+ spell.newWords.append(newWord);
+
+ msgstrEdit->cut();
+ int row=0;
+ int col=0;
+ msgstrEdit->getCursorPosition(&row,&col);
+ msgstrEdit->insertAt(newWord,row,col,true);
+
+ int newCorrection = newWord.length() - marked.length();
+ spell.posCorrection += newCorrection;
+ spell.inWordCorrection += newCorrection;
+
+ // now store the new position
+ Position *p = spell.posDict.at(pos);
+ if(p)
+ {
+ p->end=p->end+newCorrection;
+ }
+ }
+ }
+}
+
+
+void KBabelView::spellResult(bool flag)
+{
+ kdDebug(KBABEL) << "spellResult: " << flag << endl;
+
+
+ if(spell.replaced > 0)
+ {
+ // close the spell check action
+ _catalog->applyEndCommand(spell.lastIndex,Msgstr,this);
+ }
+
+
+ if(flag)
+ {
+ emit signalChangeStatusbar(i18n("Spellcheck: %n word replaced","Spellcheck: %n words replaced",spell.replaced));
+
+ if(spell.misspelled==0)
+ {
+ KMessageBox::information(this,i18n(
+ "Spellcheck successfully finished.\n"
+ "No misspelled words have been found."));
+ }
+ else if(spell.replaced > 0 && spell.what2Check!=Current
+ && spell.what2Check!=Marked)
+ {
+ QStringList list;
+ QStringList::Iterator origIt;
+ QStringList::Iterator newIt;
+ origIt=spell.origWords.begin();
+ newIt=spell.newWords.begin();
+
+ for(;origIt != spell.origWords.end()
+ && newIt != spell.newWords.end(); origIt++,newIt++)
+ {
+ list.append(*origIt+" -> "+*newIt);
+ }
+
+ }
+
+ if( spell.what2Check!=AllMulti && spell.misspelled!=0 )
+ KMessageBox::information(this,i18n("Spellcheck: %n word replaced","Spellcheck: %n words replaced",spell.replaced));
+
+ if(_spellcheckSettings.rememberIgnored)
+ {
+ if(spell.newIgnoreList.count() > 0)
+ {
+ KURL url(_spellcheckSettings.ignoreURL);
+ if(url.isLocalFile())
+ {
+ QFile file(url.path());
+ if(file.open(IO_WriteOnly|IO_Append))
+ {
+ QStringList::Iterator it;
+ QTextStream stream(&file);
+ stream.setEncoding(QTextStream::UnicodeUTF8);
+
+ for(it=spell.newIgnoreList.begin();
+ it!=spell.newIgnoreList.end();
+ ++it)
+ {
+ stream << *it << "\n";
+ }
+
+ file.close();
+ }
+ }
+ else
+ {
+ kdDebug(KBABEL) << "only local files are supported for storing"
+ << "ignored words" << endl;
+ }
+ }
+ }
+ }
+ else
+ {
+ emit signalChangeStatusbar(i18n("Spellcheck canceled"));
+ if(spell.replaced > 0)
+ undo();
+ }
+
+ int s=spell.kspell->dlgResult();
+ spell.kspell->cleanUp();
+
+ emit signalSpellcheckDone(s);
+ QTimer::singleShot(0,this,SLOT(cleanUpSpellStruct()));
+}
+
+
+void KBabelView::spellCleanDone()
+{
+ kdDebug(KBABEL) << "spellCleanDone" << endl;
+
+ // if the pointer is cleared, you have finished correcly
+ if( !spell.kspell ) return;
+
+ KSpell::spellStatus status = spell.kspell->status();
+
+ if(status == KSpell::Error || status == KSpell::Crashed)
+ {
+ cleanUpSpellStruct();
+ }
+
+ if(status == KSpell::Error)
+ {
+ KMessageBox::sorry(this, i18n("The spell checker program could not be started.\n"
+ "Please make sure you have the spell checker program properly "
+ "configured and in your PATH."));
+ }
+ else if(status == KSpell::Crashed)
+ {
+ KMessageBox::sorry(this, i18n("The spell checker program seems to have crashed."));
+ }
+}
+
+void KBabelView::cleanUpSpellStruct()
+{
+ kdDebug(KBABEL) << "Cleaning structure" << endl;
+ // spell.kspell is set to be autodeleted
+ spell.kspell = 0;
+ delete spell.config;
+ spell.config=0;
+ spell.wordList.clear();
+ spell.posDict.clear();
+ spell.origWords.clear();
+ spell.newWords.clear();
+ spell.ignoreList.clear();
+ spell.newIgnoreList.clear();
+ spell.active = false;
+ _dontBeep=false;
+}
+
+void KBabelView::cancelSpellcheck()
+{
+ spell.active=false;
+}
+
+void KBabelView::spellAddIgnore(const QString &word)
+{
+ if(!spell.ignoreList.contains(word))
+ {
+ spell.newIgnoreList.append(word);
+ }
+}
+
+void KBabelView::forwardSearchStart()
+{
+ emit signalResetProgressBar(i18n("Searching"),100);
+ emit signalSearchActive(true);
+}
+
+void KBabelView::forwardSearchStop()
+{
+ emit signalClearProgressBar();
+ emit signalSearchActive(false);
+}
+
+void KBabelView::forwardProgressStart(const QString& msg)
+{
+ emit signalResetProgressBar(msg,100);
+}
+
+void KBabelView::slotAutoSaveTimeout( )
+{
+ if ( isModified( ) )
+ {
+ autoSaveTimer->stop( );
+ saveFile( false );
+ autoSaveTimer->start( 1000 * 60 * _autoSaveDelay );
+ }
+}
+
+void KBabelView::useProject (Project::Ptr project)
+{
+ // FIXME: close the current project first
+ disconnect (_project, SIGNAL(signalSpellcheckSettingsChanged()),
+ this, SLOT(updateProjectSettings()));
+
+ _project = project;
+ _catalog->useProject(_project);
+
+ readProject(_project);
+
+ connect (project, SIGNAL(signalSpellcheckSettingsChanged()),
+ this, SLOT(updateProjectSettings()));
+}
+
+#include "kbabelview.moc"
diff --git a/kbabel/kbabel/kbabelview.h b/kbabel/kbabel/kbabelview.h
new file mode 100644
index 00000000..a52ed4dc
--- /dev/null
+++ b/kbabel/kbabel/kbabelview.h
@@ -0,0 +1,712 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2002-2005 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef KBABELVIEW_H
+#define KBABELVIEW_H
+
+class HidingMsgEdit;
+class MsgMultiLineEdit;
+class GotoDialog;
+class QPopupMenu;
+class KLed;
+class FindDialog;
+class ReplaceDialog;
+
+namespace KBabel
+{
+ class EditCommand;
+ class RegExpExtractor;
+ class FindOptions;
+ class ReplaceOptions;
+}
+
+class QListBoxItem;
+class QTextView;
+class QTabWidget;
+class KListBox;
+class KSpell;
+class KSpellConfig;
+class KBabelDictBox;
+class KDataToolInfo;
+struct ReplaceOptions;
+struct ModuleInfo;
+
+#include <kdockwidget.h>
+#include <kurl.h>
+#include <kconfig.h>
+#include <qwidget.h>
+#include <qstrlist.h>
+#include <resources.h>
+
+#include <catalogview.h>
+#include "kbcatalog.h"
+#include "kbproject.h"
+#include "projectsettings.h"
+
+class KBabelMW;
+class CommentView;
+class ContextView;
+class KBCatalogListView;
+class CharacterSelectorView;
+class SourceView;
+class TagListView;
+
+/**
+ * This is the main view class for KBabel. Most of the non-menu,
+ * non-toolbar, and non-statusbar (e.g., non frame) GUI code should go
+ * here.
+ * @short Main view
+ * @author Matthias Kiefer <matthias.kiefer@gmx.de>
+ * @version 0.1
+ */
+class KBabelView : public QWidget, public KBabel::CatalogView
+{
+ Q_OBJECT
+public:
+ /**
+ * Default constructor
+ * @param buildLeds flag, if status leds should be created in editor
+ */
+ KBabelView(KBCatalog* catalog,KBabelMW *parent, KBabel::Project::Ptr project);
+
+ /**
+ * Destructor
+ */
+ virtual ~KBabelView();
+
+ /**
+ * @return the view, that has opened file url or 0 if this
+ * file is not opened
+ */
+ static KBabelView *viewForURL(const KURL& url, const QString project);
+
+ /**
+ * @return the view, that has no opened file url or 0 if there
+ * is no such view
+ */
+ static KBabelView *emptyView(const QString project);
+
+ KURL currentURL() const;
+ QString project() const { return _project->filename(); }
+ void useProject (KBabel::Project::Ptr project);
+
+ bool isLastView() const;
+ bool isModified() const;
+ /** the edit mode of the entry-editors*/
+ bool isOverwriteMode() const;
+ bool isReadOnly() const;
+ /** the edit mode of the entry-editors*/
+ void setOverwriteMode(bool ovr);
+ bool isSearching() const;
+
+ void saveView(KConfig *config);
+ void restoreView(KConfig *config);
+ void saveSession(KConfig*);
+ void restoreSession(KConfig*);
+
+ void readSettings(KConfig* config);
+ void saveSettings();
+
+ void readProject(KBabel::Project::Ptr project);
+ void saveProject(KConfig* config);
+
+ void openTemplate(const KURL& openURL, const KURL& saveURL);
+ bool saveFile(bool checkSyntax=true);
+ bool saveFileAs(KURL url = KURL(), bool checkSyntax=true);
+ bool saveFileSpecial();
+
+ /**
+ * Checks, if the file has been modified. If true, it askes the user if he wants
+ * to save, discard or cancel. If the users chose save, it saves the file.
+ * @return true, if it is allowed to open a new file. false, if the user wants
+ * to edit the file again.
+ */
+ bool checkModified();
+
+
+ /**
+ * Checks syntax of the current catalog. If the catalog is modified it
+ * saves it under a temporary filename ( using @ref Catalog::saveTempFile ).
+ *
+ * @param msgOnlyAtError flag, if a message should be shown, only if
+ * a error occured.
+ * @param question flag, if only a information about the result should
+ * be shown or a question, whether the user wants to continue or cancel
+ *
+ * @return true, if no error occured or if an error occured but the user
+ * wants to continue anyway.
+ */
+ bool checkSyntax(bool msgOnlyAtError, bool question);
+
+ /**
+ * this is called from the catalog when updating his views.
+ * reimplemented from @ref CatalogView
+ * @param cmd the edit command that has been applied
+ */
+ virtual void update(KBabel::EditCommand* cmd, bool undo=false);
+
+ KBCatalog* catalog() const{return _catalog;}
+
+ void processUriDrop(KURL::List& uriList, const QPoint & pos);
+
+ /**
+ * checks the status of the displayed entry: last, first, fuzzy,...
+ * and emits the appropriate signals
+ */
+ void emitEntryState();
+
+ void setRMBEditMenu(QPopupMenu*);
+ void setRMBSearchMenu(QPopupMenu*);
+ void setTagsMenu(QPopupMenu*);
+ void setArgsMenu(QPopupMenu*);
+
+ QPtrList<ModuleInfo> dictionaries();
+ KBabelDictBox* searchView() { return dictBox; }
+
+ bool autoDiffEnabled() const {return _diffEnabled;}
+
+public slots:
+
+ void gotoEntry(const KBabel::DocPosition& pos, bool updateHistory=true);
+
+ /** opens a filedialog and asks for an url */
+ void open();
+ void open(const KURL& url, const QString & package=QString::null, bool checkModified=true, bool newView=false);
+ void setFilePackage();
+ void revertToSaved();
+
+ void updateSettings();
+ void updateProjectSettings();
+
+ void undo();
+ void redo();
+ void textCut();
+ void textCopy();
+ void textPaste();
+ bool findNext();
+ bool findPrev();
+ void find();
+ void findInFile(QCString fileSource, KBabel::FindOptions options);
+ void replaceInFile(QCString fileSource, KBabel::ReplaceOptions options);
+ void replace();
+ void selectAll();
+ void deselectAll();
+ void clear();
+ void msgid2msgstr();
+ void search2msgstr();
+ void plural2msgstr();
+ void gotoFirst();
+ void gotoLast();
+ void gotoNext();
+ void gotoPrev();
+ void gotoEntry();
+ void gotoNextFuzzyOrUntrans();
+ void gotoPrevFuzzyOrUntrans();
+ void gotoNextFuzzy();
+ void gotoPrevFuzzy();
+ void gotoNextUntranslated();
+ void gotoPrevUntranslated();
+ void gotoNextError();
+ void gotoPrevError();
+
+ void forwardHistory();
+ void backHistory();
+
+ void spellcheckAll();
+ void spellcheckAllMulti();
+ void spellcheckFromCursor();
+ void spellcheckCurrent();
+ void spellcheckFromCurrent();
+ void spellcheckMarked();
+ void spellcheckCommon();
+
+ void roughTranslation();
+ void diff();
+ void toggleAutoDiff(bool on);
+ void diffShowOrig();
+ bool openDiffFile();
+ void insertNextTag();
+ void insertNextTagMsgid();
+ void insertNextArg();
+ void insertTagFromTool( const QString& tag );
+ void showTagsMenu();
+ void showArgsMenu();
+ void skipToNextTag();
+ void skipToPreviousTag();
+ void skipToTagFromTool(int index);
+ void wordCount();
+
+ void removeFuzzyStatus();
+ /** opens the header editor for the po-file */
+ void editHeader();
+
+ /** checks the syntax of the file by using msgftm */
+ bool checkSyntax();
+
+ /**
+ * perform all checks listed above
+ */
+ bool checkAll();
+
+ void stopSearch();
+ void startSearch();
+ void startSelectionSearch();
+ void startSearch(const QString id);
+ void startSelectionSearch(const QString id);
+
+ void configureDictionary(const QString id);
+ void editDictionary(const QString id);
+ void aboutDictionary(const QString id);
+
+ /**
+ * this was originally protected, but we need this to expose for
+ * KBabelMW forwarding
+ */
+ virtual void wheelEvent(QWheelEvent*);
+
+protected:
+ virtual void dragEnterEvent(QDragEnterEvent *event);
+ virtual void dropEvent(QDropEvent *event);
+ virtual bool eventFilter(QObject*, QEvent* event);
+
+signals:
+ /** emited when a fuzzy catalogentry is shown */
+ void signalFuzzyDisplayed(bool);
+ /** emited when a untranslated catalogentry is shown */
+ void signalUntranslatedDisplayed(bool);
+ void signalFaultyDisplayed(bool);
+ /** emited when the first catalogentry is shown */
+ void signalFirstDisplayed(bool firstEntry, bool firstForm);
+ /** emited when the last catalog entry is shown */
+ void signalLastDisplayed(bool lastEntry, bool lastForm);
+
+ void signalNextTag( int index );
+
+ /**
+ * emited when a new entry is shown
+ * pos: position (index and plural form) of the currently shown entry
+ */
+ void signalDisplayed(const KBabel::DocPosition& pos);
+
+ /**
+ * emited when new entry is displayed and there is no
+ * fuzzy entry afterwards in the catalog
+ */
+ void signalFuzzyAfterwards(bool);
+ /**
+ * emited when new entry is displayed and there is no
+ * fuzzy entry in front of it in the catalog
+ */
+ void signalFuzzyInFront(bool);
+ /**
+ * emited when new entry is displayed and there is no
+ * untranslated entry afterwards in the catalog
+ */
+ void signalUntranslatedAfterwards(bool);
+ /**
+ * emited when new entry is displayed and there is no
+ * fuzzy entry in fornt of it in the catalog
+ */
+ void signalUntranslatedInFront(bool);
+
+ void signalErrorAfterwards(bool);
+ void signalErrorInFront(bool);
+
+ /**
+ * Use this signal to change the content of the statusbar
+ */
+ void signalChangeStatusbar(const QString& text);
+ /**
+ * Use this signal to change the content of the caption
+ */
+ void signalChangeCaption(const QString& text);
+
+ void signalNewFileOpened(KURL url);
+
+ void signalResetProgressBar(QString,int);
+ void signalProgress(int);
+ void signalClearProgressBar();
+
+ void signalSearchActive(bool);
+
+ void signalDiffEnabled(bool);
+
+ void signalForwardHistory(bool have);
+ void signalBackHistory(bool have);
+
+ void ledColorChanged(const QColor& color);
+
+ void signalDictionariesChanged();
+
+ void signalMsgstrChanged();
+
+ void signalNextTagAvailable(bool);
+ void signalTagsAvailable(bool);
+
+ void signalNextArgAvailable(bool);
+ void signalArgsAvailable(bool);
+
+ void signalCursorPosChanged(int line, int col);
+
+ void signalSpellcheckDone(int result);
+
+ void signalCopy();
+ void signalCut();
+ void signalPaste();
+ void signalSelectAll();
+
+private:
+ /**
+ * inserts the content of the current catalog entry into
+ * the fields in the view
+ * @param delay flag, if the auto search should be started delayed
+ * this is useful when a new file is opened
+ * @param formID number of the plural form to be displayed. Use 0 for
+ * no plural form
+ */
+ void updateEditor(int formID=0, bool delay=false);
+
+ void initDockWidgets();
+
+ void startSearch(bool delay);
+
+ /**
+ * makes some checks like checkings arguments and accels etc
+ * @param onlyWhenChanged flag, if message should only be shown
+ * when status changed
+ */
+ void autoCheck(bool onlyWhenChanged);
+
+ /**
+ * Create instances of tools currently setup for autochecks
+ */
+ void setupAutoCheckTools();
+
+ /**
+ * internal function to find next string given with @ref FindDialog
+ * starting at position pos
+ * @return true, if search was successful
+ */
+ bool findNext_internal(KBabel::DocPosition& pos, bool forReplace=false, bool mark=true);
+ /**
+ * internal function to find previous string given with @ref FindDialog
+ * starting at position pos
+ * @return true, if search was successful
+ */
+ bool findPrev_internal(KBabel::DocPosition& pos, bool forReplace=false, bool mark=true);
+
+ /**
+ * makes the real work
+ * @param autoDiff flag, if called from @ref autoDiff()
+ */
+ void diffInternal(bool autoDiff);
+
+ /**
+ * @param autoDiff flag, if called from @ref autoDiff()
+ */
+ bool openDiffFile(bool autoDiff);
+
+ /**
+ * Inserts a text into the msgstr (into the current form) using undoable commands.
+ * if @param clearFirst is set to true, it will clear the contents of msgstr before inserting
+ */
+ void modifyMsgstrText(const uint offset, const QString& text, bool clearFirst=false);
+
+protected slots:
+ bool validateUsingTool( const KDataToolInfo & info, const QString & command );
+ void modifyUsingTool( const KDataToolInfo & info, const QString & command );
+ void modifyCatalogUsingTool( const KDataToolInfo & info, const QString & command );
+
+private slots:
+ void msgstrPluralFormChanged (uint index);
+ void autoRemoveFuzzyStatus();
+
+ /** connected to the catalog. it is called when a new file is opened*/
+ void newFileOpened(bool readOnly);
+
+ void showError(const QString& message);
+
+ void toggleFuzzyLed(bool on);
+ void toggleUntransLed(bool on);
+ void toggleErrorLed(bool on);
+
+ void forwardMsgstrEditCmd(KBabel::EditCommand*);
+
+ /**
+ * called from a signal from ReplaceDialog to replace the
+ * current found string. After that it searches the next string
+ */
+ void replaceNext();
+ /**
+ * called from a signal from ReplaceDialog to replace
+ * all without asking anymore.
+ */
+ void replaceAll();
+ /**
+ * called from a signal from ReplaceDialog to go to next
+ * string to replace
+ */
+ void findNextReplace();
+
+ /**
+ * makes some checks like checkings arguments and accels etc
+ */
+ void autoCheck();
+
+ void autoDiff();
+
+ /**
+ * called, when text in msgstrEdit changes to inform
+ * the dictionary about the changes
+ */
+ void informDictionary();
+ void setNewLanguage();
+
+ void forwardProgressStart(const QString& msg);
+ void forwardSearchStart();
+ void forwardSearchStop();
+
+ /**
+ * checks if there is are fuzzy entries in front or behind
+ * the current entry and emits the appropriate signals
+ */
+ void checkFuzzies();
+ /**
+ * checks if there is are untranslated entries in front or behind
+ * the current entry and emits the appropriate signals
+ */
+ void checkUntranslated();
+
+ /** inserts the nth tag from the available tags into msgstr*/
+ void insertTag(int n);
+
+ /** visually display the tag to be inserted next */
+ void selectTag();
+
+ void updateTags();
+
+ /** inserts the nth argument from the available arguments into msgstr*/
+ void insertArg(int n);
+
+ void updateArgs();
+ void insertChar(QChar ch);
+
+ void showTryLaterMessageBox();
+
+ void dummy(KSpell*) {}
+
+private:
+ static QPtrList<KBabelView> *viewList;
+
+ HidingMsgEdit* msgstrEdit;
+ HidingMsgEdit* msgidLabel;
+ KBabelDictBox* dictBox;
+ GotoDialog* _gotoDialog;
+ FindDialog* _findDialog;
+ FindDialog* _replaceDialog;
+ ReplaceDialog* _replaceAskDialog;
+
+ QPopupMenu* _dropMenu;
+
+ KLed* _fuzzyLed;
+ KLed* _untransLed;
+ KLed* _errorLed;
+
+ KBCatalog* _catalog;
+ uint _currentIndex;
+ KBabel::DocPosition _currentPos;
+
+ KBabel::SpellcheckSettings _spellcheckSettings;
+
+ bool _autoSearchTempDisabled;
+
+ QValueList<uint> _backHistory;
+ QValueList<uint> _forwardHistory;
+
+ // flag to not beep, when switching to the next entry, because
+ // go -> next or prev entry was used.
+ bool _dontBeep;
+
+ /**
+ * position in document were find or replace function
+ * started to search
+ */
+ KBabel::DocPosition _findStartPos;
+ /**
+ * the string that was marked during the last search
+ */
+ QString _lastFoundString;
+
+ /*
+ * flag, if internal find functions should break at end or ask for
+ * beginning at the other end of the document
+ */
+ bool _findBreakAtEnd;
+
+ /*
+ * flag, if we search backwards and the direction was already
+ * changed (see findNext and findPrev)
+ */
+ bool _redirectedBackSearch;
+
+ bool _showTryLaterBox;
+
+ KBabel::DocPosition _replacePos;
+ int _replaceLen;
+ int _replacesTotal;
+ bool _replaceWasAtEnd;
+ /** contains the diff to the offset, where we started to search */
+ int _replaceExtraOffset;
+
+ /** appId for a source of the next files to be searched */
+ QCString _fileSource;
+
+ QStringList _tags;
+ QPopupMenu *_tagsMenu;
+
+ QStringList _args;
+ QPopupMenu *_argsMenu;
+
+ bool _diffEnabled;
+ bool _loadingDiffFile;
+ bool _diffing;
+
+ /*
+ * flag, set if editing KDE documentation PO-file
+ */
+ bool _editingDocumentation;
+ QPtrList<KDataTool> _autocheckTools;
+
+//spellcheck things
+private:
+ struct Position
+ {
+ uint index;
+ uint form;
+ uint pos;
+ uint end;
+ };
+
+ enum SpellWhat{All,AllMulti,Current,Marked,Begin,End,BeginCurrent};
+
+ struct
+ {
+ KSpell *kspell;
+ KSpellConfig* config;
+ QStringList wordList;
+ bool active;
+ int misspelled;
+ int replaced;
+ int posCorrection;
+ uint lastIndex;
+ QPtrList<Position> posDict;
+ SpellWhat what2Check;
+
+ // the last word, that was misspelled
+ uint lastPos;
+ // the position correction in the last word.
+ // needed if words with '-' are treated as seperate words
+ int inWordCorrection;
+
+ QStringList origWords;
+ QStringList newWords;
+
+ QStringList ignoreList;
+ QStringList newIgnoreList;
+ } spell;
+
+ struct {
+ KSpell *kspell;
+ KSpellConfig* config;
+ } spell2; // on-the-fly spellchecking
+
+ //DictSpellChecker * flyspell;
+
+
+ /**
+ * Marks a misspelled word in the editor.
+ * After that, the cursor is at the beginning of the
+ * marked text
+ * @param orig the original word as given from KSpell
+ * @param pos the position of the word in the StringList
+ * spell.wordList
+ *
+ * @returns false, if the there is a synchronization error,
+ * means the word has not been found in the editor.
+ */
+ bool markMisspelled(const QString &orig, unsigned int pos);
+
+private slots:
+ void spellcheck();
+ void cancelSpellcheck();
+ void spellStart(KSpell*);
+ void spellMisspelled(const QString &orig, const QStringList &sug, unsigned int pos);
+ void spellCorrected(const QString &orig, const QString &newWord, unsigned int pos);
+ void spellResult(bool);
+ void spellCleanDone();
+ void spellAddIgnore(const QString &);
+ // initialize spellchecking struct
+ void cleanUpSpellStruct();
+ void slotAutoSaveTimeout( );
+
+private:
+ void addSpellcheckWords(uint pos, QString text, uint index, uint form);
+
+private:
+ // configuration file
+ KSharedConfig::Ptr _config;
+ // project file
+ KBabel::Project::Ptr _project;
+
+ KBabel::RegExpExtractor* _tagExtractor;
+ KBabel::RegExpExtractor* _argExtractor;
+
+ QTimer * autoSaveTimer;
+ int _autoSaveDelay;
+
+ int _currentTag;
+
+ KBabelMW* m_mainwindow;
+ CommentView* m_commentview;
+ ContextView* m_contextview;
+ KBCatalogListView* m_cataloglistview;
+
+ CharacterSelectorView* m_charselectorview;
+ TagListView* m_taglistview;
+ SourceView* m_sourceview;
+
+ bool m_overwrite;
+};
+
+#endif // KBABELVIEW_H
diff --git a/kbabel/kbabel/kbabelview2.cpp b/kbabel/kbabel/kbabelview2.cpp
new file mode 100644
index 00000000..c07990d0
--- /dev/null
+++ b/kbabel/kbabel/kbabelview2.cpp
@@ -0,0 +1,1025 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2002-2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#include <kdatatool.h>
+#include <kdebug.h>
+#include <kfiledialog.h>
+#include <kinputdialog.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <knotifyclient.h>
+#include <kurl.h>
+#include <kio/netaccess.h>
+
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qmessagebox.h>
+#include <qpopupmenu.h>
+#include <qvbox.h>
+
+#include "catalogsettings.h"
+#include "editcmd.h"
+#include "tagextractor.h"
+#include "kbabelview.h"
+#include "kbabeldictbox.h"
+#include "mymultilineedit.h"
+#include "hidingmsgedit.h"
+#include "roughtransdlg.h"
+#include "kbabelsettings.h"
+#include "kbprojectsettings.h"
+
+#include "resources.h"
+
+using namespace KBabel;
+
+QPtrList<ModuleInfo> KBabelView::dictionaries()
+{
+ QPtrList<ModuleInfo> list = dictBox->moduleInfos();
+
+ return list;
+}
+
+void KBabelView::configureDictionary(const QString id)
+{
+ dictBox->configure(id);
+}
+
+void KBabelView::editDictionary(const QString id)
+{
+ dictBox->edit(id);
+}
+
+
+void KBabelView::aboutDictionary(const QString id)
+{
+ dictBox->aboutModule(id);
+}
+
+void KBabelView::informDictionary()
+{
+ if( isSearching () )
+ stopSearch ();
+
+ if( msgstrEdit->isModified() )
+ dictBox->setTextChanged(_catalog->msgid(_currentIndex,true)
+ ,*(_catalog->msgstr(_currentIndex).at(msgstrEdit->currentForm()))
+ ,msgstrEdit->currentForm()
+ ,_catalog->comment(_currentIndex));
+}
+
+void KBabelView::setNewLanguage()
+{
+ IdentitySettings s = _catalog->identitySettings();
+
+ dictBox->setLanguage(s.languageCode, s.languageName);
+
+ // setup new plural form number
+ int form = msgstrEdit->currentForm();
+ if( form >= s.numberOfPluralForms )
+ form = s.numberOfPluralForms-1;
+
+ msgstrEdit->setNumberOfPlurals (s.numberOfPluralForms);
+ updateSettings();
+
+ if (! _catalog->currentURL().isEmpty())
+ {
+ updateEditor( form );
+ }
+}
+
+
+void KBabelView::wheelEvent(QWheelEvent *e)
+{
+ if( _catalog->numberOfEntries() == 0 ) return;
+
+ if( (e->state() & ControlButton) && (e->state() & AltButton))
+ {
+ if(e->delta() > 0)
+ {
+ gotoPrevFuzzyOrUntrans();
+ }
+ else
+ {
+ gotoNextFuzzyOrUntrans();
+ }
+ }
+ else if(e->state() & ControlButton)
+ {
+ if(e->delta() > 0)
+ {
+ gotoPrevFuzzy();
+ }
+ else
+ {
+ gotoNextFuzzy();
+ }
+ }
+ else if(e->state() & AltButton)
+ {
+ if(e->delta() > 0)
+ {
+ gotoPrevUntranslated();
+ }
+ else
+ {
+ gotoNextUntranslated();
+ }
+ }
+ else
+ {
+ if(e->delta() > 0)
+ {
+ gotoPrev();
+ }
+ else
+ {
+ gotoNext();
+ }
+ }
+
+ e->accept();
+}
+
+
+
+void KBabelView::roughTranslation()
+{
+ RoughTransDlg *dlg = new RoughTransDlg(dictBox, _catalog, this
+ , "roughtransDlg");
+
+ dlg->exec();
+
+ delete dlg;
+}
+
+
+void KBabelView::updateTags()
+{
+ bool hadTags = _tags.count() > 0;
+
+ _tags = _catalog->tagList(_currentIndex);
+
+ if(_tagsMenu)
+ {
+ _tagsMenu->clear();
+
+ QStringList tList;
+ QStringList::Iterator it;
+ int counter=0;
+ for(it=_tags.begin(); it!=_tags.end(); ++it)
+ {
+ QString s = *it;
+ if( s.startsWith("&") ) s = "&"+s;
+ if(!tList.contains(s))
+ {
+ _tagsMenu->insertItem(s,counter);
+ tList.append(s);
+ }
+ counter++;
+ }
+ }
+
+ bool haveTags = (_tags.count() > 0);
+
+ if(isReadOnly())
+ haveTags=false;
+
+ if(haveTags != hadTags)
+ {
+ emit signalNextTagAvailable(haveTags);
+ emit signalTagsAvailable(haveTags);
+ }
+
+ _currentTag = 0;
+
+ if(haveTags)
+ {
+ _tagExtractor->setString(_catalog->msgid(_currentIndex).first());
+ }
+ // if there is no tag, it will set invalid tag
+ selectTag();
+}
+
+void KBabelView::skipToNextTag()
+{
+ if( (uint)_currentTag >= _tags.count()-1 ) return;
+ ++_currentTag;
+ selectTag();
+}
+
+void KBabelView::skipToPreviousTag()
+{
+ if( _currentTag == 0 ) return;
+ --_currentTag;
+ selectTag();
+}
+
+void KBabelView::selectTag()
+{
+ if( _tagExtractor->countMatches() == 0 ) {
+ // no tags, select none
+ kdDebug() << "No tags" << endl;
+ msgidLabel->selectTag(0,0);
+ return;
+ }
+
+ // count number of eofs in tag
+ uint diff=0;
+ // FIXME: what about plural forms
+ QString msgid = _catalog->msgid(_currentIndex).first();
+
+ for( uint i = _tagExtractor->matchIndex(_currentTag); i < _tagExtractor->matchIndex(_currentTag)+_tags[_currentTag].length()+1; i++ )
+ {
+ if( msgid[i] == '\n' ) diff++;
+ }
+ msgidLabel->selectTag(_tagExtractor->matchIndex(_currentTag),_tags[_currentTag].length()+diff);
+ emit signalNextTag (_currentTag);
+}
+
+void KBabelView::setTagsMenu(QPopupMenu *menu)
+{
+ _tagsMenu=menu;
+
+ connect(_tagsMenu,SIGNAL(activated(int)),this,SLOT(insertTag(int)));
+}
+
+void KBabelView::modifyMsgstrText(const uint offset, const QString& text, bool clearFirst)
+{
+ _catalog->applyBeginCommand( _currentIndex, Msgstr ,this);
+
+ if( clearFirst ) msgstrEdit->clear();
+
+ InsTextCmd* insCmd = new InsTextCmd(offset,text,msgstrEdit->currentForm());
+ insCmd->setPart(Msgstr);
+ insCmd->setIndex(_currentIndex);
+
+ msgstrEdit->processCommand(insCmd,false);
+ forwardMsgstrEditCmd(insCmd);
+
+ _catalog->applyEndCommand(_currentIndex, Msgstr,this);
+
+ autoCheck( true ); // check it NOW - it should not be needed, but it is, I don't know why :-(
+}
+
+void KBabelView::insertTag(int n)
+{
+ QString tag = _tagsMenu->text(n);
+ if( tag.startsWith( "&&" ) ) tag = tag.remove(0,1); // replace && -> &. && is used for correct menu display
+
+ modifyMsgstrText( msgstrEdit->currentIndex(), tag );
+}
+
+void KBabelView::insertNextTag()
+{
+ if(_currentTag >= (int)_tags.count())
+ {
+ KNotifyClient::beep();
+ return;
+ }
+
+ int offset = msgstrEdit->currentIndex();
+
+ _currentTag++;
+ selectTag();
+
+ modifyMsgstrText( offset, _tags[_currentTag-1] );
+}
+
+void KBabelView::insertNextTagMsgid()
+{
+ TagExtractor extractor;
+
+ int offset = msgstrEdit->beginOfLastMarkedText(); //msgstrEdit->currentIndex();
+
+ QString s = (*_catalog->msgstr(_currentIndex).at(msgstrEdit->currentForm())).left(offset);
+
+ QString t;
+
+ if( _catalog->pluralForm( _currentIndex ) == KDESpecific )
+ {
+ int pos = msgstrEdit->currentIndex();
+ int currentFormBegin=s.findRev("\\n",pos);
+ if( currentFormBegin == -1 ) currentFormBegin=0;
+ else currentFormBegin+=3; // skip the newline
+ int currentFormEnd=s.find("\\n",pos);
+ if( currentFormEnd == -1 ) currentFormEnd=s.length();
+
+ s=s.mid(currentFormBegin,currentFormEnd-currentFormBegin);
+ }
+
+ extractor.setString(s);
+ uint num= extractor.countMatches();
+ if(num >= _tags.count())
+ {
+ KNotifyClient::beep();
+ return;
+ }
+
+ t=_tags[num];
+
+ modifyMsgstrText( offset, t );
+}
+
+void KBabelView::showTagsMenu()
+{
+ if(_tagsMenu && _tags.count() > 0)
+ {
+ int y=msgstrEdit->height()/2;
+ int x=msgstrEdit->width()/2;
+ _tagsMenu->exec(msgstrEdit->mapToGlobal( QPoint(x,y) ) );
+
+ return;
+ }
+}
+
+
+void KBabelView::updateArgs()
+{
+ bool hadArgs = _args.count() > 0;
+
+ _args = _catalog->argList(_currentIndex);
+
+ if(_argsMenu)
+ {
+ _argsMenu->clear();
+
+ QStringList tList;
+ QStringList::Iterator it;
+ int counter=0;
+ for(it=_args.begin(); it!=_args.end(); ++it)
+ {
+ QString s = *it;
+ if(!tList.contains(s))
+ {
+ _argsMenu->insertItem(s,counter);
+ tList.append(s);
+ }
+ counter++;
+ }
+ }
+
+ bool haveArgs = (_args.count() > 0);
+
+ if(isReadOnly())
+ haveArgs=false;
+
+ if(haveArgs != hadArgs)
+ {
+ emit signalNextArgAvailable(haveArgs);
+ emit signalArgsAvailable(haveArgs);
+ }
+}
+
+void KBabelView::setArgsMenu(QPopupMenu *menu)
+{
+ _argsMenu=menu;
+
+ connect(_argsMenu,SIGNAL(activated(int)),this,SLOT(insertArg(int)));
+}
+
+
+void KBabelView::insertArg(int n)
+{
+ QString arg = _argsMenu->text(n);
+
+ modifyMsgstrText( msgstrEdit->currentIndex(), arg );
+}
+
+void KBabelView::insertNextArg()
+{
+ int offset = msgstrEdit->currentIndex();
+
+ QString s = (*_catalog->msgstr(_currentIndex).at(msgstrEdit->currentForm())).left(offset);
+
+ if( _catalog->pluralForm( _currentIndex ) == KDESpecific )
+ {
+ int pos = msgstrEdit->currentIndex();
+ int currentFormBegin=s.findRev("\\n",pos);
+ if( currentFormBegin == -1 ) currentFormBegin=0;
+ else currentFormBegin+=3; // skip the newline
+ int currentFormEnd=s.find("\\n",pos);
+ if( currentFormEnd == -1 ) currentFormEnd=s.length();
+
+ s=s.mid(currentFormBegin,currentFormEnd-currentFormBegin);
+ }
+
+ _argExtractor->setString(s);
+ uint num=_argExtractor->countMatches();
+ if(num >= _args.count())
+ {
+ KNotifyClient::beep();
+ return;
+ }
+
+ QString t=_args[num];
+
+ modifyMsgstrText( offset,t );
+}
+
+void KBabelView::showArgsMenu()
+{
+ if(_argsMenu && _args.count() > 0)
+ {
+ int y=msgstrEdit->height()/2;
+ int x=msgstrEdit->width()/2;
+ _argsMenu->exec(msgstrEdit->mapToGlobal( QPoint(x,y) ) );
+
+ return;
+ }
+}
+
+
+void KBabelView::diff()
+{
+ diffInternal(false);
+ msgstrEdit->setFocus();
+}
+
+void KBabelView::diffShowOrig()
+{
+ msgidLabel->setText(_catalog->msgid(_currentIndex));
+ msgidLabel->forceUpdate();
+ msgstrEdit->setFocus();
+}
+
+void KBabelView::toggleAutoDiff(bool on)
+{
+ if(on != _diffEnabled)
+ {
+ _diffEnabled = on;
+
+ if(on)
+ {
+ diff();
+ }
+ else
+ {
+ diffShowOrig();
+ }
+ }
+}
+
+void KBabelView::autoDiff()
+{
+ diffInternal(true);
+}
+
+void KBabelView::diffInternal(bool autoDf)
+{
+ if(_diffing || _loadingDiffFile)
+ {
+ return;
+ }
+
+ _diffing = true;
+ uint diffIndex = _currentIndex;
+
+ QString diffString;
+
+ Catalog::DiffResult r = _catalog->diff(_currentIndex, &diffString);
+
+ if(r == Catalog::DiffNeedList)
+ {
+ switch( _project->settings()->useDBForDiff() )
+ {
+ case 1:
+ {
+ _loadingDiffFile=true;
+ bool wasEnabled=_diffEnabled;
+ _diffEnabled=false;
+
+ QValueList<DiffEntry> diffList;
+ QString error;
+ QString package = _catalog->packageName()+".po";
+ kdDebug(KBABEL) << "getting list for " << package << endl;
+
+ if(dictBox->messagesForPackage(package,diffList,error))
+ {
+ kdDebug(KBABEL) << "got " << diffList.count()
+ << " messages" << endl;
+ _catalog->setDiffList(diffList);
+ }
+ else
+ {
+ KMessageBox::sorry(this
+ ,i18n("An error occurred while trying to get the list "
+ "of messages for this file from the database:\n"
+ "%1").arg(error));
+
+ _diffing=false;
+ _diffEnabled=false;
+ _loadingDiffFile=false;
+ emit signalDiffEnabled(false);
+
+ return;
+ }
+
+ _diffEnabled=wasEnabled;
+ _loadingDiffFile=false;
+ break;
+ }
+ case 0:
+ {
+ _diffing=false;
+ if(!openDiffFile(true))
+ {
+ _diffEnabled=false;
+ emit signalDiffEnabled(false);
+
+ _diffing=false;
+ return;
+ }
+
+ _diffing = true;
+ break;
+ }
+ case 2:
+ {
+ // get the list of all entries
+ QValueList<DiffEntry> diffList = _catalog->asDiffList();
+
+ QValueList<DiffEntry> resultList;
+
+ // swap msgstr and msgid
+ QValueList<DiffEntry>::iterator it;
+ DiffEntry entry;
+
+ for ( it = diffList.begin(); it != diffList.end(); ++it )
+ {
+ entry.msgstr = (*it).msgid;
+ // if there is no translation, do not show difference
+ if( !(*it).msgstr.isEmpty() )
+ {
+ entry.msgid = (*it).msgstr;
+ }
+ else
+ {
+ entry.msgid = (*it).msgid;
+ }
+ resultList.append(entry);
+ }
+
+ // set as a source for diff
+ _catalog->setDiffList(resultList);
+
+ _diffing=false;
+ _diffEnabled=true;
+ _loadingDiffFile=false;
+ emit signalDiffEnabled(true);
+ }
+ }
+
+ diffIndex = _currentIndex;
+ r = _catalog->diff(_currentIndex, &diffString);
+ }
+
+ // if the index changed in the meanwhile
+ while(diffIndex != _currentIndex)
+ {
+ diffIndex=_currentIndex;
+ r = _catalog->diff(_currentIndex,&diffString);
+ }
+
+ if(r == Catalog::DiffOk)
+ {
+ msgidLabel->setText(diffString);
+ msgidLabel->forceUpdate();
+
+ // FIXME: should care about plural forms
+ if(diffString == _catalog->msgid(_currentIndex).first() )
+ {
+ emit signalChangeStatusbar(i18n("No difference found"));
+ }
+ else
+ {
+ emit signalChangeStatusbar(i18n("Difference found"));
+ }
+ }
+ else
+ {
+ if(!autoDf)
+ {
+ KMessageBox::information(this
+ ,i18n("No corresponding message found."));
+ }
+ else
+ {
+ emit signalChangeStatusbar(
+ i18n("No corresponding message found"));
+ }
+ }
+
+ _diffing = false;
+}
+
+bool KBabelView::openDiffFile()
+{
+ return openDiffFile(false);
+}
+
+bool KBabelView::openDiffFile(bool autoDiff)
+{
+ if(_diffing || _loadingDiffFile)
+ return false;
+
+ KURL url;
+
+ if( autoDiff && ! _project->settings()->diffBaseDir().isEmpty() )
+ {
+ KURL fileURL = _catalog->currentURL();
+
+ KURL poBaseURL( _project->catManSettings().poBaseDir );
+
+ QString poBase = poBaseURL.path();
+ int len = poBase.length();
+ if(fileURL.path().left(len) == poBase)
+ {
+ QString fileRelPath = fileURL.path().mid(len);
+ if(fileRelPath[0] == '/')
+ fileRelPath=fileRelPath.mid(1);
+
+ if(_project->settings()->diffBaseDir().right(1) != "/")
+ _project->settings()->diffBaseDir() += '/';
+
+ QString diffFilePath = _project->settings()->diffBaseDir() + fileRelPath;
+
+
+ KURL diffFileURL(diffFilePath);
+
+ if(diffFileURL.isValid() && KIO::NetAccess::exists(diffFileURL,true,NULL))
+ {
+ url = diffFileURL;
+
+ kdDebug(KBABEL) << "using file " << diffFileURL.prettyURL()
+ << " as diff file" << endl;
+ }
+ }
+ }
+
+
+ if(url.isEmpty())
+ {
+ url = KFileDialog::getOpenURL(_project->settings()->diffBaseDir(),
+"application/x-gettext", this, i18n("Select File to Diff With"));
+ }
+
+ if(url.isEmpty())
+ return false;
+
+ _loadingDiffFile=true;
+ bool wasEnabled=_diffEnabled;
+ _diffEnabled=false;
+
+
+ Catalog cat;
+
+ connect(&cat,SIGNAL(signalProgress(int)),this,SIGNAL(signalProgress(int)));
+ emit signalResetProgressBar(i18n("loading file for diff"),100);
+
+ ConversionStatus stat = cat.openURL(url);
+
+ emit signalClearProgressBar();
+
+
+ if(stat != OK && stat != RECOVERED_PARSE_ERROR)
+ {
+ switch(stat)
+ {
+ case PARSE_ERROR:
+ {
+ KMessageBox::sorry(this
+ ,i18n("Error while trying to read file:\n %1\n"
+ "Maybe it is not a valid PO file.").arg(url.prettyURL()));
+ break;
+ }
+ case NO_PERMISSIONS:
+ {
+ KMessageBox::sorry(this,i18n(
+ "You do not have permissions to read file:\n %1")
+ .arg(url.prettyURL()));
+ break;
+ }
+ case NO_FILE:
+ {
+ KMessageBox::sorry(this,i18n(
+ "You have not specified a valid file:\n %1")
+ .arg(url.prettyURL()));
+ break;
+ }
+ case NO_PLUGIN:
+ {
+ KMessageBox::error(this,i18n(
+ "KBabel cannot find a corresponding plugin for the MIME type of the file:\n %1").arg(url.prettyURL()));
+ break;
+ }
+ case UNSUPPORTED_TYPE:
+ {
+ KMessageBox::error(this,i18n(
+ "The import plugin cannot handle this type of the file:\n %1").arg(url.prettyURL()));
+ break;
+ }
+ default:
+ {
+ KMessageBox::sorry(this,i18n(
+ "Error while trying to open file:\n %1")
+ .arg(url.prettyURL()));
+ break;
+ }
+
+ }
+
+ _diffEnabled=wasEnabled;
+ _loadingDiffFile=false;
+
+ return false;
+ }
+
+ _catalog->setDiffList( cat.asDiffList() );
+
+ _diffEnabled=wasEnabled;
+ _loadingDiffFile=false;
+
+ return true;
+}
+
+void KBabelView::showTryLaterMessageBox()
+{
+ if( !_showTryLaterBox ) return;
+
+ KDialogBase *dialog= new KDialogBase(
+ i18n("Information"),
+ KDialogBase::Yes,
+ KDialogBase::Yes, KDialogBase::Yes,
+ this, "information", true, true,
+ KStdGuiItem::ok() );
+
+ QVBox *topcontents = new QVBox (dialog);
+ topcontents->setSpacing(KDialog::spacingHint()*2);
+ topcontents->setMargin(KDialog::marginHint()*2);
+
+ QWidget *contents = new QWidget(topcontents);
+ QHBoxLayout * lay = new QHBoxLayout(contents);
+ lay->setSpacing(KDialog::spacingHint()*2);
+
+ lay->addStretch(1);
+ QLabel *label1 = new QLabel( contents);
+ label1->setPixmap(QMessageBox::standardIcon(QMessageBox::Information));
+ lay->add( label1 );
+ QLabel *label2 = new QLabel( i18n("The search string has not been found yet.\n"
+ "However, the string might be found "
+ "in the files being searched at the moment.\n"
+ "Please try later."), contents);
+ label2->setAlignment( Qt::AlignAuto | Qt::AlignVCenter | Qt::ExpandTabs | Qt::WordBreak );
+ label2->setMinimumSize(label2->sizeHint());
+ lay->add( label2 );
+ lay->addStretch(1);
+
+ QCheckBox *checkbox = new QCheckBox(i18n("Do not show in this find/replace session again"), topcontents);
+
+ dialog->setMainWidget(topcontents);
+ dialog->enableButtonSeparator(false);
+ dialog->incInitialSize( QSize(50,0) );
+
+ dialog->exec();
+
+ _showTryLaterBox = !checkbox->isChecked();
+ delete dialog;
+}
+
+void KBabelView::setFilePackage()
+{
+ bool result=false;
+ QString p = KInputDialog::getText(QString::null, i18n("Enter new package for the current file:"),_catalog->package(),&result,this);
+ if( result )
+ {
+ _catalog->setPackage(p);
+ emit signalChangeCaption(p);
+ }
+}
+
+void KBabelView::insertTagFromTool( const QString& tag )
+{
+ modifyMsgstrText(msgstrEdit->currentIndex(),tag);
+
+ msgstrEdit->setFocus();
+}
+
+void KBabelView::skipToTagFromTool( int index )
+{
+ _currentTag = index;
+ selectTag();
+}
+
+void KBabelView::plural2msgstr()
+{
+ int currentFormBegin, currentFormEnd, pos;
+ uint i;
+
+ QStringList msgs = _catalog->msgstr(_currentIndex);
+ QString text= *msgs.at(msgstrEdit->currentForm());
+ uint numForms = _catalog->numberOfPluralForms(_currentIndex);
+
+ if( text.isEmpty() || _catalog->pluralForm(_currentIndex) == NoPluralForm) return;
+
+
+ QString result;
+
+ switch( _catalog->pluralForm(_currentIndex) )
+ {
+ case Gettext:
+
+ _catalog->applyBeginCommand( _currentIndex, Msgstr ,this);
+
+ i=0;
+ for( QStringList::Iterator it=msgs.begin() ; it!=msgs.end() ; ++it )
+ {
+ if( i!= msgstrEdit->currentForm() )
+ {
+ // clear first
+ DelTextCmd* insCmd = new DelTextCmd(0,(*it),i);
+ insCmd->setPart(Msgstr);
+ insCmd->setIndex(_currentIndex);
+ msgstrEdit->processCommand(insCmd,false);
+ forwardMsgstrEditCmd(insCmd);
+
+ // insert text
+ insCmd = new InsTextCmd(0,text,i);
+ insCmd->setPart(Msgstr);
+ insCmd->setIndex(_currentIndex);
+ msgstrEdit->processCommand(insCmd,false);
+ forwardMsgstrEditCmd(insCmd);
+ }
+ i++;
+ }
+
+ // fill the non-initialized ones
+ while (i != numForms)
+ {
+ // insert text
+ DelTextCmd* insCmd = new InsTextCmd(0,text,i);
+ insCmd->setPart(Msgstr);
+ insCmd->setIndex(_currentIndex);
+ msgstrEdit->processCommand(insCmd,false);
+ forwardMsgstrEditCmd(insCmd);
+ i++;
+ }
+
+ _catalog->applyEndCommand( _currentIndex, Msgstr ,this);
+
+ break;
+
+ case KDESpecific:
+ {
+ pos = msgstrEdit->currentIndex();
+ currentFormBegin=text.findRev("\\n",pos);
+ if( currentFormBegin == -1 ) currentFormBegin=0;
+ else currentFormBegin+=3; // skip the newline
+ currentFormEnd=text.find("\\n",pos);
+ if( currentFormEnd == -1 ) currentFormEnd=text.length();
+
+ text=text.mid(currentFormBegin,currentFormEnd-currentFormBegin);
+
+ QString result=text;
+ for( i=1; i<numForms ; i++ )
+ result+="\\n\n"+text;
+
+ modifyMsgstrText( 0, result, true );
+ }
+ break;
+
+ case NoPluralForm: break;
+ }
+
+}
+
+bool KBabelView::validateUsingTool( const KDataToolInfo & info, const QString &command )
+{
+ if(currentURL().isEmpty())
+ return false;
+
+ KDataTool* tool = info.createTool();
+ if( !tool )
+ {
+ kdWarning() << "Cannot create tool" << endl;
+ return false;
+ }
+
+ bool result=_catalog->checkUsingTool(tool);
+ emitEntryState();
+
+ QString checkName = *(info.userCommands().at( info.commands().findIndex(command) ));
+
+ if(result)
+ {
+ KMessageBox::information(this
+ ,i18n("No mismatch has been found.")
+ ,checkName);
+ }
+ else
+ {
+ int index=0;
+ DocPosition pos;
+
+ if(!_catalog->hasError(0,pos))
+ index = _catalog->nextError(0,pos);
+ if(index>=0)
+ {
+ kdDebug(KBABEL) << "Going to " << pos.item << ", " << pos.form << endl;
+ gotoEntry(pos);
+ }
+
+ KMessageBox::error(this
+ ,i18n("Some mismatches have been found.\n"
+ "Please check the questionable entries by using "
+ "Go->Next error")
+ ,checkName);
+ }
+ delete tool;
+
+ return result;
+}
+
+void KBabelView::modifyUsingTool( const KDataToolInfo & info, const QString &command )
+{
+ KDataTool* tool = info.createTool();
+ if( !tool )
+ {
+ kdWarning() << "Cannot create tool" << endl;
+ return;
+ }
+
+ // do some stuff on all entries
+ _catalog->modifyUsingTool(tool, command);
+
+ delete tool;
+}
+
+void KBabelView::modifyCatalogUsingTool( const KDataToolInfo & info, const QString &command )
+{
+ KDataTool* tool = info.createTool();
+ if( !tool )
+ {
+ kdWarning() << "Cannot create tool" << endl;
+ return;
+ }
+
+ // do some stuff on the catalog
+ tool->run(command, _catalog, "Catalog", "application/x-kbabel-catalog");
+
+ delete tool;
+}
+
+void KBabelView::insertChar( QChar ch )
+{
+ if( isReadOnly() || _catalog->package().isEmpty() )
+ return;
+
+ modifyMsgstrText(msgstrEdit->currentIndex(),ch);
+ msgstrEdit->setFocus();
+}
+
+void KBabelView::wordCount()
+{
+ uint total, untranslated, fuzzy;
+
+ _catalog->wordCount( total, fuzzy, untranslated );
+
+ KMessageBox::information( this
+ , i18n("Total words: %1\n\n"
+"Words in untranslated messages: %2\n\n"
+"Words in fuzzy messages: %3").arg(total).arg(untranslated).arg(fuzzy)
+ , i18n("Word Count") );
+}
diff --git a/kbabel/kbabel/kbbookmarkhandler.cpp b/kbabel/kbabel/kbbookmarkhandler.cpp
new file mode 100644
index 00000000..fde1b051
--- /dev/null
+++ b/kbabel/kbabel/kbbookmarkhandler.cpp
@@ -0,0 +1,131 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002 by Marco Wegner <mail@marcowegner.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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#include <qpopupmenu.h>
+#include <qregexp.h>
+#include <qstring.h>
+
+#include "kbbookmarkhandler.h"
+
+
+// implementation of KBabelBookmark
+KBabelBookmark::KBabelBookmark(int msgindex, QString msgtext)
+{
+ _msgindex = msgindex;
+ if (msgtext.length() > 32) {
+ msgtext.truncate(32);
+ msgtext.append("...");
+ }
+
+ // insert one '&' before every consecutive group of ampersands to keep the
+ // first of these from acting either as accelerator or mask in the menu
+ QRegExp rx("&+");
+ int pos = msgtext.find(rx);
+ while (pos >= 0) {
+ msgtext.insert(pos, '&');
+ pos = msgtext.find(rx, pos + rx.matchedLength() + 1);
+ }
+
+ _msgtext = msgtext;
+}
+
+int KBabelBookmark::msgindex() const
+{
+ return _msgindex;
+}
+
+QString KBabelBookmark::msgtext() const
+{
+ return _msgtext;
+}
+
+
+// implementation of KBabelBookmarkHandler
+KBabelBookmarkHandler::KBabelBookmarkHandler(QPopupMenu* menu)
+{
+ _menu = menu;
+ _list.setAutoDelete(true);
+}
+
+void KBabelBookmarkHandler::addBookmark(KBabelBookmark* b)
+{
+ // check if a bookmark to the current msgid exists already
+ QPtrListIterator<KBabelBookmark> it(_list);
+ KBabelBookmark* temp;
+
+ while((temp = it.current()) != 0) {
+ ++it;
+ if (temp->msgindex() == b->msgindex()) {
+ // gotcha
+ delete b;
+ return;
+ }
+ }
+
+ // if it's okay then add the bookmark
+ _list.append(b);
+ _menu->insertItem(QString("#%1 - %2").arg(b->msgindex()).arg(b->msgtext()),
+ this, SIGNAL(signalBookmarkSelected(int)), 0, b->msgindex());
+}
+
+void KBabelBookmarkHandler::addBookmark(int msgindex, QString msgtext)
+{
+ addBookmark(new KBabelBookmark(msgindex, msgtext));
+}
+
+void KBabelBookmarkHandler::setBookmarks(QPtrList<KBabelBookmark> list)
+{
+ QPtrListIterator<KBabelBookmark> it(list);
+ KBabelBookmark* temp;
+
+ while((temp = it.current()) != 0) {
+ ++it;
+ addBookmark(temp->msgindex(), temp->msgtext()); // make deep copy
+ }
+}
+
+QPtrList<KBabelBookmark> KBabelBookmarkHandler::bookmarks() const
+{
+ return _list;
+}
+
+void KBabelBookmarkHandler::slotClearBookmarks()
+{
+ while (!_list.isEmpty()) {
+ KBabelBookmark* b = _list.first();
+ _menu->removeItem(b->msgindex());
+ _list.remove(b);
+ }
+}
+
+#include "kbbookmarkhandler.moc"
diff --git a/kbabel/kbabel/kbbookmarkhandler.h b/kbabel/kbabel/kbbookmarkhandler.h
new file mode 100644
index 00000000..f47c2dbf
--- /dev/null
+++ b/kbabel/kbabel/kbbookmarkhandler.h
@@ -0,0 +1,155 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002 by Marco Wegner <mail@marcowegner.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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#ifndef KBBOOKMARKHANDLER_H
+#define KBBOOKMARKHANDLER_H
+
+#include <qobject.h>
+#include <qptrlist.h>
+
+class QPopupMenu;
+class QString;
+
+
+/**
+ * Simple class representing a bookmark in KBabel.
+ * Stored in the class are the msgindex (msgid #) and part of its text.
+ */
+class KBabelBookmark
+{
+ public:
+ /**
+ * Constructor.
+ * The msgtext will be truncated automatically when creating the bookmark.
+ *
+ * @param msgindex the index of the bookmarked msgid.
+ * @param msgtext the msgid.
+ */
+ KBabelBookmark(int msgindex, QString msgtext);
+
+ /**
+ * Return the index of the msgid.
+ *
+ * @return the index of the bookmarked msgid.
+ */
+ int msgindex() const;
+ /**
+ * Return the msgid.
+ *
+ * @return the msgid.
+ */
+ QString msgtext() const;
+
+ private:
+ /**
+ * The classes' own copy of the msgindex.
+ */
+ int _msgindex;
+ /**
+ * The classes' own copy of the msgid.
+ */
+ QString _msgtext;
+};
+
+
+/**
+ * Simple class for managing bookmarks in KBabel.
+ */
+class KBabelBookmarkHandler : public QObject
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Constructor.
+ *
+ * @param menu the pointer to the menu where the bookmarks will be
+ * displayed.
+ */
+ KBabelBookmarkHandler(QPopupMenu* menu);
+
+ /**
+ * Add a bookmark.
+ * The bookmark is added to the internal list as well as to the menu.
+ *
+ * @param b the bookmark to be added.
+ */
+ void addBookmark(KBabelBookmark* b);
+ /**
+ * Add a bookmark.
+ * Overloaded member. The bookmark will first be created from msgindex
+ * and msgtext.
+ *
+ * @param msgindex the index of the bookmark's msgid.
+ * @param msgtext the msgindex of the bookmark to be added.
+ */
+ void addBookmark(int msgindex, QString msgtext);
+ /**
+ * Provide the handler with a list of bookmarks.
+ * Especially useful when creating a new view of the KBabel window.
+ *
+ * @param list the list to be copied.
+ */
+ void setBookmarks(QPtrList<KBabelBookmark> list);
+ /**
+ * Return the list of bookmarks for a new view of the KBabel window.
+ *
+ * @return the internal list of bookmarks
+ */
+ QPtrList<KBabelBookmark> bookmarks() const;
+
+ public slots:
+ /**
+ * Clear all bookmarks.
+ */
+ void slotClearBookmarks();
+
+ signals:
+ /**
+ * This signal is emitted if one of the bookmarks was activated.
+ * The signal contains the msgindex of the bookmark.
+ */
+ void signalBookmarkSelected(int);
+
+ private:
+ /**
+ * The pointer to the menu.
+ */
+ QPopupMenu* _menu;
+ /**
+ * The internal list for storing the bookmarks.
+ */
+ QPtrList<KBabelBookmark> _list;
+};
+
+#endif // KBBOOKMARKHANDLER_H
diff --git a/kbabel/kbabel/kbcatalog.cpp b/kbabel/kbabel/kbcatalog.cpp
new file mode 100644
index 00000000..52205484
--- /dev/null
+++ b/kbabel/kbabel/kbcatalog.cpp
@@ -0,0 +1,63 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#include "kbcatalog.h"
+#include "headereditor.h"
+
+
+KBCatalog::KBCatalog(QString configFile, QObject* parent, const char* name)
+ : KBabel::Catalog(parent,name,configFile)
+{
+ _headerEditor=0;
+}
+
+
+KBCatalog::~KBCatalog()
+{
+ if(_headerEditor)
+ delete _headerEditor;
+}
+
+HeaderEditor* KBCatalog::headerEditor()
+{
+ if(!_headerEditor)
+ {
+ _headerEditor = new HeaderEditor(this,"_headerEditor");
+ }
+
+ return _headerEditor;
+}
+
+
+
+#include "kbcatalog.moc"
diff --git a/kbabel/kbabel/kbcatalog.h b/kbabel/kbabel/kbcatalog.h
new file mode 100644
index 00000000..ae6508cf
--- /dev/null
+++ b/kbabel/kbabel/kbcatalog.h
@@ -0,0 +1,61 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef KBCATALOG_H
+#define KBCATALOG_H
+
+#include "catalog.h"
+
+class HeaderEditor;
+
+
+/**
+* This class adds some functionality to the catalog,
+* that is needed by the gui.
+* * @author Matthias Kiefer <matthias.kiefer@gmx.de>
+*/
+class KBCatalog : public KBabel::Catalog
+{
+ Q_OBJECT
+
+public:
+ KBCatalog(QString configFile = QString::null ,QObject* parent=0, const char* name=0);
+ virtual ~KBCatalog();
+
+ HeaderEditor* headerEditor();
+
+private:
+ HeaderEditor* _headerEditor;
+
+};
+
+#endif //CATALOG_H
diff --git a/kbabel/kbabel/kbcataloglistview.cpp b/kbabel/kbabel/kbcataloglistview.cpp
new file mode 100644
index 00000000..51f9b008
--- /dev/null
+++ b/kbabel/kbabel/kbcataloglistview.cpp
@@ -0,0 +1,136 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2004 by Asgeir Frimannsson
+ <asgeirf@redhat.com>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+**************************************************************************** */
+
+#include "kbcataloglistview.h"
+#include "kbcataloglistviewitem.h"
+#include "kbcatalog.h"
+#include "kbabel.h"
+#include "editcmd.h"
+
+#include <klocale.h>
+#include <klistview.h>
+#include <qcolor.h>
+#include <qlayout.h>
+#include <kglobalsettings.h>
+
+using namespace KBabel;
+
+KBCatalogListView::KBCatalogListView(KBCatalog* catalog, QWidget *parent, KBabel::Project::Ptr project)
+ : QWidget(parent)
+{
+ m_catalog= catalog;
+ QVBoxLayout* layout=new QVBoxLayout(this);
+
+ m_listview = new KListView(this, "catalogListView");
+ m_listview->addColumn(i18n("Id"));
+ m_listview->addColumn(i18n("Original String"));
+ m_listview->addColumn(i18n("Translated String"));
+ m_listview->setAlternateBackground(KGlobalSettings::alternateBackgroundColor());
+ m_listview->setFullWidth(true);
+ m_listview->setAllColumnsShowFocus(true);
+ m_listview->resize(this->size());
+
+ layout->addWidget(m_listview);
+ layout->setStretchFactor(m_listview,1);
+
+ connect(m_listview,SIGNAL(selectionChanged(QListViewItem *)), this,SLOT(selectionChanged(QListViewItem *)));
+}
+
+KBCatalogListView::~KBCatalogListView()
+{
+}
+
+
+void KBCatalogListView::selectionChanged ( QListViewItem * item)
+{
+ DocPosition pos;
+ int number = m_items->find(reinterpret_cast<KBCatalogListViewItem*>(item));
+ if(number<0) number = 0;
+
+ pos.item=number;
+ pos.form=0;
+
+ emit signalSelectionChanged(pos);
+}
+
+void KBCatalogListView::setSelectedItem(int index)
+{
+ QListViewItem * item = m_items->at(index);
+
+ // block signals - don't reemit the selected item signal
+ blockSignals(true);
+ m_listview->setSelected(item, true);
+ blockSignals(false);
+
+ m_listview->ensureItemVisible(item);
+}
+
+void KBCatalogListView::update(EditCommand* cmd, bool undo)
+{
+ /*
+ if((int)_currentIndex==cmd->index())
+ {
+ emitEntryState();
+
+ if(cmd->part()==Msgstr)
+ {
+ msgstrEdit->processCommand(cmd,undo);
+ emit signalMsgstrChanged();
+ }
+ }
+ */
+}
+
+void KBCatalogListView::msgstrChanged(const QString& str)
+{
+ KBCatalogListViewItem * item = reinterpret_cast<KBCatalogListViewItem *>(m_listview->selectedItem());
+ item->setMsgStr(str);
+}
+
+void KBCatalogListView::slotNewFileOpened()
+{
+ m_listview->clear();
+ KBCatalogListViewItem * tempItem;
+ if(m_catalog)
+ {
+ m_items = new QPtrVector<KBCatalogListViewItem>(m_catalog->numberOfEntries());
+
+ for(uint i=0;i<m_catalog->numberOfEntries();i++)
+ {
+ QString msgid = ( *m_catalog->msgid(i).at(0) );
+ QString msgstr = ( *m_catalog->msgstr(i).at(0) );
+ tempItem = new KBCatalogListViewItem(m_listview,0,i+1,
+ msgid,
+ msgstr);
+ m_items->insert(i, tempItem);
+ }
+ }
+
+ int width = m_listview->columnWidth(1) + m_listview->columnWidth(2);
+ m_listview->setColumnWidth(1,width/2);
+ m_listview->setColumnWidth(2,width/2);
+
+
+}
+
+
+#include "kbcataloglistview.moc"
diff --git a/kbabel/kbabel/kbcataloglistview.h b/kbabel/kbabel/kbcataloglistview.h
new file mode 100644
index 00000000..d9737871
--- /dev/null
+++ b/kbabel/kbabel/kbcataloglistview.h
@@ -0,0 +1,82 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2004 by Asgeir Frimannsson
+ <asgeirf@redhat.com>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+**************************************************************************** */
+
+#ifndef KBCATALOGLISTVIEW_H
+#define KBCATALOGLISTVIEW_H
+
+#include <qwidget.h>
+#include <catalogview.h>
+#include <kconfig.h>
+#include <qwidget.h>
+//#include <qstrlist.h>
+#include <resources.h>
+#include "catalog.h"
+#include "kbcatalog.h"
+#include "kbproject.h"
+#include "projectsettings.h"
+#include "kbcataloglistviewitem.h"
+
+namespace KBabel{
+ class EditCommand;
+}
+
+class KBabelMW;
+class KBCatalog;
+class KListView;
+
+
+/**
+@author
+*/
+class KBCatalogListView : public QWidget, public KBabel::CatalogView
+{
+ Q_OBJECT
+public:
+ KBCatalogListView(KBCatalog* catalog, QWidget *parent, KBabel::Project::Ptr project);
+
+ ~KBCatalogListView();
+
+ /**
+ * this is called from the catalog when updating his views.
+ * reimplemented from @ref CatalogView
+ * @param cmd the edit command that has been applied
+ */
+ virtual void update(KBabel::EditCommand* cmd, bool undo=false);
+
+ void setSelectedItem(int index);
+signals:
+ void signalSelectionChanged(const KBabel::DocPosition& pos);
+
+public slots:
+ virtual void slotNewFileOpened();
+ void msgstrChanged(const QString&);
+
+private:
+ KListView * m_listview;
+ KBCatalog* m_catalog;
+ QPtrVector<KBCatalogListViewItem>* m_items;
+
+private slots:
+ void selectionChanged ( QListViewItem * item);
+};
+
+#endif
diff --git a/kbabel/kbabel/kbcataloglistviewitem.cpp b/kbabel/kbabel/kbcataloglistviewitem.cpp
new file mode 100644
index 00000000..5a4012a2
--- /dev/null
+++ b/kbabel/kbabel/kbcataloglistviewitem.cpp
@@ -0,0 +1,213 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2004 by Asgeir Frimannsson
+ <asgeirf@redhat.com>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+**************************************************************************** */
+
+#include "kbcataloglistviewitem.h"
+#include <assert.h>
+
+KBCatalogListViewItem::KBCatalogListViewItem(KListView* lv, KListViewItem* parent, uint id, QString msgid, QString msgstr)
+ : Super(lv, parent, "","",""), m_id(id), m_msgid(msgid), m_msgstr(msgstr)
+{
+ setText(0,QString::number(id));
+}
+
+
+KBCatalogListViewItem::~KBCatalogListViewItem()
+{
+}
+
+void KBCatalogListViewItem::setMsgId(const QString& st)
+{
+ m_msgid = st;
+ setup();
+ repaint();
+}
+
+void KBCatalogListViewItem::setMsgStr(const QString& st)
+{
+ m_msgstr = st;
+ setup();
+ repaint();
+}
+
+uint KBCatalogListViewItem::getId()
+{
+ return m_id;
+}
+
+void KBCatalogListViewItem::setId(const uint id)
+{
+ m_id = id;
+ setup();
+ repaint();
+}
+
+QString KBCatalogListViewItem::key ( int column, bool ascending ) const{
+
+ if(column==0)
+ return QString().sprintf("%.8u", m_id);
+ else if(column==1)
+ return m_msgid;
+ else if(column==2)
+ return m_msgstr;
+ else
+ return Super::key(column, ascending);
+}
+
+
+void KBCatalogListViewItem::setup()
+{
+ assert(listView());
+
+ widthChanged();
+
+ m_doc_msgid.reset(0);
+ m_doc_msgstr.reset(0);
+
+ makeDocAvailable();
+
+ QListView* lv = listView();
+
+ m_doc_msgid->setWidth(std::max(1, int(lv->columnWidth(1))));
+ m_doc_msgstr->setWidth(std::max(1, int(lv->columnWidth(2))));
+
+ if(m_doc_msgid->height() > m_doc_msgstr->height())
+ setHeight(m_doc_msgid->height());
+ else
+ setHeight(m_doc_msgstr->height());
+
+}
+
+
+void KBCatalogListViewItem::paintMsgIdCell(QPainter* p, const QColorGroup& cg,
+ int column, int width, int align)
+{
+ // check width
+
+ int widthPrepared = m_doc_msgid->width();
+
+ if (width != widthPrepared)
+ m_doc_msgid->setWidth(p, std::max(1, int(width)));
+
+ // check height
+
+ if (height() < m_doc_msgid->height() )
+ {
+ // invalid height, don't draw
+
+ setHeight(m_doc_msgid->height());
+ return;
+ }
+
+ // draw appropriate background
+
+ Super::paintCell(p, cg, column, width, align);
+
+ // draw it
+
+ m_doc_msgid->draw(p, 0, 0, QRect(0,0, width, height()), cg);
+
+}
+
+void KBCatalogListViewItem::paintMsgStrCell(QPainter* p, const QColorGroup& cg,
+ int column, int width, int align)
+{
+ // check width
+
+ int widthPrepared = m_doc_msgstr->width();
+
+ if (width != widthPrepared)
+ m_doc_msgstr->setWidth(p, std::max(1, int(width)));
+
+ // check height
+
+ if (height() < m_doc_msgstr->height() )
+ {
+ // invalid height, don't draw
+
+ setHeight(m_doc_msgstr->height());
+ return;
+ }
+ else if(height() > m_doc_msgstr->height() && height() > m_doc_msgid->height())
+ {
+ if(m_doc_msgstr->height() > m_doc_msgid->height())
+ setHeight(m_doc_msgstr->height());
+ else
+ setHeight(m_doc_msgid->height());
+
+ return;
+ }
+
+ // draw appropriate background
+
+ Super::paintCell(p, cg, column, width, align);
+
+ // draw it
+
+ m_doc_msgstr->draw(p, 0, 0, QRect(0,0, width, height()), cg);
+
+}
+
+void KBCatalogListViewItem::paintCell(QPainter* p, const QColorGroup& cg,
+ int column, int width, int align)
+{
+ assert(m_doc_msgid.get() && m_doc_msgstr.get() && p);
+
+ // paint background (empty text)
+
+
+ switch(column)
+ {
+ case 0: // id
+ Super::paintCell(p, cg, column, width, align);
+ return;
+ case 1: // msgid
+ paintMsgIdCell(p,cg,column,width,align);
+ return;
+ case 2: // msgstr
+ paintMsgStrCell(p,cg,column,width,align);
+ return;
+ }
+}
+
+void KBCatalogListViewItem::makeDocAvailable()
+{
+ if (m_doc_msgid.get() && m_doc_msgstr.get())
+ return;
+
+ assert(listView());
+
+ m_doc_msgid.reset(new QSimpleRichText(
+ formatMsg(m_msgid), listView()->font()));
+ m_doc_msgstr.reset(new QSimpleRichText(
+ formatMsg(m_msgstr), listView()->font()));
+}
+
+QString KBCatalogListViewItem::formatMsg(const QString str)
+{
+ // TODO: Use KBHighlighting for this
+ QString tmp_msgid = str;
+ tmp_msgid = tmp_msgid.replace( "\\n", "<br>" );
+ tmp_msgid = tmp_msgid.replace( "<", "&lt;" );
+ tmp_msgid = tmp_msgid.replace( ">", "&gt;" );
+
+ return tmp_msgid;
+}
diff --git a/kbabel/kbabel/kbcataloglistviewitem.h b/kbabel/kbabel/kbcataloglistviewitem.h
new file mode 100644
index 00000000..8fa6704a
--- /dev/null
+++ b/kbabel/kbabel/kbcataloglistviewitem.h
@@ -0,0 +1,72 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2004 by Asgeir Frimannsson
+ <asgeirf@redhat.com>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+**************************************************************************** */
+
+#ifndef KBCATALOGLISTVIEWITEM_H
+#define KBCATALOGLISTVIEWITEM_H
+#include <memory>
+#include <klistview.h>
+#include <qsimplerichtext.h>
+#include "mymultilineedit.h"
+
+/**
+@author
+*/
+class KBCatalogListViewItem : public KListViewItem
+{
+ typedef KListViewItem Super;
+public:
+ KBCatalogListViewItem(KListView* lv, KListViewItem* parent, uint id, QString msgid, QString msgstr);
+
+ ~KBCatalogListViewItem();
+
+ void setMsgId(const QString& st);
+ void setMsgStr(const QString& st);
+ void setId(const uint id);
+ uint getId();
+
+protected:
+
+ virtual void setup();
+ virtual QString key ( int column, bool ascending ) const;
+
+ virtual void paintCell(QPainter* p, const QColorGroup& cg,
+ int column, int width, int align);
+
+
+private:
+ void makeDocAvailable();
+ void paintMsgIdCell(QPainter* p, const QColorGroup& cg,
+ int column, int width, int align);
+ void paintMsgStrCell(QPainter* p, const QColorGroup& cg,
+ int column, int width, int align);
+
+ QString formatMsg(const QString str);
+
+ uint m_id;
+ QString m_msgid;
+ QString m_msgstr;
+
+ std::auto_ptr<QSimpleRichText> m_doc_msgid;
+ std::auto_ptr<QSimpleRichText> m_doc_msgstr;
+};
+
+#endif
diff --git a/kbabel/kbabel/kbcatalogview.cpp b/kbabel/kbabel/kbcatalogview.cpp
new file mode 100644
index 00000000..ba8e9c03
--- /dev/null
+++ b/kbabel/kbabel/kbcatalogview.cpp
@@ -0,0 +1,137 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2004-2005 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#include "kbcatalogview.h"
+#include "resources.h"
+
+using namespace KBabel;
+
+KBCatalogView::KBCatalogView(KBCatalog* catalog, QWidget* parent, Project::Ptr project)
+ : QWidget (parent), KBabel::CatalogView () , _project (project)
+{
+ if (catalog == 0)
+ kdFatal(KBABEL) << "catalog==0" << endl;
+
+ _catalog=catalog;
+ _catalog->registerView(this);
+
+ _config = KSharedConfig::openConfig ("kbabelrc");
+
+ _currentIndex=1; // here we use 1 to accept update at opening a file
+
+ connect ( _project, SIGNAL (signalSettingsChanged()), this, SLOT (readProjectSettings()) );
+ connect ( _catalog, SIGNAL (signalFileOpened(bool)), this, SLOT (readFileSettings() ) );
+
+ readProjectSettings();
+ readFileSettings();
+ readConfigurationSettings();
+}
+
+KBCatalogView::~KBCatalogView()
+{
+ _catalog->removeView(this);
+
+ // check if this view was the last view and delete the catalog if necessary
+ if(!_catalog->hasView())
+ {
+ delete _catalog;
+ }
+}
+
+void KBCatalogView::update(EditCommand*, bool )
+{
+}
+
+void KBCatalogView::textCut()
+{
+}
+
+void KBCatalogView::textCopy()
+{
+}
+
+void KBCatalogView::textPaste()
+{
+}
+
+void KBCatalogView::textSelectAll()
+{
+}
+
+void KBCatalogView::gotoEntry(const DocPosition& pos)
+{
+ if ( _currentIndex == pos.item )
+ return;
+
+ _currentIndex=pos.item;
+
+ updateView ();
+}
+
+void KBCatalogView::readProjectSettings()
+{
+}
+
+void KBCatalogView::readFileSettings()
+{
+ setReadOnly (_catalog->isReadOnly());
+}
+
+void KBCatalogView::readConfigurationSettings()
+{
+}
+
+void KBCatalogView::readSessionSettings(KConfig *)
+{
+}
+
+void KBCatalogView::writeConfigurationSettings(KConfig *)
+{
+}
+
+void KBCatalogView::writeSessionSettings(KConfig *)
+{
+}
+
+void KBCatalogView::setReadOnly (bool on)
+{
+ setEnabled (on);
+}
+
+void KBCatalogView::setProject(KBabel::Project::Ptr project)
+{
+ _project = project;
+ readProjectSettings();
+}
+
+#include "kbcatalogview.moc"
diff --git a/kbabel/kbabel/kbcatalogview.h b/kbabel/kbabel/kbcatalogview.h
new file mode 100644
index 00000000..5f23381a
--- /dev/null
+++ b/kbabel/kbabel/kbcatalogview.h
@@ -0,0 +1,102 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2004-2005 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef KBCATALOGVIEW_H
+#define KBCATALOGVIEW_H
+
+#include <qwidget.h>
+
+#include <catalogview.h>
+#include "kbcatalog.h"
+#include "kbproject.h"
+#include "projectsettings.h"
+
+class KBCatalogView : public QWidget, public KBabel::CatalogView
+{
+ Q_OBJECT
+public:
+ /**
+ * Default constructor
+ */
+ KBCatalogView(KBCatalog* catalog, QWidget* parent, KBabel::Project::Ptr project);
+
+ /**
+ * Destructor
+ */
+ virtual ~KBCatalogView();
+
+ /**
+ * this is called from the catalog when updating his views.
+ * reimplemented from @ref CatalogView
+ * @param cmd the edit command that has been applied
+ */
+ virtual void update(KBabel::EditCommand* cmd, bool undo=false);
+
+ KBCatalog* catalog() const{return _catalog;}
+
+public slots:
+ virtual void textCut();
+ virtual void textCopy();
+ virtual void textPaste();
+ virtual void textSelectAll();
+ virtual void gotoEntry(const KBabel::DocPosition& pos);
+ virtual void setProject(KBabel::Project::Ptr project);
+ virtual void readProjectSettings();
+ virtual void readFileSettings();
+ virtual void readConfigurationSettings();
+ virtual void readSessionSettings(KConfig *config);
+
+ virtual void writeConfigurationSettings(KConfig *config);
+ virtual void writeSessionSettings(KConfig *config);
+
+ virtual void setReadOnly (bool on);
+
+ /**
+ * this is called when the view needs an updating.
+ * It's the only really needed method to reimplement
+ */
+ virtual void updateView() = 0;
+
+signals:
+ void signalCursorPosChanged(int line, int col);
+
+protected:
+ KBCatalog* _catalog;
+ uint _currentIndex;
+
+ // configuration file
+ KSharedConfig::Ptr _config;
+ // project file
+ KBabel::Project::Ptr _project;
+};
+
+#endif // KBCATALOGVIEW_H
diff --git a/kbabel/kbabel/kbcharselect.cpp b/kbabel/kbabel/kbcharselect.cpp
new file mode 100644
index 00000000..63316255
--- /dev/null
+++ b/kbabel/kbabel/kbcharselect.cpp
@@ -0,0 +1,94 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include "kbcharselect.h"
+
+#include <kconfig.h>
+#include <kcharselect.h>
+#include <kdialog.h>
+#include <klocale.h>
+
+#include <qlabel.h>
+#include <qspinbox.h>
+#include <qscrollview.h>
+
+KBCharSelect::KBCharSelect(QWidget* parent,const char* name)
+ : QVBox(parent,name)
+{
+ setSpacing( KDialog::spacingHint() );
+
+ QHBox* bar = new QHBox(this);
+ bar->setSpacing( KDialog::spacingHint() );
+
+ QLabel *lTable = new QLabel( i18n( "Table:" ), bar );
+ _tableNum = new QSpinBox( 0, 255, 1, bar );
+ lTable->setBuddy( _tableNum );
+ bar->setStretchFactor( _tableNum, 1 );
+
+ QScrollView* scroll = new QScrollView( this );
+ _table = new KCharSelectTable(scroll,"charselector","helvetica",' ',0);
+ _table->setNumCols(16);
+ _table->setNumRows(16);
+
+ scroll->addChild(_table);
+
+ connect( _table, SIGNAL( doubleClicked() ), this, SLOT( emitChar() ) );
+ connect( _tableNum, SIGNAL( valueChanged(int) ), this, SLOT( setTab(int) ));
+}
+
+void KBCharSelect::emitChar()
+{
+ emit characterDoubleClicked( _table->chr() );
+}
+
+void KBCharSelect::setTab(int value)
+{
+ _table->setTableNum( value );
+}
+
+void KBCharSelect::saveSettings(KConfig* config)
+{
+ KConfigGroupSaver saver(config, "KBCharSelector" );
+
+ config->writeEntry( "TableNum", _tableNum->value() );
+ config->writeEntry( "SelectedChar", QString(_table->chr()) );
+}
+
+void KBCharSelect::restoreSettings(KConfig* config)
+{
+ KConfigGroupSaver saver(config, "KBCharSelector" );
+
+ _tableNum->setValue( config->readNumEntry("TableNum", 0 ));
+ _table->setChar( config->readEntry("SelectedChar"," ").at(0));
+}
+
+#include "kbcharselect.moc"
diff --git a/kbabel/kbabel/kbcharselect.h b/kbabel/kbabel/kbcharselect.h
new file mode 100644
index 00000000..4de3460f
--- /dev/null
+++ b/kbabel/kbabel/kbcharselect.h
@@ -0,0 +1,65 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef KBCHARSELECT_H
+#define KBCHARSELECT_H
+
+#include <qvbox.h>
+
+class KConfig;
+class KCharSelectTable;
+class QSpinBox;
+
+class KBCharSelect : public QVBox
+{
+ Q_OBJECT
+public:
+ KBCharSelect(QWidget* parent, const char* name=0);
+
+ void saveSettings(KConfig* config);
+ void restoreSettings(KConfig* config);
+
+signals:
+ void characterDoubleClicked( QChar ch );
+
+public slots:
+ void emitChar();
+
+private slots:
+ void setTab( int value);
+
+private:
+ KCharSelectTable* _table;
+ QSpinBox* _tableNum;
+};
+
+#endif // KBCHARSELECT_H
diff --git a/kbabel/kbabel/kbhighlighting.cpp b/kbabel/kbabel/kbhighlighting.cpp
new file mode 100644
index 00000000..ce58c483
--- /dev/null
+++ b/kbabel/kbabel/kbhighlighting.cpp
@@ -0,0 +1,316 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002 by Marco Wegner <mail@marcowegner.de>
+ 2003 Trolltech AS
+ 2003 Lukas Tinkl <lukas@kde.org>
+ 2003-2005 Stanislav Visnovsky <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#include <qcolor.h>
+#include <qregexp.h>
+#include <qstring.h>
+#include <qtextedit.h>
+
+#include "kapplication.h"
+#include <kconfig.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+#include <kbabelsettings.h>
+#include <kspell.h>
+
+#include "kbhighlighting.h"
+#include "resources.h"
+
+KBabelHighlighter::KBabelHighlighter( QTextEdit * edit, KSpell *spell ) : QObject()
+ , _edit( edit )
+ , syntaxHighlighting(true)
+ , mSpell(0), alwaysEndsWithSpace(true)
+{
+ regexps << "(<[_:A-Za-z][-_.:A-Za-z0-9]*([\\s]*[_:A-Za-z][-_.:A-Za-z0-9]*=\\\\\"[^<>]*\\\\\")*[\\s]*/?>)|(</[_:A-Za-z][-_.:A-Za-z0-9]*[\\s]*>)";
+ regexps << "(&[A-Za-z_:][A-Za-z0-9_.:-]*;)";
+ regexps << "(%[\\ddioxXucsfeEgGphln]+)|(%\\d+\\$[dioxXucsfeEgGphln])";
+ regexps << "(\\\\[abfnrtv'\"\?\\\\])|(\\\\\\d+)|(\\\\x[\\dabcdef]+)";
+
+ colors.resize( 8 );
+ colors[Normal] = KGlobalSettings::textColor();
+ colors[Tag] = KBabelSettings::tagColor ();
+ colors[Entity] = KBabelSettings::tagColor ();
+ colors[CFormat] = KBabelSettings::cformatColor ();
+ colors[Masked] = KBabelSettings::quotedColor ();
+ colors[Accel] = KBabelSettings::accelColor ();
+ colors[Error] = KBabelSettings::errorColor ();
+ colors[SpellcheckError] = KBabelSettings::spellcheckErrorColor ();
+
+ _hasErrors = false;
+
+ readSettings( );
+ regexps << accelMarker + "[\\w]";
+
+ connect( _edit, SIGNAL( textChanged( ) ), this, SLOT( highlight( ) ) );
+
+ setSpellChecker(spell);
+}
+
+// spell check the current text and highlight (as red text) those words
+// that fail the spell check
+void KBabelHighlighter::highlight( )
+{
+ // no updates while we're highlighting
+ _edit->blockSignals( true );
+ _edit->setUpdatesEnabled( false );
+
+ // store cursor position
+ int cpara, cindex;
+ _edit->getCursorPosition( &cpara, &cindex );
+
+ _edit->selectAll( );
+ _edit->setColor( _hasErrors ? colors[Error] : colors[Normal] );
+ _edit->removeSelection( );
+
+ // create a single line out of the text: remove "\n", so that we only
+ // have to deal with one single line of text.
+ QString text = _edit->text( );
+ text.replace( "\n", "" );
+
+ QRegExp rx;
+ int pos;
+
+ if (syntaxHighlighting)
+ {
+ for ( uint i = 0; i < regexps.count( ); ++i ) {
+ rx.setPattern( regexps[i] );
+ pos = text.find( rx );
+ while ( pos >= 0 ) {
+ doHighlighting( (HighlightType)(i+1), pos, rx.matchedLength( ) );
+ pos = text.find( rx, pos + rx.matchedLength( ) );
+ }
+ }
+ }
+
+ if( mSpell )
+ {
+ // spell-on-fly start
+ if (!text.endsWith(" "))
+ alwaysEndsWithSpace = false;
+ else
+ alwaysEndsWithSpace = true;
+
+ //MessageHighlighter::highlightParagraph( text, endStateOfLastPara );
+
+ int len = text.length();
+ if (alwaysEndsWithSpace)
+ len--;
+
+ currentPos = 0;
+ currentWord = "";
+ for (int i = 0; i < len; i++) {
+ if (text[i].isSpace() || text[i] == '-' || (text[i]=='\\' && text[i+1]=='n')) {
+ flushCurrentWord();
+ if (text[i]=='\\') i++;
+ currentPos = i + 1;
+ } else {
+ currentWord += text[i];
+ }
+ }
+
+ // this was if (!text[len - 1].isLetter())
+ // but then the last word is never checked
+ if (text[len - 1].isLetter()) {
+ kdDebug(KBABEL) << "flushing last Current word: " << currentWord << endl;
+ flushCurrentWord();
+ }
+ else {
+ kdDebug(KBABEL) << "not flushing last Current word: " << currentWord << endl;
+ }
+ } // spell-on-fly end
+
+ _edit->setColor( colors[Normal] );
+
+ //restore cursor position
+ _edit->setCursorPosition( cpara, cindex );
+
+ // allow updates again now that we're finished highlighting
+ _edit->setUpdatesEnabled( true );
+ _edit->blockSignals( false );
+ _edit->updateContents( );
+ _edit->ensureCursorVisible();
+}
+
+void KBabelHighlighter::doHighlighting( HighlightType type, int pos, int length )
+{
+ uint startPara = 0, endPara = 0, startIndex = pos, endIndex = pos+length;
+
+ // transform the one-dimensional indexes into two-dimensional ones
+ while ( startIndex > _edit->text( startPara ).length( ) )
+ startIndex -= _edit->text( startPara++ ).length( ) - 1;
+ while ( endIndex > _edit->text( endPara ).length( ) )
+ endIndex -= _edit->text( endPara++ ).length( ) - 1;
+
+ // and finally do the actual highlighting
+ _edit->setSelection( startPara, startIndex, endPara, endIndex );
+ _edit->setColor( colors[type] );
+ _edit->removeSelection( );
+}
+
+void KBabelHighlighter::setHighlightColor( HighlightType type, QColor color )
+{
+ colors[type] = color;
+}
+
+void KBabelHighlighter::setHasErrors( bool err )
+{
+ _hasErrors = err;
+}
+
+void KBabelHighlighter::readSettings( )
+{
+ // FIXME: does not care about different projects yet
+ KConfig * config = KGlobal::config( );
+ config->setGroup( "Misc" );
+ QString temp = config->readEntry( "AccelMarker", "&" );
+ accelMarker = temp[0];
+}
+
+static int dummy, dummy2;
+static int *Okay = &dummy;
+static int *NotOkay = &dummy2;
+
+void KBabelHighlighter::flushCurrentWord()
+{
+ while (currentWord[0].isPunct()) {
+ currentWord = currentWord.mid(1);
+ currentPos++;
+ }
+
+ QChar ch;
+ while ((ch = currentWord[(int) currentWord.length() - 1]).isPunct()
+ && ch != '(' && ch != '@')
+ currentWord.truncate( currentWord.length() - 1 );
+
+ // try to remove tags (they might not be fully compliant, but
+ // we don't want to check them anyway
+ QRegExp tags("(<[-_.:A-Za-z0-9]*([\\s]*[-_.:A-Za-z0-9]*=\\\\\"[^<>]*\\\\\")*[\\s]*/?>)|(</[-_.:A-Za-z0-9]*[\\s]*>)");
+ if( tags.search (currentWord) != -1 )
+ {
+ currentPos += tags.matchedLength();
+ }
+
+ currentWord.replace ( tags, "" );
+
+ if (!currentWord.isEmpty()) {
+ bool isPlainWord = true;
+ for (int i = 0; i < (int) currentWord.length(); i++) {
+ QChar ch = currentWord[i];
+ if (ch.upper() == ch) {
+ isPlainWord = false;
+ break;
+ }
+ }
+
+ if (/*isPlainWord && currentWord.length() > 2 &&*/ isMisspelled(currentWord))
+ doHighlighting(SpellcheckError,currentPos, currentWord.length());
+ }
+ currentWord = "";
+}
+
+QDict<int> KBabelHighlighter::dict(50021);
+
+bool KBabelHighlighter::isMisspelled(const QString& wordRaw)
+{
+ // We have to treat ampersands (like in "&go" or "g&o") in a special way.
+ // they must not break the word. And we cannot change the parameter, as
+ // then the highlight would be one character short. So we have to copy the
+ // word first.
+ QString word = wordRaw;
+ kdDebug(KBABEL) << "isampersand: checking (raw):" << word << endl;
+ word.replace("&", "" );
+ kdDebug(KBABEL) << "isMisspelled: checking: " << word << endl;
+
+ // Normally isMisspelled would look up a dictionary and return
+ // true or false, but kspell is asynchronous and slow so things
+ // get tricky...
+
+ // "dict" is used as a cache to store the results of KSpell
+ if (!dict.isEmpty() && dict[word] == NotOkay)
+ return true;
+ if (!dict.isEmpty() && dict[word] == Okay)
+ return false;
+
+ // there is no 'spelt correctly' signal so default to Okay
+ kdDebug(KBABEL) << "Adding word " << word << endl;
+ dict.replace(word, Okay);
+ mSpell->checkWord(word, false);
+ return false;
+}
+
+void KBabelHighlighter::slotMisspelling(const QString & originalword,
+ const QStringList & suggestions, unsigned int)
+{
+ kdDebug(KBABEL) << "Misspelled " << originalword << ", " << suggestions << endl;
+ dict.replace( originalword, NotOkay );
+
+ // this is slow but since kspell is async this will have to do for now
+ highlight();
+}
+
+void KBabelHighlighter::setSpellChecker( KSpell* spell )
+{
+ if( mSpell )
+ {
+ disconnect(mSpell, SIGNAL(misspelling(const QString &, const QStringList &, unsigned int)),
+ this, SLOT(slotMisspelling(const QString &, const QStringList &, unsigned int)));
+
+ // cleanup the cache
+ dict.clear();
+ }
+
+ mSpell = spell;
+
+ if( mSpell )
+ {
+ connect(mSpell, SIGNAL(misspelling(const QString &, const QStringList &, unsigned int)),
+ this, SLOT(slotMisspelling(const QString &, const QStringList &, unsigned int)));
+
+ // wait for KSpell to startup correctly
+ kapp->processEvents(500);
+ }
+
+ highlight();
+}
+
+void KBabelHighlighter::setSyntaxHighlighting( bool enable )
+{
+ syntaxHighlighting = enable;
+
+ // update highlighting
+ highlight();
+}
+#include "kbhighlighting.moc"
diff --git a/kbabel/kbabel/kbhighlighting.h b/kbabel/kbabel/kbhighlighting.h
new file mode 100644
index 00000000..91a6202d
--- /dev/null
+++ b/kbabel/kbabel/kbhighlighting.h
@@ -0,0 +1,104 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002 by Marco Wegner <mail@marcowegner.de>
+ (C) 2003 TrollTech AS
+ (C) 2003 Lukas Tinkl <lukas@kde.org>
+ (C) 2003-2005 Stanislav Visnovsky <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#ifndef KBHIGHLIGHTING_H
+#define KBHIGHLIGHTING_H
+
+#include <qmemarray.h>
+#include <qobject.h>
+#include <qstringlist.h>
+#include <qguardedptr.h>
+
+class KSpell;
+class QColor;
+class QString;
+class QTextEdit;
+
+class KBabelHighlighter : public QObject
+{
+ Q_OBJECT
+
+ public:
+ enum HighlightType {
+ Normal = 0,
+ Tag,
+ Entity,
+ CFormat,
+ Masked,
+ Accel,
+ Error,
+ SpellcheckError
+ };
+
+ KBabelHighlighter( QTextEdit * edit, KSpell *spell );
+
+ void setHighlightColor( HighlightType type, QColor color );
+ void setHasErrors( bool err );
+ void setSpellChecker( KSpell* spell);
+
+ bool isMisspelled(const QString& word);
+
+ public slots:
+ void highlight( );
+ void setSyntaxHighlighting( bool enable );
+
+ protected slots:
+ void slotMisspelling (const QString & originalword,
+ const QStringList & suggestions, unsigned int pos);
+
+ private:
+ void doHighlighting( HighlightType type, int pos, int length );
+ void readSettings( );
+ void flushCurrentWord();
+
+ private:
+ QTextEdit * _edit;
+ bool syntaxHighlighting;
+
+ QStringList regexps;
+ QMemArray<QColor> colors;
+
+ bool _hasErrors;
+ QString accelMarker;
+
+ static QDict<int> dict;
+ QGuardedPtr<KSpell> mSpell;
+ QString currentWord;
+ int currentPos;
+ bool alwaysEndsWithSpace;
+};
+
+#endif // KBHIGHLIGHTING_H
diff --git a/kbabel/kbabel/lo16-app-kbabel.png b/kbabel/kbabel/lo16-app-kbabel.png
new file mode 100644
index 00000000..98ee2659
--- /dev/null
+++ b/kbabel/kbabel/lo16-app-kbabel.png
Binary files differ
diff --git a/kbabel/kbabel/lo32-app-kbabel.png b/kbabel/kbabel/lo32-app-kbabel.png
new file mode 100644
index 00000000..8d52961b
--- /dev/null
+++ b/kbabel/kbabel/lo32-app-kbabel.png
Binary files differ
diff --git a/kbabel/kbabel/main.cpp b/kbabel/kbabel/main.cpp
new file mode 100644
index 00000000..40c28926
--- /dev/null
+++ b/kbabel/kbabel/main.cpp
@@ -0,0 +1,612 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2001 by Matthias Kiefer <matthias.kiefer@gmx.de>
+ 2002-2005 by Stanislav Visnovsky <visnovsky@kde.org>
+ Copyright (C) 2006 by Nicolas GOUTTE <goutte@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include "kbabel.h"
+#include "kbabeliface.h"
+#include "kbprojectmanager.h"
+#include "catalog.h"
+#include "kbabelsplash.h"
+#include "findoptions.h"
+
+#include "version.h"
+
+#include <dcopclient.h>
+#include <kaboutdata.h>
+#include <kcmdlineargs.h>
+#include <kcursor.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kuniqueapplication.h>
+#include <kwin.h>
+
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qtimer.h>
+
+class KBabelInterface : public KBabelIface
+{
+public:
+ KBabelInterface();
+
+ virtual void openURL(QCString url, QCString package, WId window, int newWindow);
+ virtual void openURL(QCString url, QCString package, WId window, int newWindow, QCString projectFile);
+ virtual void openTemplate(QCString openFilename, QCString saveFilename, QCString package, int newWindow );
+ virtual void openTemplate(QCString openFilename, QCString saveFilename, QCString package, int newWindow, QCString projectFile );
+ virtual void gotoFileEntry(QCString url, QCString msgid);
+ virtual void gotoFileEntry(QCString url, QCString package, int msgid);
+ virtual void gotoFileEntry(QCString url, QCString package, int msgid, QCString projectFile);
+ virtual bool findInFile(QCString fileSource, QCString url,
+ QString findStr, int caseSensitive, int wholeWords, int isRegExp,
+ int inMsgid, int inMsgstr, int inComment,
+ int ignoreAccelMarker, int ignoreContextInfo, int askForNextFile, int askForSave);
+ virtual bool replaceInFile(QCString fileSource, QCString url,
+ QString findStr, QString replaceStr, int caseSensitive, int wholeWords, int isRegExp,
+ int inMsgid, int inMsgstr, int inComment,
+ int ignoreAccelMarker, int ignoreContextInfo, int ask, int askForNextFile, int askForSave);
+ virtual bool findInFile(QCString fileSource, QCString url,
+ QString findStr, int caseSensitive, int wholeWords, int isRegExp,
+ int inMsgid, int inMsgstr, int inComment,
+ int ignoreAccelMarker, int ignoreContextInfo, int askForNextFile, int askForSave, QCString project );
+ virtual bool replaceInFile(QCString fileSource, QCString url,
+ QString findStr, QString replaceStr, int caseSensitive, int wholeWords, int isRegExp,
+ int inMsgid, int inMsgstr, int inComment,
+ int ignoreAccelMarker, int ignoreContextInfo, int ask, int askForNextFile, int askForSave, QCString project );
+ virtual void spellcheck(QStringList fileList);
+private:
+ KBabelMW* findInstance( const KURL& url, const QString& project, const QString& package) const;
+};
+
+
+class KBabelApp : public KUniqueApplication
+{
+public:
+ KBabelApp();
+ virtual ~KBabelApp();
+
+ virtual int newInstance();
+
+private:
+ KBabelInterface *kbInterface;
+};
+
+KBabelApp::KBabelApp()
+ : KUniqueApplication()
+{
+ kbInterface = new KBabelInterface;
+}
+
+KBabelApp::~KBabelApp()
+{
+ delete kbInterface;
+}
+
+int KBabelApp::newInstance()
+{
+ bool first=true;
+ if(KBabelMW::memberList && !KBabelMW::memberList->isEmpty())
+ {
+ first=false;
+ }
+
+ // see if we are starting with session management
+#if KDE_IS_VERSION(3,3,0)
+ if (!restoringSession())
+#else
+ if (!isRestored() || !first)
+#endif
+ {
+ kdDebug () << "Suspending DCOP" << endl;
+ kapp->dcopClient()->suspend();
+
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+ QTimer timer;
+ QWidget *splash=0;
+ bool showSplash=args->isSet("splash");
+
+ if( showSplash && first )
+ {
+ setOverrideCursor(KCursor::waitCursor());
+ splash = new KBabelSplash();
+ splash->show();
+ timer.start(4000,true);
+ }
+
+ QString projectFile=args->getOption("project");
+ if( !projectFile.isEmpty() )
+ {
+ QFileInfo fi(projectFile);
+ projectFile = fi.absFilePath();
+ }
+ else
+ {
+ projectFile = KBabel::ProjectManager::defaultProjectName();
+ kdDebug(KBABEL) << "Using the default project Project: " << projectFile << endl;
+ }
+
+ kdDebug() << "Project: " << projectFile << endl;
+ QCString msgid=args->getOption("gotomsgid");
+ if(!msgid.isEmpty() && args->count() > 0)
+ {
+ kdDebug(KBABEL) << "gotomsgid" << endl;
+ QString m = QString::fromLocal8Bit(msgid);
+
+ kdDebug () << "Resuming DCOP" << endl;
+ kapp->dcopClient()->resume();
+ kbInterface->gotoFileEntry(args->url(0).url().local8Bit(),m.utf8());
+ }
+ else
+ {
+ // no session.. just start up normally
+ KBabelMW *widget=0;
+ if(args->count() > 0)
+ {
+ KURL u = args->url(0);
+ widget=KBabelMW::winForURL(u,projectFile);
+ }
+
+ if(!widget)
+ widget=KBabelMW::emptyWin(projectFile);
+
+ if(!widget)
+ widget=new KBabelMW(projectFile);
+
+ while(timer.isActive()) // let the user admire the splash screen ;-)
+ processEvents();
+
+ widget->show();
+ for (int i=0; i < args->count(); i++)
+ {
+ widget->open( args->url(i) , QString::null, i != 0 );
+ }
+
+ kdDebug () << "Resuming DCOP" << endl;
+ kapp->dcopClient()->resume();
+ }
+
+
+ args->clear();
+
+ if(splash)
+ {
+ delete KBabelSplash::instance;
+ }
+ if(showSplash)
+ {
+ KApplication::restoreOverrideCursor();
+ /*
+ KMessageBox::information(0,
+ "This is a development version of KBabel!\n"
+ "Please double check the files you edit "
+ "and save with this version for correctness.\n"
+ "Please report any bug you find to kiefer@kde.org.\n"
+ "Thanks.", "Warning");
+ */
+ }
+ }
+
+ return 0;
+}
+
+KBabelInterface::KBabelInterface()
+ : DCOPObject("KBabelIFace")
+{
+}
+
+void KBabelInterface::openURL(QCString url, QCString package, WId window, int newWindow)
+{
+ openURL(url,package,window,newWindow, KBabel::ProjectManager::defaultProjectName().local8Bit());
+}
+
+void KBabelInterface::openURL(QCString url, QCString package, WId window, int newWindow, QCString projectFile)
+{
+ const QString project( QString::fromLocal8Bit( projectFile ) );
+
+ kdDebug() << "openURL " << url << endl;
+
+ KURL u(QString::fromLocal8Bit(url));
+
+ kdDebug () << "Suspending DCOP" << endl;
+ kapp->dcopClient()->suspend();
+
+ KBabelMW *kb = KBabelMW::winForURL(u,project);
+ if(kb)
+ {
+ KWin::activateWindow(kb->topLevelWidget()->winId());
+ }
+ else
+ {
+ KMainWindow *mw = 0;
+ if(KMainWindow::memberList && !KMainWindow::memberList->isEmpty())
+ mw=KMainWindow::memberList->first();
+
+ // first, try to lookup correct winid
+ while( mw ) {
+ if( mw->inherits("KBabelMW") && mw->winId() == window)
+ {
+ kb = static_cast<KBabelMW*>(mw);
+ KWin::activateWindow(kb->topLevelWidget()->winId());
+ kb->open(u, QString::fromUtf8(package),newWindow);
+
+ kdDebug () << "Resuming DCOP" << endl;
+ kapp->dcopClient()->resume();
+
+ return ;
+ }
+ mw = KMainWindow::memberList->next();
+ }
+
+ // now, the empty window
+ kb = KBabelMW::emptyWin(projectFile);
+ if (kb)
+ {
+ // here, we don't care about "open in new window", because
+ // it's empty
+ KWin::setActiveWindow(kb->topLevelWidget()->winId());
+ kb->projectOpen(projectFile);
+ kb->open(u,QString::fromUtf8(package),false);
+
+ kdDebug () << "Resuming DCOP" << endl;
+ kapp->dcopClient()->resume();
+
+ return;
+ }
+
+ if(KMainWindow::memberList && !KMainWindow::memberList->isEmpty())
+ mw=KMainWindow::memberList->first();
+
+ while( mw ) {
+ if( mw->inherits("KBabelMW") && static_cast<KBabelMW*>(mw)->project()==project)
+ {
+ kb = static_cast<KBabelMW*>(mw);
+ KWin::activateWindow(kb->topLevelWidget()->winId());
+ kb->open(u, QString::fromUtf8(package),newWindow);
+
+ kdDebug () << "Resuming DCOP" << endl;
+ kapp->dcopClient()->resume();
+
+ return ;
+ }
+ mw = KMainWindow::memberList->next();
+ }
+
+ if( !mw )
+ {
+ kb = new KBabelMW(project);
+ kb->show();
+ } else kb = static_cast<KBabelMW*>(mw);
+ KWin::activateWindow(kb->topLevelWidget()->winId());
+ kb->open(u,QString::fromUtf8(package),newWindow);
+ }
+
+ kdDebug () << "Resuming DCOP" << endl;
+ kapp->dcopClient()->resume();
+}
+
+void KBabelInterface::openTemplate(QCString openFilename, QCString saveFilename, QCString package, int newWindow)
+{
+ openTemplate(openFilename, saveFilename, package, newWindow, KBabel::ProjectManager::defaultProjectName().local8Bit());
+}
+
+void KBabelInterface::openTemplate(QCString openFilename, QCString saveFilename, QCString package, int newWindow, QCString projectFile)
+{
+ const QString project( QString::fromLocal8Bit( projectFile ) );
+
+ const KURL u( QString::fromLocal8Bit( saveFilename ) );
+ const KURL t( QString::fromLocal8Bit( openFilename ) );
+
+ kdDebug () << "Suspending DCOP" << endl;
+ kapp->dcopClient()->suspend();
+
+ KBabelMW *kb = KBabelMW::winForURL(u, project);
+ if(kb)
+ {
+ KWin::activateWindow(kb->topLevelWidget()->winId());
+ }
+ else
+ {
+ KMainWindow *mw = 0;
+ if(KMainWindow::memberList && !KMainWindow::memberList->isEmpty())
+ mw=KMainWindow::memberList->first();
+
+ if(mw && mw->inherits("KBabelMW") && static_cast<KBabelMW*>(mw)->project()==project)
+ {
+ kb = static_cast<KBabelMW*>(mw);
+ KWin::activateWindow(kb->topLevelWidget()->winId());
+ kb->projectOpen(projectFile);
+ kb->openTemplate(t,u,QString::fromUtf8(package),newWindow);
+ }
+ else
+ {
+ kb = new KBabelMW(project);
+ kb->show();
+ KWin::activateWindow(kb->topLevelWidget()->winId());
+ kb->openTemplate(t,u,QString::fromUtf8(package));
+ }
+ }
+
+ kdDebug () << "Resuming DCOP" << endl;
+ kapp->dcopClient()->resume();
+}
+
+void KBabelInterface::gotoFileEntry(QCString url, QCString m)
+{
+ const KURL u( QString::fromLocal8Bit( url ) );
+ KBabelMW *kb = findInstance( u, KBabel::ProjectManager::defaultProjectName(), QString() );
+
+ if(!kb) return;
+
+ QString msgid = QString::fromUtf8(m);
+ int index = kb->m_view->catalog()->indexForMsgid(msgid);
+ if(index >= 0)
+ {
+ KBabel::DocPosition pos;
+ pos.item=index;
+ pos.form=0;
+ kb->m_view->gotoEntry(pos);
+ }
+}
+
+void KBabelInterface::gotoFileEntry(QCString url, QCString package, int m)
+{
+ gotoFileEntry(url, package, m, KBabel::ProjectManager::defaultProjectName().local8Bit() );
+}
+
+void KBabelInterface::gotoFileEntry(QCString url, QCString package, int m, QCString projectFile)
+{
+ const KURL u ( QString::fromLocal8Bit( url ) );
+ const QString p ( QString::fromUtf8( package ) ); // ### VERIFY encoding!
+ KBabelMW *kb = findInstance( u, projectFile, p );
+
+ if(!kb) return;
+
+ KBabel::DocPosition pos;
+ pos.item=m;
+ pos.form=0;
+ kb->m_view->gotoEntry(pos);
+}
+
+bool KBabelInterface::findInFile(QCString fileSource, QCString url,
+ QString findStr, int caseSensitive, int wholeWords, int isRegExp,
+ int inMsgid, int inMsgstr, int inComment,
+ int ignoreAccelMarker, int ignoreContextInfo, int askForNextFile, int askForSave)
+{
+ // no project given, open with default project
+ return findInFile ( fileSource, url, findStr, caseSensitive,
+ wholeWords, isRegExp, inMsgid, inMsgstr, inComment, ignoreAccelMarker, ignoreContextInfo,
+ askForNextFile, askForSave,
+ KBabel::ProjectManager::defaultProjectName().utf8() );
+}
+
+bool KBabelInterface::findInFile(QCString fileSource, QCString url,
+ QString findStr, int caseSensitive, int wholeWords, int isRegExp,
+ int inMsgid, int inMsgstr, int inComment,
+ int ignoreAccelMarker, int ignoreContextInfo, int askForNextFile, int askForSave, QCString project )
+{
+ kdDebug(KBABEL) << "findInFile (" <<fileSource<< "): " << url << " for " << findStr << endl;
+
+ const KURL u( QString::fromLocal8Bit( url ) );
+ KBabelMW *kb = findInstance( u, QString::fromLocal8Bit(project), QString() );
+
+ if(!kb) return false;
+
+ KBabel::FindOptions options;
+ options.findStr = findStr;
+ options.caseSensitive = (caseSensitive>0);
+ options.fromCursor = false;
+ options.backwards = false;
+ options.wholeWords = (wholeWords>0);
+ options.isRegExp = (isRegExp>0);
+ options.inMsgid = (inMsgid>0);
+ options.inMsgstr = (inMsgstr>0);
+ options.inComment = (inComment>0);
+ options.ignoreAccelMarker = (ignoreAccelMarker>0);
+ options.ignoreContextInfo = (ignoreContextInfo>0);
+ options.askForNextFile = (askForNextFile>0);
+ options.askForSave = (askForSave>0);
+ kb->m_view->findInFile(fileSource, options);
+
+ return true;
+}
+
+bool KBabelInterface::replaceInFile(QCString fileSource, QCString url,
+ QString findStr, QString replaceStr, int caseSensitive, int wholeWords, int isRegExp,
+ int inMsgid, int inMsgstr, int inComment,
+ int ignoreAccelMarker, int ignoreContextInfo, int ask, int askForNextFile, int askForSave)
+{
+ return replaceInFile( fileSource, url,
+ findStr, replaceStr, caseSensitive, wholeWords, isRegExp,
+ inMsgid, inMsgstr, inComment, ignoreAccelMarker, ignoreContextInfo,
+ ask, askForNextFile, askForSave,
+ KBabel::ProjectManager::defaultProjectName().utf8() );
+}
+
+bool KBabelInterface::replaceInFile(QCString fileSource, QCString url,
+ QString findStr, QString replaceStr, int caseSensitive, int wholeWords, int isRegExp,
+ int inMsgid, int inMsgstr, int inComment,
+ int ignoreAccelMarker, int ignoreContextInfo, int ask, int askForNextFile, int askForSave,
+ QCString project )
+{
+ kdDebug(KBABEL) << "replaceInFile (" <<fileSource<< "): " << url << " for " << findStr << endl;
+
+ const KURL u ( QString::fromLocal8Bit( url ) );
+ KBabelMW *kb = findInstance( u, QString::fromLocal8Bit(project), QString() );
+
+ if( !kb ) return false;
+
+ KBabel::ReplaceOptions options;
+ options.findStr = findStr;
+ options.replaceStr = replaceStr;
+ options.caseSensitive = (caseSensitive>0);
+ options.fromCursor = false;
+ options.backwards = false;
+ options.wholeWords = (wholeWords>0);
+ options.isRegExp = (isRegExp>0);
+ options.inMsgid = (inMsgid>0);
+ options.inMsgstr = (inMsgstr>0);
+ options.inComment = (inComment>0);
+ options.ignoreAccelMarker = (ignoreAccelMarker>0);
+ options.ignoreContextInfo = (ignoreContextInfo>0);
+ options.ask = (ask>0);
+ options.askForNextFile = (askForNextFile>0);
+ options.askForSave = (askForSave>0);
+ kb->m_view->replaceInFile(fileSource, options);
+
+ return true;
+}
+
+void KBabelInterface::spellcheck(QStringList fileList)
+{
+ // ### FIXME: the default project might use the wrong language!
+ KBabelMW *kb = findInstance( KURL(), KBabel::ProjectManager::defaultProjectName(), QString() );
+ kb->show();
+ kb->spellcheckMoreFiles( fileList );
+}
+
+KBabelMW* KBabelInterface::findInstance( const KURL& url, const QString& project, const QString& package) const
+{
+ kdDebug () << "Suspending DCOP" << endl;
+ kapp->dcopClient()->suspend();
+
+ KBabelMW *kb = 0;
+ if( !url.isEmpty() )
+ {
+ kb = KBabelMW::winForURL( url, project );
+
+ if(kb)
+ {
+ KWin::activateWindow(kb->topLevelWidget()->winId());
+ }
+ }
+
+ if( !kb )
+ {
+ kb = KBabelMW::emptyWin(project);
+ if( !kb )
+ {
+ kb = new KBabelMW(project);
+ }
+ else
+ {
+ kb->projectOpen(project);
+ }
+
+ kb->show();
+ if ( !url.isEmpty() )
+ kb->open( url, package, false );
+ }
+
+ kdDebug () << "Resuming DCOP" << endl;
+ kapp->dcopClient()->resume();
+
+ return kb;
+}
+
+static KCmdLineOptions options[] =
+{
+ {"gotomsgid <msgid>",I18N_NOOP("Go to entry with msgid <msgid>"),0},
+ {"nosplash",I18N_NOOP("Disable splashscreen at startup"),0},
+ {"project <configfile>",I18N_NOOP("File to load configuration from"),0},
+ {"+[file]",I18N_NOOP("Files to open"),0},
+ KCmdLineLastOption
+};
+
+
+int main(int argc, char **argv)
+{
+ KAboutData about("kbabel",I18N_NOOP("KBabel"),VERSION,
+ I18N_NOOP("An advanced PO file editor"),KAboutData::License_GPL,
+ I18N_NOOP("(c) 1999,2000,2001,2002,2003,2004,2005,2006 The KBabel developers"),0,"http://kbabel.kde.org");
+
+ about.addAuthor("Matthias Kiefer",I18N_NOOP("Original author"),"kiefer@kde.org");
+ about.addAuthor("Wolfram Diestel"
+ ,I18N_NOOP("Wrote diff algorithm, fixed KSpell and gave a lot "
+ "of useful hints."),"wolfram@steloj.de");
+ about.addAuthor("Andrea Rizzi",I18N_NOOP("Wrote the dictionary plugin "
+ "for searching in a database and some other code.")
+ ,"rizzi@kde.org");
+ about.addAuthor("Stanislav Visnovsky",I18N_NOOP("Current maintainer, porting to KDE3/Qt3.")
+ ,"visnovsky@kde.org");
+ about.addAuthor("Marco Wegner",I18N_NOOP("Bug fixes, KFilePlugin for PO files, CVS support, mailing files")
+ ,"dubbleu@web.de");
+ about.addAuthor("Asgeir Frimannsson",I18N_NOOP("Translation List View")
+ ,"asgeirf@redhat.com");
+ about.addAuthor("Nicolas Goutte", I18N_NOOP("Current maintainer"), "goutte@kde.org");
+
+ about.addCredit("Claudiu Costin",I18N_NOOP("Wrote documentation and sent "
+ "many bug reports and suggestions for improvements.")
+ ,"claudiuc@geocities.com");
+ about.addCredit("Thomas Diehl",I18N_NOOP("Gave many suggestions for the GUI "
+ "and the behavior of KBabel. He also contributed the beautiful splash screen.")
+ ,"thd@kde.org");
+ about.addCredit("Stephan Kulow",I18N_NOOP("Helped keep KBabel up to date "
+ "with the KDE API and gave a lot of other help."),"coolo@kde.org");
+ about.addCredit("Stefan Asserhall",I18N_NOOP("Implemented XML validation/highlighting "
+ "plus other small fixes.") ,"stefan.asserhall@telia.com");
+ about.addCredit("Dwayne Bailey",I18N_NOOP("Various validation plugins.")
+ ,"dwayne@translate.org.za");
+ about.addCredit("SuSE GmbH"
+ ,I18N_NOOP("Sponsored development of KBabel for a while.")
+ ,"suse@suse.de","http://www.suse.de");
+ about.addCredit("Trolltech", I18N_NOOP("KBabel contains code from Qt"), 0, "http://www.trolltech.com");
+
+ about.addCredit("Eva Brucherseifer", I18N_NOOP("String distance algorithm implementation"), "eva@kde.org");
+
+ about.addCredit("Albert Cervera Areny", I18N_NOOP("Error list for current entry, regexp data tool"), "albertca@hotpop.com");
+
+ about.addCredit("Nick Shaforostoff", I18N_NOOP("Word-by-word string difference algorithm implementation"), "shafff@ukr.net");
+
+ // Initialize command line args
+ KCmdLineArgs::init(argc, argv, &about);
+
+ // Tell which options are supported
+ KCmdLineArgs::addCmdLineOptions( options );
+
+ // Add options from other components
+ KUniqueApplication::addCmdLineOptions();
+
+
+ if(!KUniqueApplication::start())
+ {
+ return 0;
+ }
+
+ KBabelApp app;
+
+ if( app.isRestored() )
+ {
+ RESTORE(KBabelMW)
+ }
+
+ return app.exec();
+}
diff --git a/kbabel/kbabel/mymultilineedit.cpp b/kbabel/kbabel/mymultilineedit.cpp
new file mode 100644
index 00000000..820d493e
--- /dev/null
+++ b/kbabel/kbabel/mymultilineedit.cpp
@@ -0,0 +1,1668 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2001-2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ Alt+123 feature idea taken from KOffice by David Faure <david@mandrakesoft.com>.
+ Word wrap support by Jarno Elonen <elonen@iki.fi>, 2003
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#include "mymultilineedit.h"
+#include "editcmd.h"
+#include "resources.h"
+
+#include <qpixmap.h>
+#include <qpainter.h>
+#include <qvaluelist.h>
+#include <qstringlist.h>
+#include <qregexp.h>
+#include <qclipboard.h>
+#include <qapplication.h>
+#include <qdragobject.h>
+//#include <private/qrichtext_p.h>
+#include <qpopupmenu.h>
+
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+#include <kmessagebox.h>
+#include <kstdaccel.h>
+
+#include "kbhighlighting.h"
+
+using namespace KBabel;
+
+MyMultiLineEdit::MyMultiLineEdit(int ID, QWidget* parent,const char* name)
+ :KTextEdit(parent,name), emitUndo(true),
+ _firstChangedLine(0),
+ _lastChangedLine(0),
+ _lastParagraph(0),
+ _lastParagraphOffset(0),
+ _lastSelectionStart(-1),
+ _lastSelectionEnd(-1),
+ _dontUpdate(false), _myID (ID),
+ _menu(0), _overwrite(false)
+{
+ setUndoRedoEnabled(false); // we handle this ourselves
+ setWordWrap( WidgetWidth );
+ viewport()->setAcceptDrops( false ); // we need our parent to get drops
+
+ connect(this, SIGNAL(selectionChanged()), this, SLOT( onSelectionChanged() ) );
+}
+
+void MyMultiLineEdit::onSelectionChanged()
+{
+ kdDebug(KBABEL) << "MyMultiLineEdit::onSelectionChanged" << endl;
+ int parFrom, parTo, indexFrom, indexTo;
+ if ( hasSelectedText() ) {
+ getSelection( &parFrom, &indexFrom, &parTo, &indexTo );
+ kdDebug(KBABEL) << "parFrom=" << parFrom << "indexFrom=" << indexFrom << "parTo=" << parTo << "indexTo=" << indexTo << endl;
+ _lastSelectionStart = beginOfMarkedText();
+ }
+ else
+ {
+ _lastSelectionStart = -1; // no selection
+ _lastSelectionEnd = -1;
+ }
+
+ //kdDebug(KBABEL) << "_lastSelectionStart=" << _lastSelectionStart << endl;
+}
+
+void MyMultiLineEdit::processCommand(EditCommand* cmd, bool undo)
+{
+ if(cmd->terminator()!=0)
+ return;
+
+ DelTextCmd* delcmd = (DelTextCmd*) cmd;
+ bool ins = true;
+ if (delcmd->type() == EditCommand::Delete )
+ ins = undo;
+ else if (delcmd->type() == EditCommand::Insert )
+ ins = !undo;
+ else
+ {
+ return;
+ }
+
+ // avoid duplicate update of catalog
+ bool oldEmitUndo = emitUndo;
+ emitUndo = false;
+
+ QPalette _visibleHighlight( palette() );
+ QPalette _invisibleHighlight( palette() );
+ QColorGroup newcg( colorGroup() );
+ newcg.setColor( QColorGroup::HighlightedText, newcg.text() );
+ newcg.setColor( QColorGroup::Highlight, newcg.base() );
+ if( hasFocus() ) _invisibleHighlight.setActive( newcg );
+ else _invisibleHighlight.setInactive( newcg );
+ setPalette( _invisibleHighlight );
+
+ if(delcmd->offset <= (int)_lastParagraphOffset)
+ {
+ _lastParagraph=0;
+ _lastParagraphOffset=0;
+ }
+
+ if ( ins )
+ {
+ int row, col;
+
+ offset2Pos( delcmd->offset, row, col );
+ setCursorPosition( row, col );
+
+ _firstChangedLine=row;
+ if(delcmd->str.find("\n")>0 )_lastChangedLine=row+delcmd->str.contains("\n");
+ else _lastChangedLine=row;
+
+ KTextEdit::insert( delcmd->str );
+
+ offset2Pos( delcmd->offset+delcmd->str.length(), row, col );
+ setCursorPosition( row, col);
+ }
+ else
+ { // del
+
+ int row, col, rowEnd, colEnd;
+
+ offset2Pos( delcmd->offset, row, col );
+ offset2Pos( delcmd->offset + delcmd->str.length(), rowEnd, colEnd );
+
+ setSelection( row, col, rowEnd, colEnd, 0 );
+ _firstChangedLine=_lastChangedLine=row;
+ KTextEdit::removeSelectedText();
+ }
+
+
+ setPalette( _visibleHighlight );
+
+ emitUndo = oldEmitUndo;
+
+ emitCursorPosition();
+}
+
+int MyMultiLineEdit::beginOfLastMarkedText()
+{
+ if ( _lastSelectionStart != -1 )
+ return _lastSelectionStart;
+ else
+ return currentIndex();
+}
+
+int MyMultiLineEdit::endOfLastMarkedText()
+{
+ if ( _lastSelectionEnd != -1 )
+ return _lastSelectionEnd;
+ else
+ return currentIndex();
+}
+
+int MyMultiLineEdit::beginOfMarkedText()
+{
+ int beginX=0;
+ int beginY=0;
+ int endX=0;
+ int endY=0;
+
+ int pos=-1;
+
+ getSelection(&beginY,&beginX,&endY,&endX);
+ if( hasSelectedText() )
+ {
+ pos = pos2Offset(beginY,beginX);
+ }
+
+ return pos;
+}
+
+void MyMultiLineEdit::emitCursorPosition()
+{
+ int line=0;
+ int col=0;
+ getCursorPosition(&line,&col);
+
+ emit cursorPositionChanged(line, col);
+}
+
+void MyMultiLineEdit::wheelEvent(QWheelEvent *e)
+{
+ e->ignore();
+}
+
+void MyMultiLineEdit::focusInEvent(QFocusEvent *e)
+{
+ KTextEdit::focusInEvent(e);
+ emitCursorPosition();
+}
+
+void MyMultiLineEdit::contentsContextMenuEvent( QContextMenuEvent * e)
+{
+ e->accept();
+ if( _menu ) _menu->exec( e->globalPos() );
+}
+
+QPopupMenu * MyMultiLineEdit::createPopupMenu()
+{
+ return _menu;
+}
+
+QPopupMenu * MyMultiLineEdit::createPopupMenu(const QPoint &)
+{
+ return 0;
+}
+
+void MyMultiLineEdit::setContextMenu( QPopupMenu * menu )
+{
+ _menu = menu;
+}
+
+void MyMultiLineEdit::doKeyboardAction( KeyboardAction action )
+{
+ int row,col;
+ getCursorPosition(&row, &col);
+
+ switch( action ) {
+ case ActionDelete:
+ _firstChangedLine=_lastChangedLine=row;
+ my_del(); break;
+
+ case ActionBackspace:
+ _firstChangedLine=_lastChangedLine=row;
+ my_backspace(); break;
+
+ case ActionReturn:
+ if( emitUndo)
+ emit signalUndoCmd( new InsTextCmd(currentIndex(), "\n", _myID) );
+ break;
+
+ case ActionKill:
+ _firstChangedLine=_lastChangedLine=row;
+ if(emitUndo)
+ {
+ int x,y;
+ getCursorPosition( &x, &y );
+ QString s = text(x);
+ if( y < (int)s.length()-1 ) // not the end of paragraph
+ {
+ QString delText = s.mid( y, s.length()-y-1);
+ emit signalUndoCmd( new DelTextCmd(currentIndex(), delText, _myID ) );
+ } else
+ if( x < paragraphs()-1 ) // not the end of text
+ emit signalUndoCmd( new DelTextCmd(currentIndex(), "\n", _myID ) );
+ }
+ break;
+ default: break;
+ }
+
+ KTextEdit::doKeyboardAction( action );
+
+ emitCursorPosition();
+}
+
+void MyMultiLineEdit::setText(const QString& s)
+{
+ _lastParagraph=0;
+ _lastParagraphOffset=0;
+ // workaround, since insert does not interpret markup
+ setTextFormat( Qt::PlainText );
+ _firstChangedLine=_lastChangedLine=0;
+ KTextEdit::setText(s);
+ setTextFormat( Qt::AutoText );
+ // now the number of lines is known, let's do highlight
+ _lastChangedLine=paragraphs();
+ emit textChanged();
+ emitCursorPosition();
+}
+
+void MyMultiLineEdit::insertAt( const QString & s, int line, int col, bool mark )
+{
+ // it will invoke insert, don't need to send InsTextCmd
+ KTextEdit::insertAt(s,line,col);
+
+ // code from QMultiLineEdit
+ if( mark )
+ setSelection( line, col, line, col + s.length(), 0 );
+ // end of copied code
+
+ emitCursorPosition();
+}
+
+void MyMultiLineEdit::insert( const QString & text, bool indent, bool checkNewLine, bool removeSelected )
+{
+ int row,col;
+
+ bool noSelectionRemoved = true;
+ setUpdatesEnabled(false);
+ if( removeSelected && hasSelectedText() )
+ {
+ int endRow,endCol;
+ getSelection(&row,&col,&endRow,&endCol);
+
+ if( row < (int)_lastParagraph )
+ {
+ _lastParagraph=0;
+ _lastParagraphOffset=0;
+ }
+
+ _firstChangedLine=_lastChangedLine=row;
+ removeSelectedText();
+ noSelectionRemoved = false;
+ }
+
+ getCursorPosition(&row,&col);
+ _firstChangedLine=row;
+ _lastChangedLine=row;
+
+ if( emitUndo)
+ {
+ emit signalUndoCmd( new BeginCommand(-1,UndefPart));
+ // reimplemented overwrite
+ if( _overwrite && noSelectionRemoved)
+ {
+ doKeyboardAction( ActionDelete );
+ }
+
+ emit signalUndoCmd( new InsTextCmd(currentIndex(), text, _myID) );
+ emit signalUndoCmd( new EndCommand(-1,UndefPart));
+ }
+
+ int n=text.find("\n");
+ if( n > 0 ) _lastChangedLine+=n;
+
+ // setup palettes
+
+ QPalette _visibleHighlight( palette() );
+ QPalette _invisibleHighlight( palette() );
+ QColorGroup newcg( colorGroup() );
+ newcg.setColor( QColorGroup::HighlightedText, newcg.text() );
+ newcg.setColor( QColorGroup::Highlight, newcg.base() );
+ if( hasFocus() ) _invisibleHighlight.setActive( newcg );
+ else _invisibleHighlight.setInactive( newcg );
+ setPalette( _invisibleHighlight );
+ KTextEdit::insert(text, indent, checkNewLine, removeSelected);
+ setPalette( _visibleHighlight );
+
+ setUpdatesEnabled(true);
+
+ emitCursorPosition();
+}
+
+void MyMultiLineEdit::removeLine ( int line )
+{
+ kdDebug(KBABEL) << "removeLine invoked" << endl;
+
+ KTextEdit::removeParagraph(line);
+ emitCursorPosition();
+}
+
+void MyMultiLineEdit::clear()
+{
+ _lastParagraph=0;
+ _lastParagraphOffset=0;
+
+ _dontUpdate=true;
+
+ QString s = text();
+ if( !s.isEmpty() && emitUndo ) {
+ emit signalUndoCmd( new BeginCommand(-1,UndefPart) );
+ emit signalUndoCmd( new DelTextCmd(0,s,_myID) );
+ emit signalUndoCmd( new EndCommand(-1,UndefPart) );
+ }
+
+ KTextEdit::clear();
+
+ _dontUpdate=false;
+
+ _firstChangedLine=_lastChangedLine=0;
+ emitCursorPosition();
+}
+
+
+void MyMultiLineEdit::my_backspace()
+{
+
+ int cursorY, cursorX;
+ getCursorPosition( &cursorY, &cursorX );
+
+ if( hasSelectedText())
+ {
+ Q_ASSERT( "backspace: This should never happen, why is not invoked removeSelectedText()?");
+ }
+ else if(! (cursorY==0 && cursorX==0) )
+ {
+ if(emitUndo)
+ {
+ int offset = currentIndex();
+
+ QString s= text(cursorY);
+ if(cursorX != 0)
+ {
+ QString delTxt(s[cursorX-1]);
+ emit signalUndoCmd(new DelTextCmd(offset-1,delTxt,_myID));
+ }
+ else if( cursorY > 0 || cursorX > 0 ) // not at the beginning
+ {
+ emit signalUndoCmd(new DelTextCmd(offset-1,"\n",_myID));
+ }
+ }
+ }
+}
+
+void MyMultiLineEdit::my_del()
+{
+
+ int cursorY, cursorX;
+ getCursorPosition( &cursorY, &cursorX );
+
+ if( hasSelectedText())
+ {
+ Q_ASSERT( "del: This should never happen, why is not invoked removeSelectedText()?");
+ }
+ else if(! (cursorY==paragraphs()-1 && cursorX==paragraphLength( cursorY )) )
+ {
+ if(emitUndo)
+ {
+ int offset = pos2Offset(cursorY, cursorX);
+
+ QString s=text(cursorY);
+ if(cursorX != (int)s.length()-1)
+ {
+ QString delTxt(s[cursorX]);
+ emit signalUndoCmd(new DelTextCmd(offset,delTxt,_myID));
+ }
+ else if( cursorY < (int)paragraphs()-1 || ( (cursorY == (int)paragraphs()-1) && (cursorX < (int)text( paragraphs()-1 ).length()-1 ) ) )// !atEnd() )
+ {
+ emit signalUndoCmd(new DelTextCmd(offset,"\n",_myID));
+ }
+ }
+ }
+}
+
+void MyMultiLineEdit::removeSelectedText(int selNum)
+{
+ if( selNum != 0 )
+ {
+ _lastParagraph=0;
+ _lastParagraphOffset=0;
+
+ KTextEdit::removeSelectedText(selNum);
+ }
+ else
+ {
+ int paraFrom, idxFrom, paraTo, idxTo;
+ KTextEdit::getSelection( &paraFrom, &idxFrom, &paraTo, &idxTo );
+
+ if( paraFrom < (int)_lastParagraph )
+ {
+ _lastParagraph=0;
+ _lastParagraphOffset=0;
+ }
+
+ int offset = pos2Offset( paraFrom, idxFrom );
+ emit signalUndoCmd(new DelTextCmd( offset, selectedText(), _myID ) );
+ KTextEdit::removeSelectedText(selNum);
+ }
+
+ emitCursorPosition();
+}
+
+void MyMultiLineEdit::paste()
+{
+ KTextEdit::paste();
+ emitCursorPosition();
+}
+
+int MyMultiLineEdit::currentIndex()
+{
+ int para; // paragraph of current position
+ int index; // index in the current paragraph
+
+ KTextEdit::getCursorPosition(&para,&index);
+
+ return pos2Offset( para, index );
+}
+
+
+void MyMultiLineEdit::offset2Pos(int offset, int &paragraph, int &index) const
+{
+ if (offset <= 0)
+ {
+ paragraph = 0;
+ index = 0;
+ return;
+ }
+ else
+ {
+ int charsLeft = offset;
+ int i;
+
+ for( i = 0; i < paragraphs(); ++i )
+ {
+ if (paragraphLength( i ) < charsLeft)
+ charsLeft -= paragraphLength( i );
+ else
+ {
+ paragraph = i;
+ index = charsLeft;
+ return;
+ }
+ --charsLeft;
+ }
+
+ paragraph = i-1;
+ index = charsLeft;
+ return;
+ }
+}
+
+int MyMultiLineEdit::pos2Offset(uint paragraph, uint index)
+{
+ paragraph = QMAX( QMIN( (int)paragraph, paragraphs() - 1), 0 ); // Sanity check
+ index = QMAX( QMIN( (int)index, paragraphLength( paragraph )), 0 ); // Sanity check
+
+ {
+ uint lastI;
+ lastI = paragraphLength( paragraph );
+ uint i = 0;
+ uint tmp = 0;
+
+ if( paragraph>=_lastParagraph )
+ {
+ tmp = _lastParagraphOffset;
+ i = _lastParagraph;
+ }
+
+ for( ;i < paragraph ; i++ )
+ {
+ tmp += paragraphLength( i ) + 1;
+ }
+
+ _lastParagraphOffset=tmp;
+ _lastParagraph=paragraph;
+
+ tmp += QMIN( lastI, index );
+
+ return tmp;
+ }
+}
+
+void MyMultiLineEdit::setReadOnly(bool on)
+{
+ // I want this backgroundmode, also when readonly==true
+ if(on)
+ {
+ setBackgroundMode(PaletteBase);
+ }
+
+ QTextEdit::setReadOnly(on);
+}
+
+void MyMultiLineEdit::setOverwriteMode( bool b )
+{
+ _overwrite = b;
+}
+
+/*******************************************************************************/
+MsgMultiLineEdit::MsgMultiLineEdit(int ID, KSpell* spell, QWidget* parent,const char* name)
+ :MyMultiLineEdit(ID, parent,name),
+ _quotes(false),
+ _cleverEditing(false),
+ _highlightBg(false),
+ _spacePoints(false),
+ _bgColor(colorGroup().base().dark(110)),
+ _textColor(KGlobalSettings::textColor()),
+ _errorColor(Qt::red),
+ _currentColor(KGlobalSettings::textColor()),
+ _whitespace(0),
+ _hlSyntax(true),
+ _quoteColor(Qt::darkGreen),
+ _unquoteColor(Qt::red),
+ _cformatColor(Qt::blue),
+ _accelColor(Qt::darkMagenta),
+ _showDiff(false),
+ _diffUnderlineAdd(true),
+ _diffStrikeOutDel(true),
+ _diffAddColor(Qt::darkGreen),
+ _diffDelColor(Qt::darkRed),
+ _currentUnicodeNumber(0),
+ highlighter(0),
+ _tagStartPara(0), _tagStartIndex(0), _tagEndPara(0), _tagEndIndex(0)
+{
+ diffPos.setAutoDelete(true);
+ diffPos.clear();
+
+ _whitespace = new QPixmap(2,2,-1,QPixmap::BestOptim);
+ _whitespace->fill(_textColor);
+ _errorWhitespace = new QPixmap(2,2,-1,QPixmap::BestOptim);
+ _errorWhitespace->fill(_errorColor);
+
+ _whitespaceNB = new QPixmap(3,3,-1,QPixmap::BestOptim);
+ _whitespaceNB->fill();
+ _errorWhitespaceNB = new QPixmap(3,3,-1,QPixmap::BestOptim);
+ _errorWhitespaceNB->fill();
+
+ QPainter p(_whitespaceNB);
+ p.setPen( _textColor );
+ p.drawEllipse(_whitespaceNB->rect());
+
+ QPainter q(_errorWhitespaceNB);
+ q.setPen( _errorColor );
+ q.drawEllipse(_errorWhitespaceNB->rect());
+
+ // this will setup bitBlt pixmaps
+ setFont( font() );
+ highlighter = new KBabelHighlighter( this, spell );
+ connect( this, SIGNAL( signalSyntaxHighlightingChanged( bool ) ), highlighter, SLOT( setSyntaxHighlighting( bool ) ) );
+
+ connect( this, SIGNAL( selectionChanged() ), this, SLOT( paintSpacePoints() ) );
+ connect( this, SIGNAL( cursorPositionChanged( int, int ) ), this, SLOT( paintSpacePoints(int, int) ) );
+ connect( this, SIGNAL( textChanged() ), this, SLOT( emittedTextChanged() ) );
+}
+
+MsgMultiLineEdit::~MsgMultiLineEdit ()
+{
+ if(highlighter)
+ delete highlighter;
+}
+
+void MsgMultiLineEdit::setText(const QString& s)
+{
+ QString str = s;
+
+ if(_showDiff)
+ {
+ diffPos.clear();
+ int lines = s.contains('\n');
+ diffPos.resize(lines+1);
+
+ QStringList lineList = QStringList::split('\n',s,true);
+
+ int lineCounter=-1;
+ bool haveAdd=false;
+ bool haveDel=false;
+ bool multiline=false;
+ QStringList::Iterator it;
+ for(it = lineList.begin(); it != lineList.end(); ++it)
+ {
+ lineCounter++;
+
+ int lastPos=0;
+ bool atEnd=false;
+
+ while(!atEnd)
+ {
+ int addPos=-1;
+ int delPos=-1;
+
+ if(haveAdd && multiline)
+ {
+ addPos=0;
+ }
+ else
+ {
+ addPos = (*it).find("<KBABELADD>",lastPos);
+ }
+
+ if(haveDel && multiline)
+ {
+ delPos=0;
+ }
+ else
+ {
+ delPos = (*it).find("<KBABELDEL>",lastPos);
+ }
+
+ if(delPos >= 0 && addPos >= 0)
+ {
+ if(delPos <= addPos)
+ {
+ haveDel=true;
+ haveAdd=false;
+ }
+ else
+ {
+ haveDel=false;
+ haveAdd=true;
+ }
+ }
+ else if(delPos >= 0)
+ {
+ haveDel=true;
+ haveAdd=false;
+ }
+ else if(addPos >= 0)
+ {
+ haveDel=false;
+ haveAdd=true;
+ }
+ else
+ {
+ atEnd=true;
+ haveAdd=false;
+ haveDel=false;
+ }
+
+ DiffInfo di;
+ di.begin=-1;
+
+ if(haveAdd)
+ {
+ if(!multiline)
+ {
+ (*it).remove(addPos,11);
+ }
+
+ int endPos = (*it).find("</KBABELADD>",addPos);
+ if(endPos < 0)
+ {
+ endPos = (*it).length();
+ atEnd=true;
+ multiline=true;
+ }
+ else
+ {
+ (*it).remove(endPos,12);
+ haveAdd=false;
+ multiline=false;
+ }
+
+ lastPos=endPos;
+
+ di.begin=addPos;
+ di.end=endPos-1;
+ di.add=true;
+ }
+ else if(haveDel)
+ {
+ if(!multiline)
+ {
+ (*it).remove(delPos,11);
+ }
+
+ int endPos = (*it).find("</KBABELDEL>",delPos);
+ if(endPos < 0)
+ {
+ endPos = (*it).length();
+ atEnd=true;
+ multiline=true;
+ }
+ else
+ {
+ (*it).remove(endPos,12);
+ haveDel=false;
+ multiline=false;
+ }
+
+ lastPos=endPos;
+
+ di.begin=delPos;
+ di.end=endPos-1;
+ di.add=false;
+ }
+
+ if(di.begin >= 0)
+ {
+ QValueList<DiffInfo> *list = diffPos[lineCounter];
+ if(!list)
+ {
+ list = new QValueList<DiffInfo>;
+ diffPos.insert(lineCounter,list);
+ }
+
+ list->append(di);
+ }
+
+ }
+ }
+
+ QRegExp reg("</?KBABELADD>");
+ str.replace(reg,"");
+ reg.setPattern("</?KBABELDEL>");
+ str.replace(reg,"");
+ }
+
+ MyMultiLineEdit::setText(str);
+ paintSpacePoints();
+}
+
+void MsgMultiLineEdit::setQuotes(bool on)
+{
+ _quotes=on;
+ update();
+}
+
+void MsgMultiLineEdit::setCleverEditing(bool on)
+{
+ _cleverEditing=on;
+}
+
+
+void MsgMultiLineEdit::setHighlightBg(bool on)
+{
+ _highlightBg=on;
+ update();
+}
+
+
+void MsgMultiLineEdit::setBgColor(const QColor& color)
+{
+ _bgColor=color;
+
+ if(_highlightBg)
+ update();
+}
+
+void MsgMultiLineEdit::setSpacePoints(bool on)
+{
+ _spacePoints=on;
+
+ update();
+}
+
+void MsgMultiLineEdit::setHighlightSyntax(bool on)
+{
+ _hlSyntax=on;
+
+ emit signalSyntaxHighlightingChanged (on);
+
+ update();
+}
+
+void MsgMultiLineEdit::setHighlightColors(const QColor& quoteColor, const QColor& unquoteColor
+ , const QColor& cformatColor, const QColor& accelColor, const QColor& tagColor)
+{
+ _quoteColor=quoteColor;
+ _unquoteColor=unquoteColor;
+ _cformatColor=cformatColor;
+ _accelColor=accelColor;
+ _tagColor=tagColor;
+
+ highlighter->setHighlightColor( KBabelHighlighter::Tag, tagColor );
+ highlighter->setHighlightColor( KBabelHighlighter::Entity, accelColor );
+ highlighter->setHighlightColor( KBabelHighlighter::CFormat, cformatColor );
+ highlighter->setHighlightColor( KBabelHighlighter::Masked, quoteColor );
+
+ update();
+}
+
+
+void MsgMultiLineEdit::setFont(const QFont& font)
+{
+ KTextEdit::setFont(font);
+
+ // we don't need to calculate a special offset for non-breaking space, since
+ // they are very similar in size
+ QFontMetrics fm(font);
+ _wsOffsetX = QMAX(fm.width(' ')/2-2,1);
+ _wsOffsetY = QMAX(fm.height()/2-1,0);
+
+ repaint();
+}
+
+void MsgMultiLineEdit::setDiffDisplayMode(bool addUnderline, bool delStrikeOut)
+{
+ _diffUnderlineAdd = addUnderline;
+ _diffStrikeOutDel = delStrikeOut;
+
+ if(_showDiff)
+ update();
+}
+
+void MsgMultiLineEdit::setDiffColors(const QColor& addColor
+ , const QColor& delColor)
+{
+ _diffAddColor = addColor;
+ _diffDelColor = delColor;
+
+ if(_showDiff)
+ update();
+}
+
+void MsgMultiLineEdit::setTextColor(const QColor &color )
+{
+ QPalette p( palette() );
+ QColorGroup newcg( colorGroup() );
+ newcg.setColor( QColorGroup::Text, color );
+ if( hasFocus() ) p.setActive( newcg );
+ else p.setInactive( newcg );
+ setPalette( p );
+ _textColor = color;
+ highlighter->setHighlightColor( KBabelHighlighter::Normal, color );
+}
+
+void MsgMultiLineEdit::setErrorColor(const QColor &color )
+{
+ _errorColor = color;
+ highlighter->setHighlightColor( KBabelHighlighter::Error, color );
+}
+
+void MsgMultiLineEdit::setCurrentColor(const TextColor color)
+{
+ if( color == NormalColor ) {
+ _currentColor = _textColor;
+ highlighter->setHasErrors( false );
+ } else {
+ _currentColor = _errorColor;
+ highlighter->setHasErrors( true );
+ }
+
+ /*
+ setUpdatesEnabled(false);
+ // need to block signals (especially textChanged() to avoid recursion with KBabelView::autoCheck
+ blockSignals(true);
+ selectAll();
+ setColor( _currentColor );
+ removeSelection();
+ setColor(_currentColor);
+ blockSignals(false);
+ setUpdatesEnabled(true);
+ */
+ forceUpdate();
+}
+
+void MsgMultiLineEdit::setSpellChecker(KSpell* spell)
+{
+ highlighter->setSpellChecker(spell);
+}
+
+void MsgMultiLineEdit::paintSpacePoints(int, int )
+{
+ paintSpacePoints();
+}
+
+void MsgMultiLineEdit::paintSpacePoints()
+{
+ QRect r;
+ QPainter painter(viewport() );
+ const QFontMetrics& fm = fontMetrics();
+
+ int paranum = paragraphAt(QPoint(contentsX(), contentsY()));
+
+ if( _spacePoints )
+ {
+ int curpara = paranum;
+ painter.setPen( _currentColor );
+ QPixmap* ws, *wsnb;
+
+ if( _currentColor== _errorColor )
+ {
+ ws = _errorWhitespace;
+ wsnb = _errorWhitespaceNB;
+ }
+ else
+ {
+ ws = _whitespace;
+ wsnb = _whitespaceNB;
+ }
+
+ while( curpara < paragraphs())
+ {
+ if ( paragraphRect( curpara ).top() > contentsY()+visibleHeight()) break;
+
+ const QString& s = text(curpara);
+ int i = s.find( " " );
+ while( (i >= 0) && (i < (int)s.length()-1) ) // -1 because text will end by EOLN
+ {
+ QPixmap* pm = ( s.at(i).unicode() == 0x00A0U ) ? wsnb : ws;
+ QRect r = mapToView( curpara, i );
+ r.moveBy( r.width()/2, (r.height() - fm.descent())/2 );
+ r.moveBy( -pm->rect().width()/2, -pm->rect().height()/2-1 );
+ bitBlt(viewport(), r.topLeft(), pm, pm->rect(), Qt::CopyROP);
+ i = s.find( " ", i+1 );
+ }
+ ++curpara;
+ }
+ }
+
+ if( _quotes )
+ {
+ QFontMetrics fm( font());
+ QRect qs = fm.boundingRect("\"");
+
+ for( int curpara = paranum; curpara < paragraphs() ; curpara++ )
+ {
+ r = paragraphRect(curpara);
+ if( r.y() > contentsY()+visibleHeight() ) break;
+
+ painter.drawText( QPoint( 0, mapToView( curpara, 0 ).top()) +
+ QPoint(0, qs.height() + 4), "\""); // 4 = hardcoded margin in QT
+ painter.drawText( mapToView( curpara, QMAX( 0,
+ ((int)text( curpara ).length())-1)).topRight() +
+ QPoint(0, qs.height() + 4), "\""); // 4 = hardcoded margin in QT
+ }
+ }
+
+ if( _showDiff && (!_diffUnderlineAdd || !_diffStrikeOutDel) )
+ {
+ if( paragraphs() == (int)diffPos.size() ) // sanity check
+ {
+ painter.setRasterOp( Qt::AndROP );
+ for( int curpara = paranum; curpara < paragraphs() ; curpara++ )
+ {
+ r = paragraphRect(curpara);
+ if( r.y() > contentsY()+visibleHeight() ) break;
+
+ QValueList<DiffInfo> *list = diffPos[curpara];
+ if(list)
+ {
+ QValueList<DiffInfo>::ConstIterator it;
+ for(it = list->begin(); it != list->end(); ++it)
+ {
+ QRect beg = mapToView( curpara, (*it).begin );
+ QRect end = mapToView( curpara, (*it).end );
+
+ QColor* c = 0;
+ if( (*it).add && !_diffUnderlineAdd)
+ c = &_diffAddColor;
+ else if(!(*it).add && !_diffStrikeOutDel)
+ c = &_diffDelColor;
+
+ if ( c != 0 )
+ {
+ // Single or multiple lines?
+ if ( beg.top() == end.top())
+ {
+ painter.fillRect( QRect( beg.topLeft(),
+ QPoint( end.right(), end.bottom())), *c );
+ }
+ else
+ {
+ painter.fillRect( QRect(
+ beg.topLeft(),
+ QPoint( r.right(), beg.bottom())), *c );
+ if( end.top()-beg.bottom() > 2 ) {
+ // there is a line, not only thin space
+ painter.fillRect( QRect(
+ QPoint( r.left(), beg.bottom()),
+ QPoint( r.right(), end.top())), *c );
+ }
+ painter.fillRect( QRect(
+ QPoint( r.left(), end.top()),
+ QPoint( end.right(), end.bottom())), *c );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if( _showDiff && (_diffUnderlineAdd || _diffStrikeOutDel) )
+ {
+ if( paragraphs() == (int)diffPos.size() ) // sanity check
+ {
+ for( int curpara = paranum; curpara < paragraphs() ; curpara++ )
+ {
+ r = paragraphRect(curpara);
+ if( r.y() > contentsY()+visibleHeight() ) break;
+
+ QValueList<DiffInfo> *list = diffPos[curpara];
+ if(list)
+ {
+ QPen addPen(_diffAddColor,2);
+ QPen delPen(_diffDelColor,2);
+ QValueList<DiffInfo>::ConstIterator it;
+ for(it = list->begin(); it != list->end(); ++it)
+ {
+ QRect beg = mapToView( curpara, (*it).begin );
+ QRect end = mapToView( curpara, (*it).end );
+
+ QPen* p = 0;
+ int dy = 0;
+ if( (*it).add && _diffUnderlineAdd)
+ p = &addPen;
+ else if(!(*it).add && _diffStrikeOutDel)
+ {
+ p = &delPen;
+ dy = fm.ascent()/2-1;
+ }
+
+ if ( p != 0 )
+ {
+ painter.setPen( *p );
+
+ // Single or multiple lines?
+ if ( beg.top() == end.top())
+ painter.drawLine(
+ beg.topLeft() + QPoint(0, fm.ascent()-dy),
+ end.topRight()+ QPoint(0, fm.ascent()-dy));
+ else
+ {
+ int y = beg.top() + fm.ascent();
+ painter.drawLine(
+ QPoint(beg.left(), y),
+ QPoint(r.right(), y));
+ y += fm.lineSpacing();
+ while (y < end.top() + fm.ascent())
+ {
+ painter.drawLine(
+ QPoint(r.left(), y),
+ QPoint(r.right(), y));
+ y += fm.lineSpacing();
+ }
+ painter.drawLine(
+ QPoint(r.left(), end.top() + fm.ascent()),
+ QPoint(end.right(), end.top() + fm.ascent()));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void MsgMultiLineEdit::repaint()
+{
+ highlight();
+ MyMultiLineEdit::repaint();
+}
+
+void MsgMultiLineEdit::forceUpdate()
+{
+ _firstChangedLine=0;
+ _lastChangedLine=paragraphs()-1;
+ highlighter->highlight();
+ MyMultiLineEdit::repaint();
+}
+
+void MsgMultiLineEdit::ensureCursorVisible()
+{
+ if( isUpdatesEnabled() )
+ MyMultiLineEdit::ensureCursorVisible();
+}
+
+void MsgMultiLineEdit::highlight()
+{
+/* if( _dontUpdate ) return;
+
+ QColor bg;
+ if( _highlightBg ) bg = _bgColor;
+ else bg = colorGroup().base();
+
+ for( int i = 0 ; i < paragraphs() ; i++ )
+ setParagraphBackgroundColor( i, bg );
+
+
+ if(_hlSyntax)
+ {
+ blockSignals(true); // block signals to avoid recursion
+ setUpdatesEnabled(false);
+ int cursorParagraph, cursorIndex;
+
+ getCursorPosition( &cursorParagraph, &cursorIndex );
+
+ // setup new colors
+
+ uint i;
+
+ QRegExp markup("(\\\\)|(\")|(\\\\[abfnrtv'\"\?\\\\])|(\\\\\\d+)|(\\\\x[\\dabcdef]+)"
+ "|(%[\\ddioxXucsfeEgGphln]+)|(&[^\\s])|(&[\\w-]+;)");
+
+ for( i = QMAX(_firstChangedLine,0) ; i < QMIN(_lastChangedLine+1,(uint)paragraphs()) ; i++ ) {
+
+ QString line=text(i);
+
+ //remove old highlighting
+ setSelection(i,0,i,line.length());
+ setColor( _currentColor );
+ removeSelection();
+
+ QColor colorToUse;
+
+ int index=0;
+ index=markup.search( line, index );
+ while(index>=0)
+ {
+ switch( line[index].latin1() )
+ {
+ case '\\':
+ if( markup.matchedLength() == 1 ) colorToUse=_unquoteColor;
+ else colorToUse=_quoteColor;
+ break;
+ case '\"':
+ colorToUse=_unquoteColor;
+ break;
+ case '%':
+ colorToUse=_cformatColor;
+ break;
+ case '&':
+ colorToUse=_accelColor;
+ break;
+ }
+
+ setSelection( i, index, i, index+markup.matchedLength(), 0);
+ setColor( colorToUse );
+ removeSelection();
+ index=markup.search( line, index+markup.matchedLength() );
+ }
+ }
+
+ // Color XML and HTML tags
+
+ int tagindex=0;
+ int taglength=0;
+ int lineindex=0;
+ uint index=0;
+ int startPara, endPara, startIndex, endIndex;
+ QString t= text();
+
+ if(_lastParagraph <= _firstChangedLine)
+ {
+ index=_lastParagraph;
+ lineindex=_lastParagraphOffset;
+ }
+
+ for( ; index<_firstChangedLine ; index++)
+ lineindex+=paragraphLength(index)+1;
+
+ QRegExp re("<.*>");
+ re.setMinimal(true);
+
+ if( _firstChangedLine >0 )
+ {
+ QColor c;
+ QFont f;
+ VerticalAlignment v;
+ getFormat(_firstChangedLine-1, paragraphLength(_firstChangedLine-1)-1, &f, &c, &v);
+ QString l = text(_firstChangedLine-1);
+ if( c==_tagColor && !l.endsWith(">") ) // hope _tagColor will be different than other colors
+ {
+ QRegExp endtag("[^<]*>");
+ tagindex=endtag.search(t, lineindex);
+ taglength=endtag.matchedLength();
+ } else {
+ tagindex=re.search(t, lineindex);
+ taglength=re.matchedLength();
+ }
+ } else {
+ tagindex=re.search( t, lineindex );
+ taglength=re.matchedLength();
+ }
+
+ while( tagindex >= 0 && (int)index<paragraphs())
+ {
+ while( tagindex>=lineindex && index<_lastChangedLine+2)
+ lineindex+=paragraphLength(index++)+1;
+ if(index==_lastChangedLine+2) break;
+ lineindex-=paragraphLength(index-1);
+ lineindex--;
+ index--;
+
+ startPara=index;
+ startIndex=tagindex-lineindex;
+
+ tagindex+=taglength;
+
+ while( tagindex>=lineindex && (int)index<paragraphs())
+ lineindex+=paragraphLength(index++)+1;
+ lineindex-=paragraphLength(index-1);
+ lineindex--;
+ index--;
+
+ endPara=index;
+ endIndex=tagindex-lineindex;
+
+ setSelection( startPara, startIndex, endPara, endIndex, 0 );
+ setColor( _tagColor );
+ removeSelection();
+
+ if(index>_lastChangedLine) break;
+ tagindex=re.search( t, tagindex );
+ taglength=re.matchedLength();
+ }
+
+ setCursorPosition( cursorParagraph, cursorIndex );
+ setColor( _textColor );
+ setUpdatesEnabled(true);
+ blockSignals(false); // block signals to avoid recursion
+ updateContents();
+ }
+ ensureCursorVisible();
+ */
+}
+
+void MsgMultiLineEdit::drawContents( QPainter *painter, int clipx, int clipy, int clipw, int cliph )
+{
+ MyMultiLineEdit::drawContents( painter, clipx, clipy, clipw, cliph );
+ paintSpacePoints();
+}
+
+void MsgMultiLineEdit::paintEvent( QPaintEvent *event )
+{
+ MyMultiLineEdit::paintEvent( event );
+ paintSpacePoints();
+}
+
+QRect MsgMultiLineEdit::mapToView( int para, int index )
+{
+ if( para < 0 || para > paragraphs() ||
+ index < 0 || index > paragraphLength(para) )
+ return QRect(); //invalid rectangle
+
+ const QFontMetrics& fm = fontMetrics();
+ const QString& paratext = text(para);
+
+ // Find index of the first character on the same line as parameter
+ // 'index' using binary search. Very fast, even for long texts.
+ int linestart = 0;
+ int indexline = lineOfChar( para, index );
+ if ( indexline > 0 )
+ {
+ int min = 0, max = index;
+ int i = (min + max)/2;
+ int iline = lineOfChar( para, i );
+ while ( iline != indexline-1 ||
+ lineOfChar( para, i+1 ) != indexline )
+ {
+ Q_ASSERT( min != max && min != i && max != i );
+ if ( iline < indexline )
+ min = i;
+ else
+ max = i;
+ i = (min + max)/2;
+ iline = lineOfChar( para, i );
+ }
+ linestart = i+1;
+ }
+ Q_ASSERT( linestart >= 0 );
+
+ int linewidth;
+
+ // if the tag is not valid, easy
+ if( (_tagStartPara == _tagEndPara) && (_tagStartIndex == _tagEndIndex) ) {
+ linewidth = fm.width( paratext.mid( linestart, index-linestart ));
+ } else {
+ int tso = pos2Offset( _tagStartPara, _tagStartIndex );
+ int teo = pos2Offset( _tagEndPara, _tagEndIndex );
+ int off = pos2Offset( para, index );
+
+ if( off < tso ) {
+ // it is surely before the tag
+ linewidth = fm.width( paratext.mid( linestart, index-linestart ));
+ } else if( off >= teo ) {
+ // it is surely after the tag
+
+ // is it on the same line as the end of the tag?
+ if( _tagEndPara < para || lineOfChar( _tagEndPara, _tagEndIndex ) < indexline ) {
+ // no tag on the line, no bold
+ linewidth = fm.width( paratext.mid( linestart, index-linestart ));
+ } else {
+ QFont f( font() );
+ f.setBold( true );
+ QFontMetrics bfm( f );
+ // is tag single displayed line?
+ if( _tagStartPara == _tagEndPara
+ && lineOfChar( _tagStartPara, _tagStartIndex ) == lineOfChar( _tagEndPara, _tagEndIndex ) )
+ {
+ // yes, count the non-bold before the tag start
+ linewidth = fm.width( paratext.mid( linestart, _tagStartIndex-linestart ) )
+ + bfm.width( paratext.mid( _tagStartIndex, _tagEndIndex-_tagStartIndex ) );
+ }
+ else
+ {
+ // count the part of the tag itself
+ linewidth = bfm.width( paratext.mid( linestart, _tagEndIndex-linestart ) );
+ }
+
+ // add the rest from tag to the index
+ linewidth += fm.width( paratext.mid( _tagEndIndex, index-_tagEndIndex ) );
+ }
+ }
+ else {
+ // in tag
+ QFont f( font() );
+ f.setBold( true );
+ QFontMetrics bfm( f );
+ // is it the first line of the tag?
+ if( para == _tagStartPara && indexline == lineOfChar( _tagStartPara, _tagStartIndex ) ) {
+ // start of the line is normal
+ linewidth = fm.width( paratext.mid( linestart, _tagStartIndex-linestart ) )
+ + bfm.width( paratext.mid( _tagStartIndex, index-_tagStartIndex ) );
+ } else {
+ // whole is bold
+ linewidth = bfm.width( paratext.mid( linestart, index-linestart ) );
+ }
+ }
+ }
+
+ // FIXME as soon as it's possible to ask real margins from QTextEdit:
+ const int left_margin = 4;
+ // const int top_margin = 4;
+
+ QPainter painter( viewport());
+ const QRect& linerect = paragraphRect(para);
+ return QRect(
+ contentsToViewport( QPoint(
+ left_margin + linerect.left() + linewidth ,
+ /*top_margin + */linerect.top() + indexline * fm.lineSpacing() + fm.leading())),
+ QSize(
+ fm.charWidth( paratext, index ),
+ fm.lineSpacing()
+ ));
+}
+
+void MsgMultiLineEdit::keyPressEvent(QKeyEvent *e)
+{
+ if(!_cleverEditing || isReadOnly())
+ {
+ MyMultiLineEdit::keyPressEvent(e);
+ return;
+ }
+
+ KKey key( e );
+
+ if(e->key() == Key_Return || e->key() == Key_Enter)
+ {
+ emit signalUndoCmd(new BeginCommand(-1,UndefPart));
+
+ int row, col;
+ getCursorPosition(&row,&col);
+ QString str=text(row);
+
+ if(e->state() & ShiftButton)
+ {
+ if(col > 0 && !str.isEmpty())
+ {
+ if(str.at(col-1) == '\\' && !isMasked(&str,col-1))
+ {
+ insert("n",false);
+ }
+ else
+ {
+ insert("\\n",false);
+ }
+ }
+ else
+ {
+ insert("\\n",false);
+ }
+ }
+ else if(!(e->state() & ControlButton))
+ {
+ if(col > 0 && !str.isEmpty() && !str.at(col-1).isSpace())
+ {
+ if(str.at(col-1)=='\\' && !isMasked(&str,col-1))
+ {
+ insert("\\",false);
+ }
+
+ // if there is not a new line at the end
+ if(col < 2 || str.mid(col-2,2)!="\\n")
+ {
+ insert(" ",false);
+ }
+ }
+ else if(str.isEmpty())
+ {
+ insert("\\n",false);
+ }
+ }
+
+ if( !str.isEmpty())
+ {
+ // construct new event without modifiers
+ MyMultiLineEdit::keyPressEvent( new QKeyEvent(e->type(), e->key(), e->ascii(), 0,
+ e->text(), e->isAutoRepeat(), e->count() ) );
+ e->accept();
+ }
+
+ emit signalUndoCmd(new EndCommand(-1,UndefPart));
+ return;
+ }
+ else if(e->key() == Key_Tab)
+ {
+ insert("\\t",false);
+ emit textChanged();
+ e->accept();
+ return;
+ }
+ else if((e->key() == Key_Delete && !(e->state() & ControlButton))
+ || ((e->state() & ControlButton) && e->key() == Key_D) )
+ {
+ emit signalUndoCmd(new BeginCommand(-1,UndefPart));
+
+ if(!hasSelectedText())
+ {
+ int row, col;
+ getCursorPosition(&row,&col);
+ QString str=text(row);
+
+ if(!str.isEmpty() && col < (int)str.length() && str.at(col) == '\\'
+ && !isMasked(&str,col))
+ {
+ QString spclChars="abfnrtv'\"?\\";
+ if(col < (int)str.length()-1
+ && spclChars.contains(str.at(col+1)))
+ {
+ del();
+ }
+ }
+ }
+
+ del();
+
+ emit signalUndoCmd(new EndCommand(-1,UndefPart));
+ emit textChanged();
+ e->accept();
+ return;
+ }
+ else if(e->key() == Key_BackSpace
+ || ((e->state() & ControlButton) && e->key() == Key_H) )
+ {
+ emit signalUndoCmd(new BeginCommand(-1,UndefPart));
+
+ if(!hasSelectedText())
+ {
+ int row, col;
+ getCursorPosition(&row,&col);
+ QString str=text(row);
+
+ QString spclChars="abfnrtv'\"?\\";
+ if(!str.isEmpty() && col > 0 && spclChars.contains(str.at(col-1)))
+ {
+ if(col > 1 && str.at(col-2)=='\\' && !isMasked(&str,col-2))
+ {
+ MyMultiLineEdit::keyPressEvent(e);
+ }
+ }
+
+ }
+
+ MyMultiLineEdit::keyPressEvent(e);
+
+ emit signalUndoCmd(new EndCommand(-1,UndefPart));
+
+ e->accept();
+ return;
+ }
+ else if(e->text() == "\"")
+ {
+ emit signalUndoCmd(new BeginCommand(-1,UndefPart));
+
+ int row, col;
+ getCursorPosition(&row,&col);
+ QString str=text(row);
+
+ if(col == 0 || str.at(col-1) != '\\' || isMasked(&str,col-1) )
+ {
+ insert("\\\"",false);
+ }
+ else
+ {
+ insert("\"",false);
+ }
+
+ e->accept();
+
+ emit signalUndoCmd(new EndCommand(-1,UndefPart));
+ return;
+ }
+ else if(e->key() == Key_Space && ( e->state() & AltButton ) )
+ {
+ insert( QChar( 0x00a0U ) );
+ e->accept();
+ return;
+ }
+ // ALT+123 feature
+ else if(( e->state() & AltButton ) && e->text()[0].isDigit() )
+ {
+ QString text=e->text();
+ while ( text[0].isDigit() ) {
+ _currentUnicodeNumber = 10*_currentUnicodeNumber+(text[0].digitValue());
+ text.remove( 0, 1 );
+ }
+ }
+ else
+ {
+ MyMultiLineEdit::keyPressEvent(e);
+ }
+}
+
+void MsgMultiLineEdit::keyReleaseEvent(QKeyEvent* e)
+{
+ if ( e->key() == Key_Alt && _currentUnicodeNumber >= 32 )
+ {
+ QString text = QChar( _currentUnicodeNumber );
+ _currentUnicodeNumber=0;
+ insert( text );
+ }
+}
+
+void MsgMultiLineEdit::setDiffMode(bool on)
+{
+ _showDiff=on;
+
+ if(!on)
+ {
+ diffPos.clear();
+ }
+}
+
+bool MsgMultiLineEdit::isMasked(QString *str, uint col)
+{
+ if(col == 0 || !str)
+ return false;
+
+ uint counter=0;
+ int pos=col;
+
+ while(pos >= 0 && str->at(pos) == '\\')
+ {
+ counter++;
+ pos--;
+ }
+
+ return !(bool)(counter%2);
+}
+
+void MsgMultiLineEdit::emittedTextChanged()
+{
+ highlight();
+ paintSpacePoints();
+}
+
+void MsgMultiLineEdit::selectTag(int start, int length)
+{
+ setUpdatesEnabled(false);
+ setSelection( _tagStartPara, _tagStartIndex, _tagEndPara, _tagEndIndex);
+ setBold( false );
+
+ offset2Pos(start, _tagStartPara, _tagStartIndex);
+ offset2Pos(start+length, _tagEndPara, _tagEndIndex);
+
+ setSelection( _tagStartPara, _tagStartIndex, _tagEndPara, _tagEndIndex);
+ setBold( true );
+ setUpdatesEnabled(true);
+}
+
+#include "mymultilineedit.moc"
diff --git a/kbabel/kbabel/mymultilineedit.h b/kbabel/kbabel/mymultilineedit.h
new file mode 100644
index 00000000..30771610
--- /dev/null
+++ b/kbabel/kbabel/mymultilineedit.h
@@ -0,0 +1,307 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2001-2003 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef MYMULTILINEEDIT_H
+#define MYMULTILINEEDIT_H
+
+#include <ktextedit.h>
+#include <qptrvector.h>
+
+namespace KBabel
+{
+ class EditCommand;
+}
+
+class KBabelHighlighter;
+class KSpell;
+class QPixmap;
+
+class MyMultiLineEdit : public KTextEdit
+{
+ Q_OBJECT
+public:
+ MyMultiLineEdit(int ID,QWidget* parent,const char* name=0);
+
+ /**
+ applies cmd to the displayed text, but does not emit
+ signalUndoCommand
+ */
+ void processCommand(KBabel::EditCommand* cmd, bool undo=false);
+
+ /**
+ * @returns the position in text, where the marked text begins
+ * -1, if there is no marked text
+ */
+ int beginOfMarkedText();
+
+ /**
+ * @returns the position in text, where the last marked text began
+ * or the current cursor position if there was no marked text.
+ * This is used for getting the start position for a text replacement
+ */
+ int beginOfLastMarkedText();
+
+ /**
+ * @returns the position in text, where the last marked text ended
+ * or the current cursor position if there was no marked text.
+ * This is used for getting the end position for a text replacement
+ */
+ int endOfLastMarkedText();
+
+ virtual void insertAt ( const QString & s, int line, int col, bool mark = false );
+ virtual void removeLine ( int line );
+
+ int pos2Offset(uint paragraph, uint index);
+ void offset2Pos(int offset, int &row, int &col) const;
+ /**
+ * @returns the current position in text, where the cursor is
+ */
+
+ int currentIndex();
+ /**
+ * processes Del key
+ */
+ void my_del();
+ void my_backspace();
+
+ /**
+ * need to override deleting of popup menus :-(
+ */
+ void contentsContextMenuEvent( QContextMenuEvent *e );
+
+ /**
+ * need to reimplement overwrite mode :-(
+ */
+ bool isOverwriteMode() { return _overwrite; }
+
+public slots:
+
+ virtual void clear();
+ virtual void paste();
+ virtual void setReadOnly(bool on);
+ virtual void setContextMenu( QPopupMenu *menu );
+ virtual void setText(const QString& s);
+ virtual void doKeyboardAction( KeyboardAction action );
+ virtual void removeSelectedText(int selNum = 0);
+
+ virtual void onSelectionChanged();
+
+ /**
+ reimplemented overwrite mode, since QTextEdit handles this internally and does
+ not use any accessible virtual methods :-((.
+ */
+ virtual void setOverwriteMode(bool b);
+
+protected:
+
+ virtual void focusInEvent(QFocusEvent*);
+ virtual QPopupMenu *createPopupMenu();
+ virtual QPopupMenu *createPopupMenu(const QPoint &pos);
+
+ /* the parent handles this */
+ virtual void wheelEvent(QWheelEvent*);
+
+ bool emitUndo;
+
+ /* First and the last line of the last change. They are only approximate. Used for faster display
+ * highlighting etc.
+ */
+ uint _firstChangedLine;
+ uint _lastChangedLine;
+
+ /* This is a cache. _lastPragraphOffset always correctly corresponds to _lastParagraphOffset
+ */
+ uint _lastParagraph;
+ uint _lastParagraphOffset;
+
+ /* We save the last selection positions. This is needed when a tag is inserted to get the
+ left cursor position of the originally used selection */
+ int _lastSelectionStart;
+ int _lastSelectionEnd;
+
+ /* flag to skip any work on updating, since it will be more changes */
+ bool _dontUpdate;
+
+protected slots:
+ virtual void insert ( const QString & text, bool indent = FALSE, bool checkNewLine = TRUE, bool removeSelected = TRUE );
+ virtual void emitCursorPosition();
+
+signals:
+ void signalUndoCmd(KBabel::EditCommand*);
+ void signalSyntaxHighlightingChanged (bool enable);
+
+protected:
+ int _myID;
+
+private:
+ QPopupMenu *_menu;
+ bool _overwrite;
+};
+
+
+class MsgMultiLineEdit : public MyMultiLineEdit
+{
+ Q_OBJECT
+public:
+ enum TextColor { NormalColor, ErrorColor };
+
+ MsgMultiLineEdit(int ID, KSpell* spell=0, QWidget* parent=0,const char* name=0);
+ virtual ~MsgMultiLineEdit();
+
+ /** is displaying surrounding quotes enabled? */
+ bool quotes() const { return _quotes;}
+ /** enable or disable displaying of surrounding quotes */
+ void setQuotes(bool on);
+
+ /** is clever editing enabled? */
+ bool cleverEditing() const { return _cleverEditing; }
+ /** enable or disable clever editing */
+ void setCleverEditing(bool on);
+ /** is highlighting background enabled? */
+ bool highlightBg() const { return _highlightBg; }
+ /** enable or disable highlighting background*/
+ void setHighlightBg(bool on);
+ QColor bgColor() const { return _bgColor; }
+ void setBgColor(const QColor& color);
+
+ bool spacePoints() const { return _spacePoints; }
+ void setSpacePoints(bool on);
+
+ bool highlightSyntax() const { return _hlSyntax; }
+ void highlight();
+ void setHighlightSyntax(bool on);
+ void setHighlightColors(const QColor& quoteColor, const QColor& unquoteColor
+ , const QColor& cformatColor, const QColor& accelColor, const QColor& tagColor);
+
+ void setFont(const QFont& font);
+
+ void setDiffMode(bool on);
+ void setDiffDisplayMode(bool underlineAdded, bool strikeOutDeleted);
+ void setDiffColors(const QColor& addColor, const QColor& delColor);
+
+ void setTextColor(const QColor &color);
+ void setErrorColor(const QColor &color);
+
+ void setCurrentColor(const TextColor color);
+
+ void setSpellChecker(KSpell* spell);
+
+ void selectTag(int start, int length);
+
+public slots:
+ virtual void setText(const QString& s);
+ void paintSpacePoints();
+ void paintSpacePoints( int para, int pos ); // overloaded for signal QTextEdit::cursorPositionChanged
+
+ /**
+ * reimplemented to call highlight()
+ */
+ void repaint();
+ void forceUpdate();
+ void emittedTextChanged();
+
+ /**
+ * reimplemented to skip in case of disabled updates
+ */
+ void ensureCursorVisible();
+
+protected:
+ virtual void paintEvent (QPaintEvent * event );
+ virtual void drawContents( QPainter *painter, int clipx, int clipy, int clipw, int cliph );
+
+ virtual void keyPressEvent(QKeyEvent*);
+ virtual void keyReleaseEvent(QKeyEvent*);
+
+private:
+ /**
+ * Computes the pixel position in line which corresponds to
+ * character position xIndex
+ */
+ QRect mapToView( int para, int index );
+
+ /**
+ * tests if the character in string str at position col is masked with
+ * '\' by counting the number of '\' backwards
+ */
+ static bool isMasked(QString *str,uint col);
+
+private:
+ bool _quotes;
+ bool _cleverEditing;
+ bool _highlightBg;
+ bool _spacePoints;
+ QColor _bgColor;
+ QColor _textColor;
+ QColor _errorColor;
+ QColor _currentColor;
+
+ QPixmap* _whitespace;
+ QPixmap* _whitespaceNB;
+ QPixmap* _errorWhitespace;
+ QPixmap* _errorWhitespaceNB;
+
+ int _wsOffsetX;
+ int _wsOffsetY;
+
+ bool _hlSyntax;
+ QColor _quoteColor;
+ QColor _unquoteColor;
+ QColor _cformatColor;
+ QColor _accelColor;
+ QColor _tagColor;
+
+ struct DiffInfo
+ {
+ bool add;
+ int begin;
+ int end;
+ };
+
+ QPtrVector< QValueList<DiffInfo> > diffPos;
+ bool _showDiff;
+ bool _diffUnderlineAdd;
+ bool _diffStrikeOutDel;
+ QColor _diffAddColor;
+ QColor _diffDelColor;
+
+ // for Alt+123 feature
+ int _currentUnicodeNumber;
+
+ KBabelHighlighter * highlighter;
+
+ // next tag highlighting
+ int _tagStartPara, _tagStartIndex, _tagEndPara, _tagEndIndex;
+};
+
+#endif // MYMULTILINEEDIT_H
diff --git a/kbabel/kbabel/pics/Makefile.am b/kbabel/kbabel/pics/Makefile.am
new file mode 100644
index 00000000..b5108197
--- /dev/null
+++ b/kbabel/kbabel/pics/Makefile.am
@@ -0,0 +1,6 @@
+# Add all of your pixmaps here
+pics_DATA = broken.png missing.png needwork.png ok.png pref_identity.png \
+ splash.png noflag.png
+
+# This is where it will all be installed
+picsdir = $(kde_datadir)/kbabel/pics
diff --git a/kbabel/kbabel/pics/broken.png b/kbabel/kbabel/pics/broken.png
new file mode 100644
index 00000000..d0948e92
--- /dev/null
+++ b/kbabel/kbabel/pics/broken.png
Binary files differ
diff --git a/kbabel/kbabel/pics/missing.png b/kbabel/kbabel/pics/missing.png
new file mode 100644
index 00000000..e0311068
--- /dev/null
+++ b/kbabel/kbabel/pics/missing.png
Binary files differ
diff --git a/kbabel/kbabel/pics/needwork.png b/kbabel/kbabel/pics/needwork.png
new file mode 100644
index 00000000..e31413d8
--- /dev/null
+++ b/kbabel/kbabel/pics/needwork.png
Binary files differ
diff --git a/kbabel/kbabel/pics/noflag.png b/kbabel/kbabel/pics/noflag.png
new file mode 100644
index 00000000..5b6ad0c2
--- /dev/null
+++ b/kbabel/kbabel/pics/noflag.png
Binary files differ
diff --git a/kbabel/kbabel/pics/ok.png b/kbabel/kbabel/pics/ok.png
new file mode 100644
index 00000000..f2b731a0
--- /dev/null
+++ b/kbabel/kbabel/pics/ok.png
Binary files differ
diff --git a/kbabel/kbabel/pics/pref_identity.png b/kbabel/kbabel/pics/pref_identity.png
new file mode 100644
index 00000000..de7e1459
--- /dev/null
+++ b/kbabel/kbabel/pics/pref_identity.png
Binary files differ
diff --git a/kbabel/kbabel/pics/splash.png b/kbabel/kbabel/pics/splash.png
new file mode 100644
index 00000000..26f908c7
--- /dev/null
+++ b/kbabel/kbabel/pics/splash.png
Binary files differ
diff --git a/kbabel/kbabel/searchpreferences.ui b/kbabel/kbabel/searchpreferences.ui
new file mode 100644
index 00000000..5e002657
--- /dev/null
+++ b/kbabel/kbabel/searchpreferences.ui
@@ -0,0 +1,109 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>SearchPreferences</class>
+<author>Stanislav Visnovsky</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>SearchPreferences</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>600</width>
+ <height>480</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>frame3</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>kcfg_AutoSearch</cstring>
+ </property>
+ <property name="text">
+ <string>Au&amp;tomatically start search</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;&lt;p&gt;&lt;b&gt;Automatically start search&lt;/b&gt;&lt;/p&gt;
+&lt;p&gt;If this is activated, the search is automatically started
+whenever you switch to another entry in the editor. You can
+choose where to search with the combo box &lt;b&gt;Default Dictionary&lt;/b&gt;.
+&lt;/p&gt;&lt;p&gt;You can also start searching manually by choosing an entry in
+the popup menu that appears either when clicking
+&lt;b&gt;Dictionaries-&gt;Find...&lt;/b&gt; or keeping the dictionary button
+in the toolbar pressed for a while.&lt;/p&gt;&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>D&amp;efault dictionary:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>_kcfg_DefaultModule</cstring>
+ </property>
+ </widget>
+ <widget class="QComboBox">
+ <property name="name">
+ <cstring>_kcfg_DefaultModule</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;&lt;p&gt;&lt;b&gt;Default Dictionary&lt;/b&gt;&lt;/p&gt;
+&lt;p&gt;Choose here where to search as default.
+This setting is used when searching is started automatically
+or when pressing the dictionary button in the toolbar.&lt;/p&gt;
+&lt;p&gt;You can configure the different dictionaries by selecting
+the desired dictionary from &lt;b&gt;Settings-&gt;Configure Dictionary&lt;/b&gt;.
+&lt;/p&gt;&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <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>31</width>
+ <height>91</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kbabel/kbabel/sourceview.cpp b/kbabel/kbabel/sourceview.cpp
new file mode 100644
index 00000000..08c0f8a4
--- /dev/null
+++ b/kbabel/kbabel/sourceview.cpp
@@ -0,0 +1,75 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2004-2005 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#include "sourceview.h"
+#include "context.h"
+
+#include <qlayout.h>
+#include <qwhatsthis.h>
+
+#include <kcursor.h>
+#include <klocale.h>
+
+#include "resources.h"
+#include "kbcatalog.h"
+
+using namespace KBabel;
+
+SourceView::SourceView(KBCatalog* catalog,QWidget *parent, Project::Ptr project)
+ : KBCatalogView(catalog,parent,project)
+{
+ QVBoxLayout* layout = new QVBoxLayout( this );
+ layout->setResizeMode( QLayout::Minimum );
+
+ _contextView = new SourceContext (this, project);
+ layout->addWidget (_contextView);
+
+ connect(_catalog, SIGNAL(signalFileOpened(bool)), this, SLOT(setDisabled(bool)));
+}
+
+void SourceView::updateView()
+{
+ if (isVisible ())
+ {
+ // Note: we use Catalog::comment instead of Catalog::context as SourceContext::setContext has to repeat the major part of the code of Catalog::context, so SourceContext::setContext can do the whole job alone.
+ _contextView->setContext( _catalog->packageDir(), _catalog->packageName(), _catalog->comment(_currentIndex), _catalog->currentURL() );
+ }
+}
+
+void SourceView::setProject(KBabel::Project::Ptr project)
+{
+ KBCatalogView::setProject(project);
+ _contextView->setProject(project);
+}
+
+#include "sourceview.moc"
diff --git a/kbabel/kbabel/sourceview.h b/kbabel/kbabel/sourceview.h
new file mode 100644
index 00000000..8caeed35
--- /dev/null
+++ b/kbabel/kbabel/sourceview.h
@@ -0,0 +1,57 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2004-2005 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef SOURCEVIEW_H
+#define SOURCEVIEW_H
+
+#include "kbcatalogview.h"
+
+class SourceContext;
+
+class SourceView : public KBCatalogView
+{
+ Q_OBJECT
+public:
+ /**
+ * Default constructor
+ */
+ SourceView(KBCatalog* catalog,QWidget *parent, KBabel::Project::Ptr project);
+
+public slots:
+ virtual void updateView();
+ virtual void setProject(KBabel::Project::Ptr project);
+
+private:
+ SourceContext* _contextView;
+};
+
+#endif // SOURCEVIEW_H
diff --git a/kbabel/kbabel/spelldlg.cpp b/kbabel/kbabel/spelldlg.cpp
new file mode 100644
index 00000000..49500e09
--- /dev/null
+++ b/kbabel/kbabel/spelldlg.cpp
@@ -0,0 +1,142 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include "spelldlg.h"
+#include "spelldlgwidget.h"
+
+#include <qcheckbox.h>
+#include <qradiobutton.h>
+
+#include <kconfig.h>
+#include <kglobal.h>
+#include <klocale.h>
+
+SpellDlg::SpellDlg(bool haveMarkedText,QWidget *parent,const char *name)
+ : KDialogBase(parent,name,true,i18n("Caption of dialog","Spelling")
+ , Ok|Cancel)
+{
+ setButtonOK(KGuiItem(i18n("&Spell Check"),"spellcheck"));
+
+ _mainWidget = new SpellDlgWidget(this);
+ setMainWidget(_mainWidget);
+
+ if(haveMarkedText)
+ {
+ _mainWidget->markedBtn->setChecked(true);
+ _mainWidget->defaultBtn->setChecked(false);
+ _mainWidget->defaultBtn->setEnabled(false);
+ }
+ else
+ {
+ _mainWidget->markedBtn->setEnabled(false);
+
+ KConfig *config = KGlobal::config();
+ KConfigGroupSaver cs(config,"SpellDlg");
+ QString what=config->readEntry("Default","All");
+
+ if(what=="All")
+ _mainWidget->allBtn->setChecked(true);
+ else if(what=="Current")
+ _mainWidget->currentBtn->setChecked(true);
+ else if(what=="Begin")
+ _mainWidget->beginBtn->setChecked(true);
+ else if(what=="End")
+ _mainWidget->endBtn->setChecked(true);
+ else
+ _mainWidget->allBtn->setChecked(true);
+
+ }
+
+}
+
+SpellDlg::~SpellDlg()
+{
+ if(_mainWidget->defaultBtn->isChecked())
+ {
+ KConfig *config=KGlobal::config();
+ KConfigGroupSaver cs(config,"SpellDlg");
+
+ QString what="All";
+ if(_mainWidget->endBtn->isChecked())
+ what="End";
+ else if(_mainWidget->beginBtn->isChecked())
+ what="Begin";
+ else if(_mainWidget->currentBtn->isChecked())
+ what="Current";
+
+ config->writeEntry("Default",what);
+ }
+}
+
+bool SpellDlg::all() const
+{
+ return _mainWidget->allBtn->isChecked();
+}
+
+bool SpellDlg::current() const
+{
+ return _mainWidget->currentBtn->isChecked();
+}
+
+bool SpellDlg::begin() const
+{
+ return _mainWidget->beginBtn->isChecked();
+}
+
+bool SpellDlg::end() const
+{
+ return _mainWidget->endBtn->isChecked();
+}
+
+bool SpellDlg::marked() const
+{
+ return _mainWidget->markedBtn->isChecked();
+}
+
+
+void SpellDlg::markedChecked(bool on)
+{
+ if(on)
+ {
+ _mainWidget->defaultBtn->setChecked(false);
+ }
+
+ _mainWidget->defaultBtn->setEnabled(!on);
+}
+
+bool SpellDlg::beginCurrent( ) const
+{
+ return _mainWidget->beginCurrentMsgBtn->isChecked( );
+}
+
+
+#include "spelldlg.moc"
diff --git a/kbabel/kbabel/spelldlg.h b/kbabel/kbabel/spelldlg.h
new file mode 100644
index 00000000..ea857777
--- /dev/null
+++ b/kbabel/kbabel/spelldlg.h
@@ -0,0 +1,63 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef SPELLDLG_H
+#define SPELLDLG_H
+
+#include <kdialogbase.h>
+
+
+class SpellDlgWidget;
+
+class SpellDlg : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ SpellDlg(bool haveMarkedText, QWidget* parent, const char *name=0);
+ ~SpellDlg();
+
+ bool all() const;
+ bool current() const;
+ bool begin() const;
+ bool end() const;
+ bool marked() const;
+ bool beginCurrent() const;
+
+private slots:
+ void markedChecked(bool);
+
+private:
+ SpellDlgWidget *_mainWidget;
+};
+
+#endif // SPELLDLG_H
diff --git a/kbabel/kbabel/spelldlgwidget.ui b/kbabel/kbabel/spelldlgwidget.ui
new file mode 100644
index 00000000..fe5a5d0b
--- /dev/null
+++ b/kbabel/kbabel/spelldlgwidget.ui
@@ -0,0 +1,126 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>SpellDlgWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>SpellDlgWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>388</width>
+ <height>262</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>buttonGroup1</cstring>
+ </property>
+ <property name="title">
+ <string>Choose What You Want to Spell Check</string>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Spell check only the current message.</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>allBtn</cstring>
+ </property>
+ <property name="text">
+ <string>A&amp;ll messages</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Spell check all translated messages of this file.</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>currentBtn</cstring>
+ </property>
+ <property name="text">
+ <string>C&amp;urrent message only</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Spell check only the current message.</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>beginCurrentMsgBtn</cstring>
+ </property>
+ <property name="text">
+ <string>Fro&amp;m beginning of current message to end of file</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>beginBtn</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;From beginning of file to cursor position</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Spell check all text from the beginning of the file to the current cursor position.</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>endBtn</cstring>
+ </property>
+ <property name="text">
+ <string>F&amp;rom cursor position to end of file</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Spell check all text from the current cursor position to the end of the file.</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>markedBtn</cstring>
+ </property>
+ <property name="text">
+ <string>S&amp;elected text only</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Spell check only the selected text.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>defaultBtn</cstring>
+ </property>
+ <property name="text">
+ <string>U&amp;se this selection as default</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check this, to store the current selection as default selection.</string>
+ </property>
+ </widget>
+ </vbox>
+</widget>
+<tabstops>
+ <tabstop>allBtn</tabstop>
+ <tabstop>beginBtn</tabstop>
+ <tabstop>markedBtn</tabstop>
+ <tabstop>currentBtn</tabstop>
+ <tabstop>endBtn</tabstop>
+ <tabstop>defaultBtn</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kbabel/kbabel/taglistview.cpp b/kbabel/kbabel/taglistview.cpp
new file mode 100644
index 00000000..8dedccea
--- /dev/null
+++ b/kbabel/kbabel/taglistview.cpp
@@ -0,0 +1,78 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2002-2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#include "taglistview.h"
+
+#include <qlayout.h>
+#include <qwhatsthis.h>
+
+#include <kcursor.h>
+#include <klistbox.h>
+#include <klocale.h>
+
+#include "kbcatalog.h"
+
+using namespace KBabel;
+
+TagListView::TagListView(KBCatalog* catalog,QWidget *parent, Project::Ptr project)
+ : KBCatalogView(catalog,parent,project)
+{
+ QVBoxLayout* layout = new QVBoxLayout( this );
+ layout->setResizeMode( QLayout::Minimum );
+
+ _tagBox = new KListBox (this, "taglist textview");
+
+ layout->addWidget (_tagBox);
+
+ connect(_tagBox,SIGNAL(selected(const QString&))
+ , this, SIGNAL(signalTagSelected(const QString&)));
+ connect(_tagBox,SIGNAL(highlighted(int))
+ , this, SIGNAL(signalHighlightedTagChanged(int)));
+
+ connect(_catalog, SIGNAL(signalFileOpened(bool))
+ , this, SLOT(setDisabled(bool)));
+}
+
+void TagListView::updateView()
+{
+ _tagBox->clear();
+ _tagBox->insertStringList(_catalog->tagList(_currentIndex));
+ _tagBox->setCurrentItem(0);
+}
+
+void TagListView::highlightTag(int index)
+{
+ _tagBox->setCurrentItem(index);
+}
+
+#include "taglistview.moc"
diff --git a/kbabel/kbabel/taglistview.h b/kbabel/kbabel/taglistview.h
new file mode 100644
index 00000000..0435e3ba
--- /dev/null
+++ b/kbabel/kbabel/taglistview.h
@@ -0,0 +1,61 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2004 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef TAGLISTVIEW_H
+#define TAGLISTVIEW_H
+
+#include "kbcatalogview.h"
+
+class KListBox;
+
+class TagListView : public KBCatalogView
+{
+ Q_OBJECT
+public:
+ /**
+ * Default constructor
+ */
+ TagListView(KBCatalog* catalog,QWidget *parent, KBabel::Project::Ptr project);
+
+public slots:
+ virtual void updateView();
+ void highlightTag (int index);
+
+signals:
+ void signalHighlightedTagChanged (int index);
+ void signalTagSelected (const QString& tag);
+
+private:
+ KListBox* _tagBox;
+};
+
+#endif // TAGLISTVIEW_H
diff --git a/kbabel/kbabeldict/Makefile.am b/kbabel/kbabeldict/Makefile.am
new file mode 100644
index 00000000..3720988f
--- /dev/null
+++ b/kbabel/kbabeldict/Makefile.am
@@ -0,0 +1,66 @@
+## Makefile.am for kbabeldict
+
+# this has all of the subdirectories that make will recurse into. if
+# there are none, comment this out
+SUBDIRS = . modules
+
+pkgincludedir = $(includedir)/kbabel
+
+# this is the program that gets installed. it's name is used for all
+# of the other Makefile.am variables
+noinst_LTLIBRARIES = libkbabeldict.la
+bin_PROGRAMS = kbabeldict
+
+# set the include path for X, qt and KDE
+INCLUDES = -I$(srcdir)/../common -I$(top_builddir)/kbabel/common $(all_includes)
+
+
+# library for babeldict plugins
+lib_LTLIBRARIES = libkbabeldictplugin.la
+libkbabeldictplugin_la_SOURCES = searchengine.cpp
+libkbabeldictplugin_la_LIBADD = $(LIB_KDECORE)
+libkbabeldictplugin_la_LDFLAGS = -version-info 3:0:2 $(all_libraries)
+
+libkbabeldict_la_SOURCES = kbabeldictbox.cpp \
+ kbabeldictiface.skel dictionarymenu.cpp dictchooser.cpp \
+ aboutmoduledlg.cpp
+libkbabeldict_la_LIBADD = ../common/libkbabelcommon.la libkbabeldictplugin.la $(LIB_KDEUI)
+libkbabeldict_la_LDFLAGS = $(all_libraries) -no-undefined
+
+
+kbabeldict_SOURCES = main.cpp kbabeldictview.cpp kbabeldict.cpp kbabelsplash.cpp
+
+# the libraries to link against.
+kbabeldict_LDADD = libkbabeldict.la
+kbabeldict_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+
+# these are the headers for your project
+noinst_HEADERS = kbabeldict.h kbabeldictview.h kbabelsplash.h aboutmoduledlg.h
+pkginclude_HEADERS = searchengine.h kbabeldictbox.h kbabeldictiface.h \
+dictionarymenu.h dictchooser.h
+
+
+# let automoc handle all of the meta source files (moc)
+METASOURCES = AUTO
+
+KDE_OPTIONS = nofinal
+#rcdir = $(kde_datadir)/kbabel
+#rc_DATA = kbabelui.rc
+
+api:
+ mkdir -p API && kdoc -d API -u $$PWD/API -p -lkdeui -lkdecore -lqt -ldcop *.h
+
+distclean-local:
+ rm -r -f API
+
+KDE_ICON = kbabeldict
+
+ # this is where the kdelnk file will go
+xdg_apps_DATA = kbabeldict.desktop
+
+kde_servicetypes_DATA = kbabeldict_module.desktop
+EXTRA_DIST = $(kde_servicetypes_DATA)
+
+kbabeldictbox.lo: ../common/version.h
+main.o: ../common/version.h
+
diff --git a/kbabel/kbabeldict/README b/kbabel/kbabeldict/README
new file mode 100644
index 00000000..9a4eb950
--- /dev/null
+++ b/kbabel/kbabeldict/README
@@ -0,0 +1,5 @@
+This directory contains a standalone application to search for translations
+as you can do in KBabel and the framework for loading plugins for
+searching in different types of translation sources. This way
+KBabel can be easily extended. For more information about
+developing a search module for KBabel see file README.modules
diff --git a/kbabel/kbabeldict/README.modules b/kbabel/kbabeldict/README.modules
new file mode 100644
index 00000000..a672743b
--- /dev/null
+++ b/kbabel/kbabeldict/README.modules
@@ -0,0 +1,34 @@
+This directory contains the framework for KBabel to be easily extensible with
+plugins for searching translations.
+
+For an examples of modules see subdirectory "modules".
+
+
+Here is a short description, how to write an module:
+
+First off all, the module must inherit the interface class SearchEngine and
+has to implement all the virtual functions in there. Also a preferences
+widget must be available, that has to inherit from PrefWidget.
+Just include searchengine.h to have everything necessary available.
+
+Then you module has to be compiled as shared library and there must be a
+factory available, so that it can be loaded with KLibLoader. See
+documentation of KLibLoader for more details. The library should be prefixed
+by "kbabeldict_" instead of more common "lib". This is to indicate that it is
+a module for KBabelDict.
+
+The method of dictionary loading has changed in KBabel 1.2, but the
+modules for previous versions should work. Here is how to install
+the dictionary: You should define a standard KDE service desktop file.
+The most important entry is
+
+X-KDE-Library=<libname>
+
+where <libname> is the name of the shared library, that contains your
+SearchEngine, for example "kbabeldict_pocompendium".
+Additionally you can add a list of applications, to them your module is
+restricted to with "Applications=<list>". For example with "Applications=kbabel",
+your module will only be used in KBabel. If you omit the entry, the
+module can be used in any application.
+
+
diff --git a/kbabel/kbabeldict/aboutmoduledlg.cpp b/kbabel/kbabeldict/aboutmoduledlg.cpp
new file mode 100644
index 00000000..eaab8b3b
--- /dev/null
+++ b/kbabel/kbabeldict/aboutmoduledlg.cpp
@@ -0,0 +1,54 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2001 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include "aboutmoduledlg.h"
+
+#include <kbugreport.h>
+#include <klocale.h>
+
+AboutModuleDlg::AboutModuleDlg(const KAboutData *aboutData, QWidget *parent)
+ : KAboutApplication(aboutData, parent)
+ , _aboutData(aboutData)
+{
+ setHelpLinkText(i18n("Report Bug..."));
+ enableLinkedHelp(true);
+}
+
+void AboutModuleDlg::helpClickedSlot(const QString&)
+{
+ KBugReport *bugReport = new KBugReport(0,true,_aboutData);
+
+ bugReport->exec();
+
+ delete bugReport;
+}
+#include "aboutmoduledlg.moc"
diff --git a/kbabel/kbabeldict/aboutmoduledlg.h b/kbabel/kbabeldict/aboutmoduledlg.h
new file mode 100644
index 00000000..f79d77ec
--- /dev/null
+++ b/kbabel/kbabeldict/aboutmoduledlg.h
@@ -0,0 +1,55 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2001 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#ifndef ABOUTMODULEDLG_H
+#define ABOUTMODULEDLG_H
+
+#include <kaboutapplication.h>
+
+
+class AboutModuleDlg : public KAboutApplication
+{
+ Q_OBJECT
+
+public:
+ AboutModuleDlg(const KAboutData *aboutData, QWidget* parent=0);
+
+public slots:
+ virtual void helpClickedSlot(const QString&);
+
+private:
+ const KAboutData *_aboutData;
+};
+
+#endif
diff --git a/kbabel/kbabeldict/dictchooser.cpp b/kbabel/kbabeldict/dictchooser.cpp
new file mode 100644
index 00000000..f9360b61
--- /dev/null
+++ b/kbabel/kbabeldict/dictchooser.cpp
@@ -0,0 +1,335 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2001 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2003 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include "dictchooser.h"
+#include "resources.h"
+
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <kconfig.h>
+#include <klistbox.h>
+#include <klocale.h>
+#include <kdialog.h>
+#include <ktempfile.h>
+
+DictChooser::DictChooser(KBabelDictBox*b, QStringList selected
+ , QWidget *parent, const char *name)
+ : QWidget(parent,name), box(b)
+{
+ tempConfig.clear();
+ tempConfig.setAutoDelete(true);
+
+ dictList = box->moduleInfos();
+ QGridLayout *layout = new QGridLayout(this);
+ layout->setSpacing(KDialog::spacingHint());
+
+
+ QLabel *label = new QLabel(i18n("dictionary to not use","Do not use:"),this);
+ layout->addWidget(label,0,0);
+
+ label = new QLabel(i18n("dictionary to use","Use:"),this);
+ layout->addWidget(label,0,2);
+
+ unselectedBox = new KListBox(this,"unselectedBox");
+ layout->addWidget(unselectedBox,1,0);
+
+
+ QVBoxLayout *bLayout = new QVBoxLayout();
+ selectBtn = new QPushButton(" &>> ", this);
+ selectBtn->setEnabled(false);
+ bLayout->addWidget(selectBtn);
+ unselectBtn = new QPushButton(" &<< ", this);
+ unselectBtn->setEnabled(false);
+ bLayout->addWidget(unselectBtn);
+ bLayout->addStretch();
+ layout->addLayout(bLayout,1,1);
+
+ selectedBox = new KListBox(this,"selectedBox");
+ layout->addWidget(selectedBox,1,2);
+
+
+ bLayout = new QVBoxLayout();
+ upBtn = new QPushButton(i18n("Move &Up"), this);
+ upBtn->setEnabled(false);
+ bLayout->addWidget(upBtn);
+ downBtn = new QPushButton(i18n("Move &Down"), this);
+ downBtn->setEnabled(false);
+ bLayout->addWidget(downBtn);
+ configureBtn = new QPushButton(i18n("Con&figure..."), this);
+ bLayout->addWidget(configureBtn);
+ bLayout->addStretch();
+ layout->addLayout(bLayout,1,3);
+
+
+ dictList.setAutoDelete(true);
+ ModuleInfo *mi;
+ for(QStringList::Iterator it=selected.begin(); it!=selected.end();
+ ++it)
+ {
+ for(mi = dictList.first(); mi != 0; mi = dictList.next())
+ {
+ if(mi->id==*it)
+ {
+ selectedBox->insertItem(mi->name);
+ }
+ }
+ }
+
+ for(mi = dictList.first(); mi != 0; mi = dictList.next())
+ {
+ if(!selected.contains(mi->id))
+ {
+ unselectedBox->insertItem(mi->name);
+ }
+ }
+
+ if(selectedBox->count() == 0 && unselectedBox->count() > 0)
+ {
+ selectedBox->insertItem(unselectedBox->text(0));
+ unselectedBox->removeItem(0);
+ }
+
+
+ connect(selectedBox,SIGNAL(highlighted(int)), this
+ , SLOT(selectedMarked(int)));
+ connect(unselectedBox,SIGNAL(highlighted(int)), this
+ , SLOT(unselectedMarked(int)));
+
+ connect(selectBtn, SIGNAL(clicked()), this, SLOT(select()));
+ connect(unselectBtn, SIGNAL(clicked()), this, SLOT(unselect()));
+ connect(upBtn, SIGNAL(clicked()), this, SLOT(up()));
+ connect(downBtn, SIGNAL(clicked()), this, SLOT(down()));
+ connect(configureBtn,SIGNAL(clicked()), this
+ , SLOT(configureSelected()));
+
+
+ selectedBox->installEventFilter(this);
+ unselectedBox->installEventFilter(this);
+
+ int min = minimumHeight();
+ if(min < 100)
+ setMinimumHeight(100);
+}
+
+
+QStringList DictChooser::selectedDicts()
+{
+ QStringList selected;
+
+ for(int i = 0; i < (int)selectedBox->count(); i++)
+ {
+ QString text = selectedBox->text(i);
+
+ ModuleInfo *mi;
+ for(mi = dictList.first(); mi!=0; mi = dictList.next())
+ {
+ if(mi->name == text)
+ {
+ selected.append(mi->id);
+ }
+ }
+ }
+
+ return selected;
+}
+
+
+void DictChooser::selectedMarked(int index)
+{
+ unselectedBox->selectAll(false);
+
+ unselectBtn->setEnabled(selectedBox->count() > 1);
+ selectBtn->setEnabled(false);
+ downBtn->setEnabled((int)selectedBox->count()-1 > index);
+ upBtn->setEnabled(index > (int)0);
+}
+
+void DictChooser::unselectedMarked(int)
+{
+ selectedBox->selectAll(false);
+
+ selectBtn->setEnabled(true);
+ unselectBtn->setEnabled(false);
+ downBtn->setEnabled(false);
+ upBtn->setEnabled(false);
+}
+
+
+void DictChooser::select()
+{
+ int i = unselectedBox->currentItem();
+ if(i >= 0)
+ {
+ QString text = unselectedBox->text(i);
+ selectedBox->insertItem(text);
+
+ unselectedBox->removeItem(i);
+
+ if(unselectedBox->count() == 0)
+ {
+ selectBtn->setEnabled(false);
+ }
+ else
+ {
+ unselectedBox->setSelected(i,true);
+ }
+ }
+}
+
+
+void DictChooser::unselect()
+{
+ int i = selectedBox->currentItem();
+ if(i >= 0 && selectedBox->count() > 1)
+ {
+ QString text = selectedBox->text(i);
+ unselectedBox->insertItem(text);
+
+ selectedBox->removeItem(i);
+
+ if(i < (int)selectedBox->count()-1)
+ {
+ selectedBox->setSelected(i,true);
+ }
+ else
+ {
+ selectedBox->setSelected(i-1,true);
+ }
+ }
+}
+
+
+void DictChooser::up()
+{
+ int i = selectedBox->currentItem();
+ if(i > 0)
+ {
+ QString text = selectedBox->text(i);
+ selectedBox->changeItem(selectedBox->text(i-1),i);
+ selectedBox->changeItem(text,i-1);
+ selectedBox->setSelected(i-1,true);
+ }
+}
+
+
+void DictChooser::down()
+{
+ int i = selectedBox->currentItem();
+ if(i < (int)selectedBox->count()-1)
+ {
+ QString text = selectedBox->text(i);
+ selectedBox->changeItem(selectedBox->text(i+1),i);
+ selectedBox->changeItem(text,i+1);
+ selectedBox->setSelected(i+1,true);
+ }
+}
+
+
+bool DictChooser::eventFilter(QObject *object, QEvent *event)
+{
+ if(event->type() == QEvent::FocusIn)
+ {
+ if(object==selectedBox)
+ {
+ int i = selectedBox->currentItem();
+ selectedBox->setSelected(i,true);
+ selectedMarked(i);
+ unselectedBox->clearSelection();
+ }
+ else
+ {
+ int i = unselectedBox->currentItem();
+ if(i >= 0)
+ {
+ unselectedBox->setSelected(i,true);
+ unselectedMarked(i);
+ selectedBox->clearSelection();
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+void DictChooser::configureSelected()
+{
+ int ci = selectedBox->currentItem();
+ if( ci == -1 ) ci = 0; // there is always at least one item
+ QString module = selectedBox->text(ci);
+
+ ModuleInfo *mi;
+ for(mi = dictList.first(); mi!=0; mi = dictList.next())
+ {
+ if(mi->name == module)
+ {
+ // do backup first
+ if( !tempConfig[mi->id])
+ {
+ KTempFile* tmp=new KTempFile();
+ tmp->setAutoDelete(true);
+ tempConfig.insert(mi->id ,tmp);
+
+ kdDebug(KBABEL_SEARCH) << "Temp file: " << tmp->name() << endl;
+ KConfig config(tmp->name());
+ config.setGroup(mi->id);
+ box->saveSettings(mi->id, &config);
+ }
+
+ // now let user change configuration
+ box->configure(mi->id,true);
+ break;
+ }
+ }
+}
+
+void DictChooser::restoreConfig()
+{
+ kdDebug( KBABEL_SEARCH ) << "Cleanup" << endl;
+ // cleanup
+ QDictIterator<KTempFile> it( tempConfig ); // See QDictIterator
+ for( ; it.current(); ++it )
+ {
+ KConfig config( it.current()->name() );
+ config.setGroup( it.currentKey() );
+ box->readSettings( it.currentKey(), &config);
+ }
+
+ // there is no temporary configs
+ tempConfig.clear();
+}
+
+#include "dictchooser.moc"
diff --git a/kbabel/kbabeldict/dictchooser.h b/kbabel/kbabeldict/dictchooser.h
new file mode 100644
index 00000000..2b757455
--- /dev/null
+++ b/kbabel/kbabeldict/dictchooser.h
@@ -0,0 +1,94 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2001 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2003 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef DICTCHOOSER_H
+#define DICTCHOOSER_H
+
+#include <qptrlist.h>
+#include <qstringlist.h>
+#include <qwidget.h>
+#include <kbabeldictbox.h>
+
+class KListBox;
+class KTempFile;
+
+class QPushButton;
+class QListBoxItem;
+
+
+class KDE_EXPORT DictChooser : public QWidget
+{
+ Q_OBJECT
+
+public:
+ DictChooser(KBabelDictBox* box, QStringList selected,
+ QWidget *parent , const char *name=0);
+
+ QStringList selectedDicts();
+
+ /** If the user configured some of the modules, this
+ * restores the original configuration of all these modules
+ */
+ void restoreConfig();
+
+ virtual bool eventFilter(QObject *, QEvent *);
+
+private slots:
+ void select();
+ void unselect();
+ void up();
+ void down();
+
+ void selectedMarked(int);
+ void unselectedMarked(int);
+
+ void configureSelected();
+
+private:
+ KBabelDictBox* box;
+ QPtrList<ModuleInfo> dictList;
+
+ KListBox *selectedBox;
+ KListBox *unselectedBox;
+
+ QPushButton *selectBtn;
+ QPushButton *unselectBtn;
+ QPushButton *upBtn;
+ QPushButton *downBtn;
+ QPushButton *configureBtn;
+
+ QDict<KTempFile> tempConfig;
+};
+
+#endif // DICTCHOOSER_H
diff --git a/kbabel/kbabeldict/dictionarymenu.cpp b/kbabel/kbabeldict/dictionarymenu.cpp
new file mode 100644
index 00000000..2ed57d5f
--- /dev/null
+++ b/kbabel/kbabeldict/dictionarymenu.cpp
@@ -0,0 +1,154 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include "dictionarymenu.h"
+#include <kpopupmenu.h>
+#include <kaction.h>
+#include <kdebug.h>
+#include <kshortcut.h>
+
+#include <qsignalmapper.h>
+
+DictionaryMenu::DictionaryMenu(KPopupMenu *popupMenu, KActionCollection *collection
+ , QObject *parent)
+ : QObject(parent, "dictionarymenu")
+ , popup(popupMenu)
+ , actionCollection(collection)
+ , maxId(10)
+{
+ num2id.setAutoDelete(true);
+ accel2id.setAutoDelete(true);
+
+ if(popup)
+ {
+ connect(popup,SIGNAL(activated(int)),this,SLOT(activated(int)));
+ }
+
+ dictionaryMapper = new QSignalMapper( this );
+ connect( dictionaryMapper, SIGNAL( mapped( int ) ),
+ this, SLOT( activated( int ) ) );
+
+}
+
+DictionaryMenu::~DictionaryMenu()
+{
+ clear();
+}
+
+void DictionaryMenu::clear()
+{
+ if(popup)
+ {
+ QIntDictIterator<QString> it( num2id ); // iterator for dict
+ while ( it.current() )
+ {
+ popup->removeItem(it.currentKey());
+ ++it;
+ }
+ }
+
+ num2id.clear();
+
+ // create new mapper
+ delete dictionaryMapper;
+ dictionaryMapper = new QSignalMapper( this );
+ connect( dictionaryMapper, SIGNAL( mapped( int ) ),
+ this, SLOT( activated( int ) ) );
+}
+
+void DictionaryMenu::add(const QString& name, const QString& moduleId)
+{
+ if(popup)
+ {
+ KAction* dictionaryAction = new KAction( name, 0, dictionaryMapper, SLOT(map()), actionCollection, moduleId.utf8() );
+
+ uint id = maxId++;
+ dictionaryAction->plug(popup, id);
+
+ dictionaryMapper->setMapping( dictionaryAction, id );
+
+ QString *idString = new QString(moduleId);
+ num2id.insert(id,idString);
+ }
+
+}
+
+void DictionaryMenu::add(const QString& n, const QString& moduleId
+ , const QString& key)
+{
+ if(popup)
+ {
+ QString name=n;
+
+ QString keyString=key;
+ if(keyString.contains("%1"))
+ {
+ keyString=key.arg(accel2id.count()+1);
+ }
+ KShortcut k(keyString);
+
+ KAction* dictionaryAction = new KAction( name, k, dictionaryMapper, SLOT(map()), actionCollection, key.arg(moduleId).utf8() );
+ uint id = maxId++;
+ dictionaryAction->plug(popup,id);
+
+ if(!k.isNull())
+ {
+ QString *idString = new QString(moduleId);
+ accel2id.insert(id,idString);
+
+ dictionaryMapper->setMapping( dictionaryAction, id );
+
+ name+='\t';
+ name+=k.toString();
+ }
+ else
+ {
+ kdWarning() << "key not valid" << endl;
+ }
+
+ QString *idString = new QString(moduleId);
+ num2id.insert(id,idString);
+ }
+}
+
+
+void DictionaryMenu::activated(int id)
+{
+ QString *idString = num2id[id];
+
+ if(idString)
+ {
+ emit activated(*idString);
+ }
+}
+
+#include "dictionarymenu.moc"
diff --git a/kbabel/kbabeldict/dictionarymenu.h b/kbabel/kbabeldict/dictionarymenu.h
new file mode 100644
index 00000000..c688508e
--- /dev/null
+++ b/kbabel/kbabeldict/dictionarymenu.h
@@ -0,0 +1,81 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef DICTIONARYMENU_H
+#define DICTIONARYMENU_H
+
+#include <qintdict.h>
+#include <qobject.h>
+#include <qstringlist.h>
+#include <qguardedptr.h>
+#include <kdemacros.h>
+
+class QSignalMapper;
+class KPopupMenu;
+class KActionCollection;
+
+class KDE_EXPORT DictionaryMenu : public QObject
+{
+ Q_OBJECT
+
+public:
+ DictionaryMenu(KPopupMenu *menu, KActionCollection *collection, QObject *parent=0);
+ ~DictionaryMenu();
+
+ void add(const QString& name,const QString& id);
+
+ /**
+ * Adds an item to this menu and to the keyboard accelerator.
+ * If key contains %1 it is replaced with a number 1-9
+ */
+ void add(const QString& name,const QString& id, const QString& key);
+
+ void clear();
+
+signals:
+ void activated(const QString moduleId);
+
+private slots:
+ void activated(int);
+
+private:
+ QGuardedPtr<KPopupMenu> popup;
+ QGuardedPtr<KActionCollection> actionCollection;
+ QIntDict<QString> num2id;
+ QIntDict<QString> accel2id;
+ QSignalMapper* dictionaryMapper;
+
+ uint maxId;
+};
+
+#endif
+
diff --git a/kbabel/kbabeldict/hi16-app-kbabeldict.png b/kbabel/kbabeldict/hi16-app-kbabeldict.png
new file mode 100644
index 00000000..eedcb0c1
--- /dev/null
+++ b/kbabel/kbabeldict/hi16-app-kbabeldict.png
Binary files differ
diff --git a/kbabel/kbabeldict/hi32-app-kbabeldict.png b/kbabel/kbabeldict/hi32-app-kbabeldict.png
new file mode 100644
index 00000000..d6d23a0a
--- /dev/null
+++ b/kbabel/kbabeldict/hi32-app-kbabeldict.png
Binary files differ
diff --git a/kbabel/kbabeldict/hi48-app-kbabeldict.png b/kbabel/kbabeldict/hi48-app-kbabeldict.png
new file mode 100644
index 00000000..75eb285b
--- /dev/null
+++ b/kbabel/kbabeldict/hi48-app-kbabeldict.png
Binary files differ
diff --git a/kbabel/kbabeldict/kbabeldict.cpp b/kbabel/kbabeldict/kbabeldict.cpp
new file mode 100644
index 00000000..ebb68227
--- /dev/null
+++ b/kbabel/kbabeldict/kbabeldict.cpp
@@ -0,0 +1,113 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include "kbabeldict.h"
+#include "kbabeldictview.h"
+
+#include <kdebug.h>
+
+KBabelDict::KBabelDict()
+ : KDialogBase(0,"kbabeldictmain",false,i18n("KBabelDict")
+ , Close|Help|User1|User2|User3|Ok, Ok, true
+ , i18n("About"), i18n("About Module")
+ , i18n("Hide Sett&ings"))
+{
+ connect(this, SIGNAL(closeClicked()),this,SLOT(saveConfig()));
+ connect(this, SIGNAL(closeClicked()),this,SLOT(quit()));
+
+ view = new KBabelDictView(this);
+ connect(this, SIGNAL(user1Clicked()), view, SLOT(about()));
+ connect(this, SIGNAL(user2Clicked()), view, SLOT(aboutModule()));
+ connect(this, SIGNAL(user3Clicked()), this, SLOT(togglePref()));
+
+ // HACK: hide default button, otherwise it would be Help button
+ showButtonOK(false);
+
+ // KBabelDict has not a separate help file, so point to the correct part of the KBabel documentation
+ setHelp( "using-kbabeldict", "kbabel" );
+
+ setMainWidget(view);
+
+ readConfig();
+}
+
+KBabelDict::~KBabelDict()
+{
+ delete(view);
+}
+
+void KBabelDict::saveConfig()
+{
+ KConfig *config=KGlobal::config();
+ KConfigGroupSaver gs(config,"KBabelDict");
+ config->writeEntry("Preferences",view->prefVisible());
+}
+
+void KBabelDict::readConfig()
+{
+ KConfig *config=KGlobal::config();
+ KConfigGroupSaver gs(config,"KBabelDict");
+ bool pref=config->readBoolEntry("Preferences",true);
+
+ if(view->prefVisible() != pref)
+ {
+ togglePref();
+ }
+}
+
+void KBabelDict::quit()
+{
+ kapp->quit();
+}
+
+void KBabelDict::togglePref()
+{
+ view->togglePref();
+
+ if(view->prefVisible())
+ {
+ setButtonText(User3,i18n("Hide Sett&ings"));
+ }
+ else
+ {
+ setButtonText(User3,i18n("Show Sett&ings"));
+ }
+}
+
+
+#include "kbabeldict.moc"
diff --git a/kbabel/kbabeldict/kbabeldict.desktop b/kbabel/kbabeldict/kbabeldict.desktop
new file mode 100644
index 00000000..21b60a04
--- /dev/null
+++ b/kbabel/kbabeldict/kbabeldict.desktop
@@ -0,0 +1,96 @@
+[Desktop Entry]
+Name=KBabel Dictionary
+Name[bg]=Речник - KBabel
+Name[br]=Geriadur KBabel
+Name[ca]=Diccionari de KBabel
+Name[cs]=Slovník (KBabel)
+Name[da]=KBabel ordbog
+Name[de]=KBabel-Wörterbuch
+Name[el]=Λεξικό του KBabel
+Name[eo]=Babelo-vortaro
+Name[es]=Diccionario de KBabel
+Name[et]=Sõnaraamat
+Name[eu]=KBabel hiztegia
+Name[fa]=واژه‌نامۀKBabel
+Name[fi]=KBabel-sanakirja
+Name[fr]=Dictionnaire de KBabel
+Name[ga]=Foclóir KBabel
+Name[gl]=Dicionario de KBabel
+Name[he]=KBabel - מילון
+Name[hu]=KBabel szótár
+Name[is]=KBabel orðabók
+Name[it]=Dizionario di KBabel
+Name[ja]=KBabel 辞書
+Name[ka]=KBabel ლექსიკáƒáƒœáƒ˜
+Name[kk]=KBabel Ñөздігі
+Name[lt]=KBabel žodynas
+Name[nb]=KBabel-ordbok
+Name[nds]=KBabel-Wöörbook
+Name[ne]=केबà¥à¤¯à¤¾à¤¬à¤² शबà¥à¤¦à¤•à¥‹à¤¶
+Name[nl]=KBabel woordenboek
+Name[nn]=KBabel-ordbok
+Name[pa]=ਕੇਬਬੇਲ ਸ਼ਬਦ-ਕੋਸ਼
+Name[pl]=SÅ‚ownik programu KBabel
+Name[pt]=Dicionário do KBabel
+Name[pt_BR]=Dicionário do KBabel
+Name[ru]=KBabel - Словарь
+Name[sk]=KBabel slovník
+Name[sl]=Slovar za KBabel
+Name[sr]=KBabel-ов Речник
+Name[sr@Latn]=KBabel-ov ReÄnik
+Name[sv]=Kbabel ordlista
+Name[tr]=KBabel Sözlüğü
+Name[uk]=Словник KBabel
+Name[zh_CN]=KBabel è¯å…¸
+Name[zh_TW]=KBabel å­—å…¸
+GenericName=Translation Tool Dictionary
+GenericName[bg]=Речник за инÑтрумента за превод
+GenericName[br]=Geriaoueg an ostilh troidigezh
+GenericName[ca]=Diccionari de l'eina de traducció
+GenericName[cs]=Překladový slovník
+GenericName[da]=Ordbog til oversættelsesværktøj
+GenericName[de]=Wörterbuch für Übersetzungsprogramm
+GenericName[el]=Λεξικό εÏγαλείου μετάφÏασης
+GenericName[eo]=Tradukila Vortaro
+GenericName[es]=Diccionario de la herramienta de traducción
+GenericName[et]=KBabel'i sõnaraamat
+GenericName[eu]=Itzulpen tresnen hiztegia
+GenericName[fa]=واژه‌نامۀ ابزار ترجمه
+GenericName[fi]=Käännöstyökalun sanakirja
+GenericName[fr]=Dictionnaire d'un outil de traduction
+GenericName[ga]=Uirlis Aistriúcháin - Foclóir
+GenericName[gl]=Dicionario da ferramenta de tradución
+GenericName[he]=מילון של כלי תרגו×
+GenericName[hu]=Fordítássegítő szótár
+GenericName[is]=Þýðingaforrit orðabók
+GenericName[it]=Dizionario di uno strumento di traduzione
+GenericName[ja]=翻訳ツール辞書
+GenericName[ka]=თáƒáƒ áƒ’მნის ხელსáƒáƒ¬áƒ§áƒáƒ¡ ლექსიკáƒáƒœáƒ˜
+GenericName[kk]=Ðудару құралының Ñөздігі
+GenericName[lt]=Vertimo įrankio žodynas
+GenericName[nb]=Ordbok for oversettingsverktøy
+GenericName[nds]=Översettenwarktüüch-Wöörbook
+GenericName[ne]=अनà¥à¤¬à¤¾à¤¦ उपकरण शबà¥à¤¦à¤•à¥‹à¤¶
+GenericName[nl]=Vertaalhulpmiddel woordenboek
+GenericName[nn]=Ordbok for omsetjingsverktøy
+GenericName[pa]=ਅਨà©à¨µà¨¾à¨¦ ਸੰਦ ਲਈ ਸ਼ਬਦ-ਕੋਸ਼
+GenericName[pl]=Słownik do narzędzia tłumaczy
+GenericName[pt]=Dicionário da Ferramenta de Tradução
+GenericName[pt_BR]=Dicionário da Ferramenta de Tradução
+GenericName[ru]=ПоиÑк в готовых переводах
+GenericName[sk]=Slovník pre prekladací nástroj
+GenericName[sl]=Slovar orodja za prevajanje
+GenericName[sr]=Речник преводилачких алата
+GenericName[sr@Latn]=ReÄnik prevodilaÄkih alata
+GenericName[sv]=Översättningsverktyg ordlista
+GenericName[tr]=Çeviri Aracı Sözlüğü
+GenericName[uk]=Словник заÑобу Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐºÐ»Ð°Ð´Ñ–Ð²
+GenericName[zh_CN]=翻译工具è¯å…¸
+GenericName[zh_TW]=翻譯工具字典
+Exec=kbabeldict %i %m -caption "%c"
+Icon=kbabeldict
+Type=Application
+Terminal=false
+X-KDE-StartupNotify=true
+X-DCOP-ServiceType=Unique
+Categories=Qt;KDE;Development;Translation;
diff --git a/kbabel/kbabeldict/kbabeldict.h b/kbabel/kbabeldict/kbabeldict.h
new file mode 100644
index 00000000..3bfca817
--- /dev/null
+++ b/kbabel/kbabeldict/kbabeldict.h
@@ -0,0 +1,62 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#ifndef KBABELDICT_H
+#define KBABELDICT_H
+
+#include <kdialogbase.h>
+
+class KBabelDictView;
+
+class KBabelDict : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ KBabelDict();
+ ~KBabelDict();
+
+protected slots:
+ void saveConfig();
+ void quit();
+ void togglePref();
+
+protected:
+ void readConfig();
+
+private:
+ KBabelDictView *view;
+};
+
+#endif
diff --git a/kbabel/kbabeldict/kbabeldict_module.desktop b/kbabel/kbabeldict/kbabeldict_module.desktop
new file mode 100644
index 00000000..c5a019d1
--- /dev/null
+++ b/kbabel/kbabeldict/kbabeldict_module.desktop
@@ -0,0 +1,54 @@
+[Desktop Entry]
+Type=ServiceType
+X-KDE-ServiceType=KBabelDictModule
+Comment=Dictionary module for KBabelDict
+Comment[bg]=Речников модул за KBabelDict
+Comment[br]=Mollad geriaoueg evit KBabelDict
+Comment[bs]=RjeÄniÄki modul za KBabelDict
+Comment[ca]=Mòdul de diccionari per a KBabelDict
+Comment[cs]=Modul se slovníkem pro KBabelDict
+Comment[cy]=Modiwl geiriadur i KBabelDict
+Comment[da]=Ordbogsmodul for KBabelDict
+Comment[de]=Wörterbuch-Modul für KBabelDict
+Comment[el]=ΆÏθÏωμα Î»ÎµÎ¾Î¹ÎºÎ¿Ï Î³Î¹Î± το KBabelDict
+Comment[es]=Módulo de diccionario para KBabelDict
+Comment[et]=KBabelDicti sõnaraamatumoodul
+Comment[eu]=Hiztegi modulua KBabelDict-entzat
+Comment[fa]=پیمانۀ واژه‌نامه برایKBabelDict
+Comment[fi]=KBabelDict-ohjelman sanakirjamoduuli
+Comment[fr]=Module de dictionnaire pour KBabelDict
+Comment[ga]=Modúl foclóra le haghaidh KBabelDict
+Comment[gl]=Módulo de dicionario para KBabelDict
+Comment[hi]=के-बेबल-डिकà¥à¤¶ के लिठशबà¥à¤¦à¤•à¥‹à¤¶ मॉडà¥à¤¯à¥‚ल
+Comment[hu]=Szótármodul a KBabelDicthez
+Comment[is]=Orðabókareining fyrir KBabel
+Comment[it]=Modulo dizionario per KBabelDict
+Comment[ja]=KBabelDict 辞書モジュール
+Comment[ka]=ლექსიკáƒáƒœáƒ˜áƒ¡ მáƒáƒ“ული KBabelDict-სთვის
+Comment[kk]=KBabelDict-Ñ‚Ñ–Ò£ Ñөздік модулі
+Comment[lt]=KBabelDict žodyno modulis
+Comment[ms]=Modul kamus untuk KBabelDict
+Comment[nb]=Ordboksmodul for KBabelDict
+Comment[nds]=Wöörbookmoduul för KBabelDict
+Comment[ne]=KBabelDict का लागि शबà¥à¤¦à¤•à¥‹à¤¶ मोडà¥à¤¯à¥à¤²
+Comment[nl]=Woordenboekmodule voor KBabelDict
+Comment[nn]=Ordboksmodul for KBabelDict
+Comment[pa]=ਕੇਬਬੇਲ-ਸ਼ਬਦਕੋਸ਼ ਲਈ ਸ਼ਬਦ-ਕੋਸ਼ ਮੈਡੀਊਲ
+Comment[pl]=Moduł słownika dla KBabelDict
+Comment[pt]=Módulo de dicionário para o KBabelDict
+Comment[pt_BR]=Módulo de dicionário para o KBabekDict
+Comment[ru]=Модуль ÑÐ»Ð¾Ð²Ð°Ñ€Ñ Ð´Ð»Ñ KBabelDict
+Comment[sk]=Modul slovníka pre KBabelDict
+Comment[sl]=Slovarski modul za KBabelDict
+Comment[sr]=Модул речника за KBabelDict
+Comment[sr@Latn]=Modul reÄnika za KBabelDict
+Comment[sv]=Ordlistemodul för Kbabeldict
+Comment[ta]= Kபாபேலà¯à®•à¯à®•à®¾à®© அகராதி கூறà¯
+Comment[tg]=Модули луғат барои KBabelDict
+Comment[tr]=KBabelDict için Sözlük Modülü
+Comment[uk]=Модуль Ñловника Ð´Ð»Ñ KBabelDict
+Comment[zh_CN]=KBabelDict çš„è¯å…¸æ¨¡å—
+Comment[zh_TW]=KBabelDict 字典模組
+
+[PropertyDef::Applications]
+Type=QStringList
diff --git a/kbabel/kbabeldict/kbabeldictbox.cpp b/kbabel/kbabeldict/kbabeldictbox.cpp
new file mode 100644
index 00000000..2beed684
--- /dev/null
+++ b/kbabel/kbabeldict/kbabeldictbox.cpp
@@ -0,0 +1,1767 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2003-2005 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#include <dcopclient.h>
+#include <kaboutapplication.h>
+
+#include "aboutmoduledlg.h"
+#include "kbabeldictbox.h"
+#include <version.h>
+#include <resources.h>
+
+#include <kaboutdata.h>
+#include <kaboutdialog.h>
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kcmenumngr.h>
+#include <kdialogbase.h>
+#include <klibloader.h>
+#include <klistview.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kglobal.h>
+#include <kdebug.h>
+#include <ktrader.h>
+#include <kwin.h>
+
+#include <qclipboard.h>
+#include <qdir.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qpopupmenu.h>
+#include <qpushbutton.h>
+#include <qtextview.h>
+#include <qstylesheet.h>
+#include <qtoolbutton.h>
+#include <qwhatsthis.h>
+#include <qtimer.h>
+
+#define KBABELDICT 5321
+
+using namespace KBabel;
+
+class ResultListItem : public QListViewItem
+{
+public:
+ ResultListItem(QListView *parent, const SearchResult& result,bool richText);
+
+ virtual QString key(int column, bool ascending) const;
+ const SearchResult* result() const;
+ bool richText() const { return _richText; }
+
+private:
+ SearchResult _result;
+ bool _richText;
+};
+
+ResultListItem::ResultListItem(QListView *parent, const SearchResult& result
+ , bool richText)
+ : QListViewItem(parent)
+ , _result(result)
+ , _richText(richText)
+{
+ int score=_result.score;
+ if(score<0)
+ score=0;
+ else if(score>100)
+ score=100;
+ setText(0,QString::number(score));
+
+ QString tmp;
+ if(richText)
+ tmp=_result.plainFound;
+ else
+ // FIXME: what about plural forms?
+ tmp=result.found.first();
+
+ bool cutted=false;
+ int index=tmp.find('\n');
+ if(index > 0)
+ {
+ tmp=tmp.left(index);
+ cutted=true;
+ }
+ if(tmp.length() > 30)
+ {
+ tmp=tmp.left(30);
+ cutted=true;
+ }
+ tmp=tmp.stripWhiteSpace();
+ if(cutted)
+ tmp+="...";
+
+ setText(1,tmp);
+
+ if(richText)
+ tmp=_result.plainTranslation;
+ else
+ tmp=result.translation;
+
+ cutted=false;
+ index=tmp.find('\n');
+ if(index > 0)
+ {
+ tmp=tmp.left(index);
+ cutted=true;
+ }
+ if(tmp.length() > 30)
+ {
+ tmp=tmp.left(30);
+ cutted=true;
+ }
+ tmp=tmp.stripWhiteSpace();
+ if(cutted)
+ tmp+="...";
+ setText(2,tmp);
+
+
+ if(!_result.descriptions.isEmpty())
+ {
+ TranslationInfo *ti = _result.descriptions.first();
+ if(ti)
+ {
+ setText(3,ti->location);
+ }
+ }
+
+}
+
+QString ResultListItem::key(int column, bool ascending) const
+{
+ if(column==0)
+ {
+ QString result=QString::number(_result.score);
+ result=result.rightJustify(10,'0');
+
+ return result;
+ }
+
+ return QListViewItem::key(column,ascending);
+}
+
+const SearchResult *ResultListItem::result() const
+{
+ return &_result;
+}
+
+/*
+ * Constructs a KBabelDictBox which is a child of 'parent', with the
+ * name 'name' and widget flags set to 'f'
+ */
+KBabelDictBox::KBabelDictBox( QWidget* parent, const char* name, WFlags fl )
+ : DCOPObject("KBabelDict"), QWidget( parent, name, fl )
+{
+ active=-1;
+ currentResult=0;
+ currentInfo=0;
+ moduleList.setAutoDelete(false);
+
+
+ QVBoxLayout *mainLayout = new QVBoxLayout(this);
+ mainLayout->setMargin(KDialog::marginHint());
+ mainLayout->setSpacing(KDialog::spacingHint());
+
+ QGridLayout *grid = new QGridLayout(mainLayout);
+
+ QHBoxLayout *hbox = new QHBoxLayout;
+ QLabel *label = new QLabel(i18n("Total:"),this);
+ hbox->addWidget(label);
+ totalResultsLabel = new QLabel("0",this);
+ hbox->addWidget(totalResultsLabel);
+ grid->addLayout(hbox,0,0);
+
+ hbox = new QHBoxLayout;
+ label = new QLabel(i18n("Current:"), this);
+ hbox->addWidget(label);
+ currentLabel = new QLabel("0",this);
+ hbox->addWidget(currentLabel);
+ grid->addLayout(hbox,1,0);
+
+
+ hbox = new QHBoxLayout;
+ label = new QLabel(i18n("Found in:"), this);
+ hbox->addWidget(label);
+ locationLabel = new QLabel(this);
+ hbox->addWidget(locationLabel);
+ hbox->setStretchFactor(locationLabel,2);
+ grid->addLayout(hbox,0,1);
+
+ hbox = new QHBoxLayout;
+ label = new QLabel(i18n("Translator:"), this);
+ hbox->addWidget(label);
+ translatorLabel = new QLabel(this);
+ translatorLabel->setMinimumSize(50,0);
+ hbox->addWidget(translatorLabel);
+ hbox->setStretchFactor(translatorLabel,2);
+ grid->addLayout(hbox,1,1);
+
+ grid->setColStretch(1,2);
+
+
+ hbox = new QHBoxLayout;
+ label = new QLabel(i18n("Date:"),this);
+ hbox->addWidget(label);
+ dateLabel = new QLabel(this);
+ dateLabel->setMinimumSize(50,0);
+ hbox->addWidget(dateLabel);
+ hbox->setStretchFactor(dateLabel,2);
+
+ moreButton = new QPushButton(this,"moreButton");
+ moreButton->setText(i18n("&More"));
+ moreButton->setEnabled(false);
+ moreButton->setAutoRepeat(true);
+ hbox->addWidget(moreButton);
+
+ mainLayout->addLayout(hbox);
+
+
+ hbox = new QHBoxLayout;
+ hbox->addStretch(1);
+ listButton = new QToolButton(Qt::UpArrow,this);
+ listButton->setFixedSize(20,15);
+ listButton->setAutoRepeat(false);
+ connect(listButton,SIGNAL(clicked()),this,SLOT(showListOnly()));
+ hbox->addWidget(listButton);
+ detailButton = new QToolButton(Qt::DownArrow,this);
+ detailButton->setFixedSize(20,15);
+ detailButton->setAutoRepeat(false);
+ connect(detailButton,SIGNAL(clicked()),this,SLOT(showDetailsOnly()));
+ hbox->addWidget(detailButton);
+
+ mainLayout->addLayout(hbox);
+
+
+ resultSplitter = new QSplitter(Qt::Vertical,this
+ ,"resultsplitter");
+ mainLayout->addWidget(resultSplitter);
+
+ viewContainer = new QSplitter(Qt::Vertical,resultSplitter, "singleEntrySplitter");
+ QVBoxLayout *vbox = new QVBoxLayout(viewContainer);
+ vbox->setResizeMode(QLayout::FreeResize);
+ origView = new QTextView(viewContainer,"origView");
+ origView->setWordWrap( QTextEdit::WidgetWidth );
+ origView->setMinimumSize(1,1);
+ vbox->addWidget(origView);
+ translationView = new QTextView(viewContainer,"translationView");
+ origView->setWordWrap( QTextEdit::WidgetWidth );
+ translationView->setMinimumSize(1,1);
+ vbox->addWidget(translationView);
+ viewContainer->setMinimumSize(1,1);
+
+ resultListView = new KListView( resultSplitter, "resultListView" );
+ resultListView->setMinimumSize(1,1);
+ resultListView->addColumn( i18n( "Score" ) );
+ resultListView->addColumn( i18n( "Original" ) );
+ resultListView->addColumn( i18n( "Translation" ) );
+ resultListView->addColumn( i18n( "Location" ) );
+
+ resultListView->installEventFilter(this);
+ connect(resultListView
+ , SIGNAL(doubleClicked(QListViewItem *,const QPoint&,int))
+ , this, SLOT(editFile()));
+ connect(resultListView, SIGNAL(returnPressed(QListViewItem *))
+ , this, SLOT(editFile()));
+ connect(resultListView
+ , SIGNAL(contextMenu(KListView *,QListViewItem *,const QPoint&))
+ , this
+ , SLOT(showContextMenu(KListView *,QListViewItem *,const QPoint&)));
+
+ resultSplitter->setResizeMode(viewContainer,QSplitter::KeepSize);
+ QValueList<int> sizes;
+ sizes.append(50);
+ sizes.append(50);
+ resultSplitter->setSizes(sizes);
+
+
+ hbox = new QHBoxLayout;
+ hbox->addStretch(1);
+
+ prevButton = new QPushButton(i18n("< &Previous"),this);
+ prevButton->setEnabled(false);
+ prevButton->setAutoRepeat(true);
+ hbox->addWidget(prevButton);
+
+ nextButton = new QPushButton(i18n("&Next >"),this);
+ nextButton->setEnabled(false);
+ nextButton->setAutoRepeat(true);
+ hbox->addWidget(nextButton);
+
+ hbox->addStretch(1);
+ mainLayout->addLayout(hbox);
+
+ totalResultsLabel->setNum(100000);
+ totalResultsLabel->setFixedSize(totalResultsLabel->sizeHint());
+ totalResultsLabel->setNum(0);
+ currentLabel->setNum(100000);
+ currentLabel->setFixedSize(currentLabel->sizeHint());
+ currentLabel->setNum(0);
+
+ setRMBMenu(new QPopupMenu(this));
+ QStringList fileList;
+#if 0
+ // try to find installed modules by looking into directories
+ // kbabeldict/modules and getting all files *.rc
+ QStringList dirList = KGlobal::dirs()->findDirs("data"
+ ,"kbabeldict/modules");
+
+ for ( QStringList::Iterator it = dirList.begin(); it != dirList.end()
+ ; ++it )
+ {
+ QDir dir((*it),"*.rc");
+ QStringList list = dir.entryList(QDir::Files|QDir::Readable);
+
+ for ( QStringList::Iterator fit = list.begin(); fit != list.end()
+ ; ++fit )
+ {
+ if(!fileList.contains((*fit)))
+ {
+ fileList.append((*fit));
+ }
+ }
+ }
+#endif
+
+ // use locate to locate the actual file, because rcfiles in the users
+ // directory is prefered for systemwide rc files
+ QStringList rcList;
+ for( QStringList::Iterator fit = fileList.begin(); fit != fileList.end();
+ ++fit)
+ {
+ rcList.append(locate("data","kbabeldict/modules/"+(*fit)));
+ }
+
+ for( QStringList::Iterator rit = rcList.begin(); rit != rcList.end();
+ ++rit)
+ {
+ KConfig rcConfig((*rit),true,false);
+
+ rcConfig.setGroup("SearchEngine");
+
+ QStringList appList = rcConfig.readListEntry("Applications");
+ KInstance *inst = KGlobal::instance();
+ if(inst && !appList.isEmpty() && !appList.contains(inst->instanceName()))
+ {
+ continue;
+ }
+
+ QString libName = rcConfig.readEntry("Lib");
+
+ if(!libName.isNull())
+ {
+ kdDebug(KBABELDICT) << "loading library " << libName << endl;
+
+ KLibFactory *factory=KLibLoader::self()->factory(libName.latin1());
+
+ if(factory)
+ {
+ SearchEngine *e = (SearchEngine *)factory->create(this
+ , "searchengine", "SearchEngine");
+ if(!e)
+ {
+ kdError() << "searchengine not initialized" << endl;
+ }
+ else
+ {
+ registerModule(e);
+ }
+ }
+ else
+ {
+ kdError() << "wasn't able to load library" << endl;
+ }
+
+ }
+ }
+
+ kdDebug(KBABEL_SEARCH) << "Now using trader for " << KGlobal::instance()->instanceName() << endl;
+
+ // try to find installed modules by KTrader
+ KTrader::OfferList offers = KTrader::self()->query("KBabelDictModule",
+ "('"+KGlobal::instance()->instanceName()+"' in [Applications])");
+
+ for(KTrader::OfferList::ConstIterator it = offers.begin(); it != offers.end(); ++it )
+ {
+ KLibFactory *factory = KLibLoader::self()->factory( (*it)->library().local8Bit() );
+
+ if(factory)
+ {
+ SearchEngine *e = (SearchEngine *)factory->create(this
+ , "searchengine", "SearchEngine");
+ if(!e)
+ {
+ kdError() << "searchengine not initialized" << endl;
+ }
+ else
+ {
+ registerModule(e);
+ }
+ }
+ else
+ {
+ kdError() << "wasn't able to load library" << endl;
+ }
+ }
+
+ kdDebug(KBABEL_SEARCH) << "Now for any application" << endl;
+
+ offers = KTrader::self()->query("KBabelDictModule",
+ "not ( exist Applications)");
+
+ for(KTrader::OfferList::ConstIterator it = offers.begin(); it != offers.end(); ++it )
+ {
+ KLibFactory *factory = KLibLoader::self()->factory( (*it)->library().local8Bit() );
+
+ if(factory)
+ {
+ SearchEngine *e = (SearchEngine *)factory->create(this
+ , "searchengine", "SearchEngine");
+ if(!e)
+ {
+ kdError() << "searchengine not initialized" << endl;
+ }
+ else
+ {
+ registerModule(e);
+ }
+ }
+ else
+ {
+ kdError() << "wasn't able to load library" << endl;
+ }
+ }
+
+ connect(nextButton,SIGNAL(clicked()),this,SLOT(slotNextResult()));
+ connect(prevButton,SIGNAL(clicked()),this,SLOT(slotPrevResult()));
+ connect(moreButton,SIGNAL(clicked()),this,SLOT(nextInfo()));
+
+
+ origView->installEventFilter(this);
+ translationView->installEventFilter(this);
+
+ resultListView->setSorting(0,false);
+ resultListView->setAllColumnsShowFocus(true);
+
+ connect(resultListView,SIGNAL(selectionChanged(QListViewItem*))
+ , this, SLOT(showResult(QListViewItem*)));
+}
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+KBabelDictBox::~KBabelDictBox()
+{
+}
+
+void KBabelDictBox::registerModule( SearchEngine* e )
+{
+ active = 0;
+ moduleList.append(e);
+ connect(e, SIGNAL(started()),this,SIGNAL(searchStarted()));
+ connect(e, SIGNAL(finished()),this,SIGNAL(searchStopped()));
+ connect(e, SIGNAL(finished()),this
+ ,SLOT(clearModuleResults()));
+ connect(e, SIGNAL(progress(int)),this,SIGNAL(progressed(int)));
+ connect(e, SIGNAL(progressStarts(const QString&)),this
+ , SIGNAL(progressStarts(const QString&)));
+ connect(e, SIGNAL(progressEnds()),this,SIGNAL(progressEnds()));
+ connect(e, SIGNAL(resultFound(const SearchResult*)), this
+ , SLOT(addResult(const SearchResult*)));
+ connect(e, SIGNAL(hasError(const QString&)), this
+ , SIGNAL(errorInModule(const QString&)));
+}
+
+void KBabelDictBox::saveSettings(KConfigBase *config)
+{
+ KConfigGroupSaver cs(config,"KBabelDict");
+
+ config->writeEntry("ResultSplitter",resultSplitter->sizes());
+
+ SearchEngine *e;
+
+ e = moduleList.at(active);
+ if(e)
+ {
+ config->writeEntry("ActiveModule",e->id());
+ }
+
+ for(e = moduleList.first(); e != 0; e = moduleList.next())
+ {
+ config->setGroup(e->id());
+ e->saveSettings(config);
+ }
+
+
+}
+
+void KBabelDictBox::saveSettings(const QString& moduleId, KConfigBase *config)
+{
+ SearchEngine *e;
+
+ for(e = moduleList.first(); e != 0; e = moduleList.next())
+ {
+ if(e->id() == moduleId)
+ {
+ e->saveSettings(config);
+ break;
+ }
+ }
+}
+
+void KBabelDictBox::readSettings(KConfigBase *config)
+{
+ SearchEngine *e;
+ KConfigGroupSaver cs(config,"KBabelDict");
+ QValueList<int> sizes=config->readIntListEntry("ResultSplitter");
+ if(!sizes.isEmpty())
+ resultSplitter->setSizes(sizes);
+
+ QString m = config->readEntry("ActiveModule");
+ if(!m.isEmpty())
+ {
+ setActiveModule(m);
+ }
+
+ for(e = moduleList.first(); e != 0; e = moduleList.next())
+ {
+ config->setGroup(e->id());
+ e->readSettings(config);
+ }
+}
+
+void KBabelDictBox::readSettings(const QString& moduleId, KConfigBase *config)
+{
+ SearchEngine *e;
+
+ for(e = moduleList.first(); e != 0; e = moduleList.next())
+ {
+ if(e->id() == moduleId)
+ {
+ e->readSettings(config);
+ break;
+ }
+ }
+}
+
+void KBabelDictBox::setAutoUpdateOptions(bool on)
+{
+ SearchEngine *e;
+
+ for(e = moduleList.first(); e != 0; e = moduleList.next())
+ {
+ e->setAutoUpdateOptions(on);
+ }
+}
+
+
+int KBabelDictBox::activeModule()
+{
+ return active;
+}
+
+/*
+ * public slot
+ */
+void KBabelDictBox::setActiveModule(int a)
+{
+ if( a == active)
+ return;
+
+ if( a < (int)moduleList.count())
+ {
+ SearchEngine *engine = moduleList.at(active);
+
+ if(!engine)
+ {
+ kdDebug(KBABELDICT) << "no module available" << endl;
+ }
+ else if(engine->isSearching())
+ {
+ engine->stopSearch();
+ engine->clearResults();
+ }
+
+ engine = moduleList.at(a);
+ if(engine)
+ {
+ active = a;
+ emit activeModuleChanged(active);
+ emit activeModuleChanged(engine->isEditable());
+ }
+
+
+ }
+}
+
+void KBabelDictBox::setActiveModule(QString id)
+{
+ SearchEngine *e;
+
+ int i=0;
+
+ for(e = moduleList.first(); e != 0; e = moduleList.next())
+ {
+ if(e->id() == id)
+ {
+ setActiveModule(i);
+ break;
+ }
+
+ i++;
+ }
+}
+
+/*
+ * public slot
+ */
+void KBabelDictBox::startSearch(const QString text)
+{
+ clear();
+ SearchEngine *engine = moduleList.at(active);
+
+ if(!engine)
+ {
+ kdDebug(KBABELDICT) << "no module available" << endl;
+ }
+ else
+ {
+ if(engine->isSearching())
+ {
+ engine->stopSearch();
+ connect(this, SIGNAL(searchStopped()), this
+ , SLOT(startDelayedSearch()));
+
+ searchText=text;
+ }
+ else engine->startSearch(text);
+ }
+}
+
+/*
+ * public slot
+ */
+void KBabelDictBox::startTranslationSearch(const QString text)
+{
+ clear();
+ SearchEngine *engine = moduleList.at(active);
+
+ if(!engine)
+ {
+ kdDebug(KBABELDICT) << "no module available" << endl;
+ }
+ else
+ {
+ if(engine->isSearching())
+ {
+ engine->stopSearch();
+ connect(this, SIGNAL(searchStopped()), this
+ , SLOT(startDelayedTranslationSearch()));
+
+ searchText=text;
+ }
+ else engine->startSearchInTranslation(text);
+ }
+}
+
+void KBabelDictBox::startDelayedSearch(const QString text)
+{
+ clear();
+ SearchEngine *engine = moduleList.at(active);
+
+ if(!engine)
+ {
+ kdDebug(KBABELDICT) << "no module available" << endl;
+ }
+ else
+ {
+ searchText=text;
+
+ if(engine->isSearching())
+ {
+ engine->stopSearch();
+
+ connect(this, SIGNAL(searchStopped()), this
+ , SLOT(startDelayedSearch()));
+
+ }
+ else
+ {
+ QTimer::singleShot(5,this,SLOT(startDelayedSearch()));
+ }
+ }
+}
+
+void KBabelDictBox::startDelayedTranslationSearch(const QString text)
+{
+ clear();
+ SearchEngine *engine = moduleList.at(active);
+
+ if(!engine)
+ {
+ kdDebug(KBABELDICT) << "no module available" << endl;
+ }
+ else
+ {
+ searchText=text;
+
+ if(engine->isSearching())
+ {
+ engine->stopSearch();
+
+ connect(this, SIGNAL(searchStopped()), this
+ , SLOT(startDelayedTranslationSearch()));
+
+ }
+ else
+ {
+ QTimer::singleShot(5,this,SLOT(startDelayedTranslationSearch()));
+ }
+ }
+}
+
+QString KBabelDictBox::translate(const QString text)
+{
+ SearchEngine *engine = moduleList.at(active);
+
+ if(!engine)
+ {
+ kdDebug(KBABELDICT) << "no module available" << endl;
+ return QString::null;
+ }
+ else
+ {
+ if(engine->isSearching())
+ {
+ engine->stopSearch();
+ }
+
+ return engine->translate(text);
+ }
+}
+
+QString KBabelDictBox::fuzzyTranslation(const QString text, int &score)
+{
+ SearchEngine *engine = moduleList.at(active);
+
+ if(!engine)
+ {
+ kdDebug(KBABELDICT) << "no module available" << endl;
+ return QString::null;
+ }
+ else
+ {
+ if(engine->isSearching())
+ {
+ engine->stopSearch();
+ }
+
+ return engine->fuzzyTranslation(text, score);
+ }
+}
+
+QString KBabelDictBox::searchTranslation(const QString text, int &score)
+{
+ SearchEngine *engine = moduleList.at(active);
+
+ if(!engine)
+ {
+ kdDebug(KBABELDICT) << "no module available" << endl;
+ return QString::null;
+ }
+ else
+ {
+ if(engine->isSearching())
+ {
+ engine->stopSearch();
+ }
+
+ return engine->searchTranslation(text, score);
+ }
+}
+
+void KBabelDictBox::startDelayedSearch()
+{
+ clear();
+
+ SearchEngine *engine = moduleList.at(active);
+
+ if(!engine)
+ {
+ kdDebug(KBABELDICT) << "no module available" << endl;
+ }
+ else
+ {
+ disconnect(this, SIGNAL(searchStopped()), this
+ , SLOT(startDelayedSearch()));
+
+
+ engine->startSearch(searchText);
+ }
+}
+
+void KBabelDictBox::startDelayedTranslationSearch()
+{
+ clear();
+
+ SearchEngine *engine = moduleList.at(active);
+
+ if(!engine)
+ {
+ kdDebug(KBABELDICT) << "no module available" << endl;
+ }
+ else
+ {
+ disconnect(this, SIGNAL(searchStopped()), this
+ , SLOT(startDelayedTranslationSearch()));
+
+
+ engine->startSearchInTranslation(searchText);
+ }
+}
+
+/*
+ * public slot
+ */
+void KBabelDictBox::stopSearch()
+{
+ SearchEngine *engine = moduleList.at(active);
+
+ if(!engine)
+ {
+ kdDebug(KBABELDICT) << "no module available" << endl;
+ }
+ else
+ {
+ engine->stopSearch();
+ }
+
+}
+
+bool KBabelDictBox::isSearching()
+{
+ SearchEngine *engine = moduleList.at(active);
+
+ if(!engine)
+ {
+ kdDebug(KBABELDICT) << "no module available" << endl;
+ return false;
+ }
+
+ return engine->isSearching();
+}
+
+
+QStringList KBabelDictBox::moduleNames()
+{
+ QStringList list;
+ SearchEngine *e;
+
+ for(e = moduleList.first(); e != 0; e = moduleList.next())
+ {
+ list.append(e->name());
+ }
+
+ return list;
+}
+
+QStringList KBabelDictBox::modules()
+{
+ QStringList list;
+ SearchEngine *e;
+
+ for(e = moduleList.first(); e != 0; e = moduleList.next())
+ {
+ list.append(e->id());
+ }
+
+ return list;
+}
+
+QPtrList<ModuleInfo> KBabelDictBox::moduleInfos()
+{
+ QPtrList<ModuleInfo> list;
+ SearchEngine *e;
+
+ for(e = moduleList.first(); e != 0; e = moduleList.next())
+ {
+ ModuleInfo *info = new ModuleInfo;
+ info->id=e->id();
+ info->name=e->name();
+ info->editable=e->isEditable();
+
+ list.append(info);
+ }
+
+ return list;
+}
+
+
+QPtrList<PrefWidget> KBabelDictBox::modPrefWidgets(QWidget *parent)
+{
+ QPtrList<PrefWidget> list;
+ list.setAutoDelete(false);
+ SearchEngine *e;
+
+ for(e = moduleList.first(); e != 0; e = moduleList.next())
+ {
+ list.append(e->preferencesWidget(parent));
+ }
+
+ return list;
+
+}
+
+
+void KBabelDictBox::showResult(QListViewItem *item)
+{
+ ResultListItem *resultItem = static_cast<ResultListItem*>(item);
+
+ if(!item)
+ {
+ kdError(KBABELDICT) << "no item" << endl;
+ if(rmbPopup)
+ {
+ rmbPopup->changeItem(editFileIndex, i18n("Edit File"));
+ rmbPopup->setItemEnabled(editFileIndex,false);
+ }
+ }
+ else
+ {
+ const SearchResult *result= resultItem->result();
+ if(!result)
+ return;
+
+ resultListView->ensureItemVisible(item);
+
+ currentResult = resultListView->itemIndex(item);
+ currentInfo = 0;
+
+ bool richText=resultItem->richText();
+ if(richText)
+ {
+ // FIXME: what about plural forms?
+ origView->setText(result->found.first());
+ translationView->setText(result->translation);
+ }
+ else
+ {
+ // FIXME: what about plural forms?
+ origView->setText(QStyleSheet::convertFromPlainText(result->found.first()));
+ translationView->setText(
+ QStyleSheet::convertFromPlainText(result->translation));
+ }
+
+ if(result->descriptions.count() > 0)
+ {
+ QPtrListIterator<TranslationInfo> it(result->descriptions);
+ TranslationInfo *info=it.current();
+ if(info)
+ {
+ if(info->lastChange.isValid())
+ {
+ dateLabel->setText(KGlobal::locale()->formatDate(
+ info->lastChange.date(),true));
+ }
+ else
+ {
+ dateLabel->setText("");
+ }
+ locationLabel->setText(info->location);
+ translatorLabel->setText(info->translator);
+
+ if(rmbPopup)
+ {
+ if(!info->filePath.isEmpty())
+ {
+ rmbPopup->changeItem(editFileIndex
+ ,i18n("Edit File %1").arg(info->location));
+ rmbPopup->setItemEnabled(editFileIndex,true);
+ }
+ else
+ {
+ rmbPopup->changeItem(editFileIndex, i18n("Edit File"));
+ rmbPopup->setItemEnabled(editFileIndex,false);
+ }
+ }
+ }
+ }
+ else
+ {
+ dateLabel->setText("");
+ locationLabel->setText("");
+ translatorLabel->setText("");
+
+ rmbPopup->changeItem(editFileIndex, i18n("Edit File"));
+ rmbPopup->setItemEnabled(editFileIndex,false);
+ }
+
+ moreButton->setEnabled((result->descriptions.count() > 1));
+
+ currentLabel->setText(QString::number(currentResult+1));
+
+ prevButton->setEnabled(currentResult > 0);
+ nextButton->setEnabled(currentResult+1 < total);
+ }
+
+}
+
+void KBabelDictBox::nextResult()
+{
+ QListViewItem *item=resultListView->selectedItem();
+ if(item)
+ {
+ item=item->itemBelow();
+ if(item)
+ {
+ resultListView->setSelected(item,true);
+ }
+ }
+}
+
+
+void KBabelDictBox::prevResult()
+{
+ QListViewItem *item=resultListView->selectedItem();
+ if(item)
+ {
+ item=item->itemAbove();
+ if(item)
+ {
+ resultListView->setSelected(item,true);
+ }
+ }
+
+}
+
+void KBabelDictBox::addResult(const SearchResult* result)
+{
+ SearchEngine *e;
+
+ e = moduleList.at(active);
+ if(!e)
+ {
+ kdError(KBABELDICT) << "no module available" << endl;
+ return;
+ }
+
+ QListViewItem *item=resultListView->selectedItem();
+ int index=0;
+ if(item)
+ {
+ index=resultListView->itemIndex(item);
+ }
+
+ new ResultListItem(resultListView, *result,e->usesRichTextResults());
+ total++;
+ totalResultsLabel->setText(QString::number(total));
+
+ if(total==1)
+ {
+ resultListView->setSelected(resultListView->firstChild(),true);
+ }
+ else
+ {
+ nextButton->setEnabled((currentResult+1) < total);
+ item=resultListView->itemAtIndex(index);
+ if(item)
+ {
+ resultListView->setSelected(item,true);
+ }
+ }
+}
+
+void KBabelDictBox::clear()
+{
+ dateLabel->setText("");
+ locationLabel->setText("");
+ translatorLabel->setText("");
+ currentLabel->setText(QString::number(0));
+ totalResultsLabel->setText(QString::number(0));
+ origView->setText("");
+ translationView->setText("");
+ currentResult=0;
+ currentInfo=0;
+ total=0;
+
+ resultListView->clear();
+ clearModuleResults();
+
+ moreButton->setEnabled(false);
+ prevButton->setEnabled(false);
+ nextButton->setEnabled(false);
+
+ if(rmbPopup)
+ {
+ rmbPopup->changeItem(editFileIndex,i18n("Edit File"));
+ rmbPopup->setItemEnabled(editFileIndex,false);
+ }
+}
+
+void KBabelDictBox::nextInfo()
+{
+ ResultListItem *item = static_cast<ResultListItem*>(resultListView->selectedItem());
+
+ if(!item)
+ {
+ kdDebug(KBABELDICT) << "no item available" << endl;
+ }
+ else
+ {
+ const SearchResult *result = item->result();
+ if(!result)
+ return;
+
+ if(result->descriptions.count() > 0)
+ {
+ currentInfo++;
+ TranslationInfo *info;
+ if(currentInfo == (int)result->descriptions.count())
+ {
+ QPtrListIterator<TranslationInfo> it(result->descriptions);
+ info = it.current();
+ currentInfo = 0;
+ }
+ else
+ {
+ QPtrListIterator<TranslationInfo> it(result->descriptions);
+ for(int i=0; i < currentInfo; i++)
+ {
+ ++it;
+ }
+ info=*it;
+ }
+
+ if(info->lastChange.isValid())
+ {
+ dateLabel->setText(KGlobal::locale()->formatDate(
+ info->lastChange.date(),true));
+ }
+ else
+ {
+ dateLabel->setText("");
+ }
+
+ locationLabel->setText(info->location);
+ translatorLabel->setText(info->translator);
+
+ if(rmbPopup)
+ {
+ if(!info->filePath.isEmpty())
+ {
+ rmbPopup->changeItem(editFileIndex
+ ,i18n("Edit File %1").arg(info->location));
+ rmbPopup->setItemEnabled(editFileIndex,true);
+ }
+ else
+ {
+ rmbPopup->changeItem(editFileIndex, i18n("Edit File"));
+ rmbPopup->setItemEnabled(editFileIndex,false);
+ }
+ }
+ }
+ }
+
+}
+
+void KBabelDictBox::showListOnly()
+{
+ int h=resultSplitter->height();
+ QValueList<int> sizes;
+ sizes.append(1);
+ sizes.append(h-1);
+ resultSplitter->setSizes(sizes);
+}
+
+void KBabelDictBox::showDetailsOnly()
+{
+ int h=resultSplitter->height();
+ QValueList<int> sizes;
+ sizes.append(h-1);
+ sizes.append(h);
+ resultSplitter->setSizes(sizes);
+}
+
+void KBabelDictBox::clearModuleResults()
+{
+ SearchEngine *engine = moduleList.at(active);
+ if(engine)
+ engine->clearResults();
+}
+
+void KBabelDictBox::about()
+{
+ KAboutApplication *aboutDlg = new KAboutApplication(this);
+
+ SearchEngine *e;
+ for(e = moduleList.first(); e != 0; e = moduleList.next())
+ {
+ KAboutContainer *page = aboutDlg->addScrolledContainerPage(e->name());
+
+ const KAboutData *aboutData = e->about();
+ if(aboutData)
+ {
+
+ QString text = aboutData->programName() + " " +
+ aboutData->version() + "\n";
+
+ text += "\n"+aboutData->shortDescription()+"\n";
+
+ if(!aboutData->homepage().isEmpty())
+ {
+ text += "\n" + aboutData->homepage() + "\n";
+ }
+ if(!aboutData->otherText().isEmpty())
+ {
+ text += "\n" + aboutData->otherText() + "\n";
+ }
+ if(!aboutData->copyrightStatement().isEmpty())
+ {
+ text += "\n" + aboutData->copyrightStatement() + "\n";
+ }
+
+ if(aboutData->bugAddress() != "submit@bugs.kde.org")
+ {
+ text += "\n" + i18n("Send bugs to %1")
+ .arg(aboutData->bugAddress()) +"\n";
+ }
+
+ QLabel *label = new QLabel(text,0);
+ page->addWidget(label);
+
+ int authorCount = aboutData->authors().count();
+ if(authorCount)
+ {
+ if(authorCount==1)
+ text=i18n("Author:");
+ else
+ text=i18n("Authors:");
+
+ label = new QLabel(text,0);
+ page->addWidget(label);
+
+ QValueList<KAboutPerson>::ConstIterator it;
+ for(it = aboutData->authors().begin();
+ it != aboutData->authors().end(); ++it)
+ {
+ page->addPerson( (*it).name(), (*it).emailAddress(),
+ (*it).webAddress(), (*it).task() );
+ }
+ }
+ int creditsCount = aboutData->credits().count();
+ if(creditsCount)
+ {
+ text = i18n("Thanks to:");
+ label = new QLabel(text,0);
+ page->addWidget(label);
+
+ QValueList<KAboutPerson>::ConstIterator it;
+ for(it = aboutData->credits().begin();
+ it != aboutData->credits().end(); ++it)
+ {
+ page->addPerson( (*it).name(), (*it).emailAddress(),
+ (*it).webAddress(), (*it).task() );
+ }
+
+ }
+ }
+ else
+ {
+ QString text = i18n("No information available.");
+ QLabel *label = new QLabel(text,0);
+ page->addWidget(label);
+ }
+
+ }
+
+ aboutDlg->setInitialSize(QSize(400,1));
+ aboutDlg->exec();
+
+ delete aboutDlg;
+}
+
+void KBabelDictBox::aboutActiveModule()
+{
+ SearchEngine *engine = moduleList.at(active);
+ if(!engine)
+ return;
+
+ aboutModule(engine->id());
+}
+
+void KBabelDictBox::aboutModule(const QString& id)
+{
+ SearchEngine *e;
+
+ for(e = moduleList.first(); e != 0; e = moduleList.next())
+ {
+ if(e->id() == id)
+ {
+ break;
+ }
+ }
+
+ if(!e)
+ return;
+
+ AboutModuleDlg *aboutDlg = new AboutModuleDlg(e->about(),this);
+ aboutDlg->exec();
+
+ delete aboutDlg;
+
+}
+
+
+void KBabelDictBox::slotNextResult()
+{
+ nextResult();
+}
+
+void KBabelDictBox::slotPrevResult()
+{
+ prevResult();
+}
+
+
+void KBabelDictBox::slotStopSearch()
+{
+ stopSearch();
+}
+
+void KBabelDictBox::slotStartSearch(const QString& text)
+{
+ startSearch(text);
+}
+
+void KBabelDictBox::setEditedPackage(const QString& name)
+{
+ SearchEngine *e;
+
+ for(e = moduleList.first(); e != 0; e = moduleList.next())
+ {
+ e->setEditedPackage(name);
+ }
+}
+
+
+void KBabelDictBox::setEditedFile(const QString& path)
+{
+ SearchEngine *e;
+
+ for(e = moduleList.first(); e != 0; e = moduleList.next())
+ {
+ e->setEditedFile(path);
+ }
+}
+
+void KBabelDictBox::setLanguage(const QString& languageCode,
+ const QString& languageName)
+{
+ SearchEngine *e;
+
+ for(e = moduleList.first(); e != 0; e = moduleList.next())
+ {
+ e->setLanguage(languageCode,languageName);
+ e->setLanguageCode(languageCode);
+ }
+}
+
+void KBabelDictBox::copy()
+{
+ if(origView->hasSelectedText())
+ {
+ origView->copy();
+ }
+ else if(translationView->hasSelectedText())
+ {
+ translationView->copy();
+ }
+ else
+ {
+ QClipboard *cb = KApplication::clipboard();
+ cb->setText(translation());
+ }
+}
+
+QString KBabelDictBox::translation()
+{
+ QString trans;
+
+ QListViewItem *item=resultListView->selectedItem();
+ if(item)
+ {
+ ResultListItem *r=static_cast<ResultListItem*>(item);
+ if(r)
+ {
+ const SearchResult *sr=r->result();
+ if(sr)
+ {
+ if(r->richText())
+ trans=sr->plainTranslation;
+ else
+ trans=sr->translation;
+ }
+ }
+ }
+
+ return trans;
+}
+
+void KBabelDictBox::setRMBMenu(QPopupMenu *popup)
+{
+ if(popup)
+ {
+ if(popup->count() > 0)
+ popup->insertSeparator();
+
+ editFileIndex = popup->insertItem(i18n("Edit File")
+ , this, SLOT(editFile()));
+ popup->setItemEnabled(editFileIndex,false);
+
+ KContextMenuManager::insert(origView,popup);
+ KContextMenuManager::insert(origView->viewport(),popup);
+ KContextMenuManager::insert(translationView,popup);
+ KContextMenuManager::insert(translationView->viewport(),popup);
+ KContextMenuManager::insert(this,popup);
+ //KContextMenuManager::insert(resultListView->viewport(),popup);
+
+ rmbPopup = popup;
+ }
+}
+
+bool KBabelDictBox::hasSelectedText() const
+{
+ bool have=false;
+ if(origView->hasSelectedText())
+ have=true;
+ else if(translationView->hasSelectedText())
+ have=true;
+ else if(resultListView->selectedItem() )
+ have=true;
+
+ return have;
+}
+
+QString KBabelDictBox::selectedText() const
+{
+ QString text;
+ if(origView->hasSelectedText())
+ text=origView->selectedText();
+ else if(translationView->hasSelectedText())
+ translationView->selectedText();
+
+ return text;
+}
+
+
+
+void KBabelDictBox::configure(const QString& id, bool modal)
+{
+
+ QWidget* w = prefDialogs[id];
+ if(w)
+ {
+ KWin::setActiveWindow(w->winId());
+ return;
+ }
+
+ SearchEngine *e;
+ for(e = moduleList.first(); e != 0; e = moduleList.next())
+ {
+ if(e->id() == id)
+ {
+ QString caption = i18n("Configure Dictionary %1").arg(e->name());
+ KDialogBase *dialog = new KDialogBase(this,"prefDialog"
+ , modal, caption
+ , KDialogBase::Ok|KDialogBase::Apply|KDialogBase::Cancel|
+ KDialogBase::Default);
+
+ QWhatsThis::add(dialog,"");
+
+ PrefWidget *prefWidget = e->preferencesWidget(dialog);
+ dialog->setMainWidget(prefWidget);
+
+ connect(dialog, SIGNAL(okClicked()),prefWidget,SLOT(apply()));
+ connect(dialog, SIGNAL(applyClicked()),prefWidget,SLOT(apply()));
+ connect(dialog, SIGNAL(defaultClicked()),prefWidget,SLOT(standard()));
+ connect(dialog, SIGNAL(cancelClicked()),prefWidget,SLOT(cancel()));
+
+ connect(dialog, SIGNAL(finished()),this,SLOT(destroyConfigDialog()));
+
+ prefDialogs.insert(id,dialog);
+
+ if( modal ) dialog->exec();
+ else dialog->show();
+
+ break;
+ }
+ }
+
+}
+
+
+void KBabelDictBox::destroyConfigDialog()
+{
+ const QObject *obj = sender();
+ if(obj && obj->inherits("KDialogBase"))
+ {
+ KDialogBase *dialog = (KDialogBase*)obj;
+ if(dialog)
+ {
+ dialog->delayedDestruct();
+
+ QDictIterator<QWidget> it(prefDialogs);
+ while(it.current() != dialog)
+ {
+ ++it;
+ }
+
+ prefDialogs.remove(it.currentKey());
+ }
+ }
+}
+
+void KBabelDictBox::edit(const QString& id)
+{
+ SearchEngine *e;
+
+ for(e = moduleList.first(); e != 0; e = moduleList.next())
+ {
+ if(e->id() == id)
+ {
+ if(e->isEditable())
+ e->edit();
+
+ break;
+ }
+ }
+}
+
+void KBabelDictBox::edit()
+{
+ SearchEngine *engine = moduleList.at(active);
+ if(!engine)
+ return;
+
+ if(engine->isEditable())
+ engine->edit();
+}
+
+void KBabelDictBox::setTextChanged(const QStringList& orig,
+ const QString& translation, uint pluralForm, const QString& description)
+{
+ SearchEngine *e;
+
+ for(e = moduleList.first(); e != 0; e = moduleList.next())
+ {
+ e->stringChanged(orig,translation,pluralForm,description);
+ }
+}
+
+
+void KBabelDictBox::wheelEvent(QWheelEvent *we)
+{
+ if(we->delta() > 0)
+ {
+ prevResult();
+ }
+ else
+ {
+ nextResult();
+ }
+
+ we->accept();
+}
+
+bool KBabelDictBox::eventFilter(QObject *o, QEvent *e)
+{
+ if(e->type() == QEvent::Wheel)
+ {
+ QWheelEvent *we = static_cast<QWheelEvent*>(e);
+ if(we)
+ {
+ wheelEvent(we);
+ return true;
+ }
+ }
+ else if(e->type() == QEvent::Resize && o == resultListView)
+ {
+ if(resultListView->height() < 2)
+ {
+ detailButton->setEnabled(false);
+ listButton->setEnabled(true);
+ }
+ else if(resultListView->height() > resultSplitter->height()-10)
+ {
+ detailButton->setEnabled(true);
+ listButton->setEnabled(false);
+ }
+ else
+ {
+ detailButton->setEnabled(true);
+ listButton->setEnabled(true);
+ }
+ }
+
+ return false;
+}
+
+void KBabelDictBox::editFile()
+{
+ ResultListItem *item = static_cast<ResultListItem*>(resultListView->currentItem());
+
+ if(!item)
+ {
+ kdDebug(KBABELDICT) << "no item available" << endl;
+ }
+ else
+ {
+ const SearchResult *result = item->result();
+ if(!result)
+ return;
+
+ if(!result->descriptions.isEmpty())
+ {
+ TranslationInfo *info;
+ QPtrListIterator<TranslationInfo> it(result->descriptions);
+ for(int i=0; i < currentInfo; i++)
+ {
+ ++it;
+ }
+ info=*it;
+
+ if(!info->filePath.isEmpty())
+ {
+ QString url = info->filePath;
+ QString msgid;
+
+ if( item->richText() )
+ {
+ msgid = result->plainFound;
+ }
+ else
+ {
+ msgid = result->found.first();
+ }
+
+ DCOPClient *dcop = kapp->dcopClient();
+
+ QCStringList list = dcop->registeredApplications();
+ int index = list.findIndex("kbabel");
+ if(index < 0)
+// if(!dcop->isApplicationRegistered("kbabel"));
+ {
+ kdDebug(KBABELDICT) << "kbabel is not registered" << endl;
+
+ QString error;
+ QStringList argList;
+ argList.append("--nosplash");
+ argList.append("--gotomsgid");
+ argList.append(msgid.local8Bit());
+ argList.append(url.local8Bit());
+ kapp->kdeinitExec("kbabel",argList,&error);
+ if(!error.isNull())
+ {
+ KMessageBox::sorry(this
+ ,i18n("There was an error starting KBabel:\n%1")
+ .arg(error));
+ return;
+ }
+ }
+ else
+ {
+ QByteArray data;
+ QDataStream arg(data, IO_WriteOnly);
+ arg << url.utf8() << msgid.utf8();
+ if (!dcop->send("kbabel", "KBabelIFace"
+ , "gotoFileEntry(QCString,QCString)",data))
+ {
+ KMessageBox::sorry(this
+ ,i18n("There was an error using DCOP."));
+ }
+ }
+ }
+ }
+ }
+}
+
+void KBabelDictBox::showContextMenu(KListView *,QListViewItem *,const QPoint& p)
+{
+ if(rmbPopup)
+ {
+ rmbPopup->exec(p);
+ }
+}
+
+
+bool KBabelDictBox::messagesForPackage(const QString& package
+ , QValueList<DiffEntry>& resultList, QString& error)
+{
+ setActiveModule("dbsearchengine");
+ SearchEngine *engine = moduleList.at(active);
+
+ if(!engine)
+ {
+ KMessageBox::sorry(this
+ ,i18n("The \"Translation Database\" module\n"
+ "appears not to be installed on your system."));
+ return false;
+ }
+
+ QValueList<SearchResult> rList;
+
+ SearchFilter* filter = new SearchFilter();
+ filter->setLocation(package);
+
+ bool success = engine->messagesForFilter(filter,rList,error);
+
+ if(success)
+ {
+ QValueList<SearchResult>::Iterator it;
+ for(it=rList.begin(); it != rList.end(); ++it)
+ {
+ // FIXME: what about plural forms?
+ DiffEntry e;
+ e.msgid = (*it).found.first();
+ e.msgstr = (*it).translation;
+ resultList.append(e);
+ }
+ }
+
+ return success;
+}
+
+#include "kbabeldictbox.moc"
+
diff --git a/kbabel/kbabeldict/kbabeldictbox.h b/kbabel/kbabeldict/kbabeldictbox.h
new file mode 100644
index 00000000..8168786e
--- /dev/null
+++ b/kbabel/kbabeldict/kbabeldictbox.h
@@ -0,0 +1,282 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef KBABELDICTBOX_H
+#define KBABELDICTBOX_H
+
+#include "kbabeldictiface.h"
+#include "searchengine.h"
+#include "catalog.h"
+
+#include <qdict.h>
+#include <qguardedptr.h>
+#include <qptrlist.h>
+#include <qstringlist.h>
+
+class KListView;
+class QLabel;
+class QListViewItem;
+class QPopupMenu;
+class QPushButton;
+class QSplitter;
+class QTextView;
+class QToolButton;
+
+struct ModuleInfo
+{
+ QString id;
+ QString name;
+
+ bool editable;
+};
+
+
+class KDE_EXPORT KBabelDictBox : public QWidget, virtual public KBabelDictIFace
+{
+ Q_OBJECT
+
+public:
+ KBabelDictBox( QWidget* parent = 0, const char* name = 0
+ , WFlags fl = 0 );
+ ~KBabelDictBox();
+
+ /** @returns ids of available modules */
+ virtual QStringList modules();
+
+ /** @returns (translated) names of available modules */
+ QStringList moduleNames();
+
+ /**
+ * @returns a list with information about the available modules
+ * Take care about, that you have to delete the items by yourself.
+ */
+ QPtrList<ModuleInfo> moduleInfos();
+
+ /** @returns preferencesWidgets of modules */
+ QPtrList<PrefWidget> modPrefWidgets(QWidget* parent);
+
+ int activeModule();
+ bool activeModuleEditable();
+
+ /**
+ * lets the modules always update their options before
+ * starting a new search
+ */
+ void setAutoUpdateOptions(bool on);
+
+ void nextResult();
+ void prevResult();
+ void startSearch(const QString);
+ void startTranslationSearch(const QString);
+ void startDelayedSearch(const QString);
+ void startDelayedTranslationSearch(const QString);
+ QString translate(const QString);
+ QString searchTranslation(const QString, int& score);
+ QString fuzzyTranslation(const QString, int& score);
+ void stopSearch();
+ void setActiveModule(QString name);
+
+ /**
+ * @returns true, if a search is active at the moment
+ */
+ bool isSearching();
+
+ /**
+ * Saves the settings including the settings of the different modules
+ * in the given config object.
+ */
+ void saveSettings(KConfigBase *config);
+
+ /**
+ * Saves the settings of the given module
+ * in the given config object.
+ */
+ void saveSettings(const QString& moduleId, KConfigBase *config);
+
+ /**
+ * Reads the settings including the settings of the different modules
+ * from the given config object.
+ */
+ void readSettings(KConfigBase *config);
+
+ /**
+ * Reads the settings of the given module
+ * from the given config object.
+ */
+ void readSettings(const QString& moduleId, KConfigBase *config);
+
+
+
+ /** @returns the translation of the current search result */
+ QString translation();
+
+ bool hasSelectedText() const;
+ QString selectedText() const;
+
+ void setRMBMenu(QPopupMenu *popup);
+
+
+ virtual bool eventFilter(QObject *, QEvent*);
+
+
+ /**
+ * A hack for kbabel to get a list of messages for a specific package
+ * from dbsearchengine. When dbsearchengine allows multiple access to
+ * the database this will get removed.
+ */
+ bool messagesForPackage(const QString& package
+ , QValueList<KBabel::DiffEntry>& resultList, QString& error);
+
+public slots:
+ virtual void setActiveModule(int);
+ void slotStartSearch(const QString&);
+ void slotStopSearch();
+ void slotNextResult();
+ void slotPrevResult();
+
+ void about();
+ void aboutModule(const QString& moduleID);
+ void aboutActiveModule();
+
+ /**
+ * sets the name of the package currently edited
+ */
+ void setEditedPackage(const QString& packageName);
+
+ /**
+ * sets the filepath of the package currently edited
+ */
+ void setEditedFile(const QString& path);
+
+ /** sets the language code to use */
+ void setLanguage(const QString& languageCode
+ , const QString& languageName);
+
+
+ void setTextChanged(const QStringList& orig, const QString& translation,
+ uint pluralForm, const QString& description);
+
+ /**
+ * if text is marked, copy this into the clipboard, otherwise
+ * copy the current translation into the clipboard
+ */
+ void copy();
+
+ void configure(const QString& moduleID, bool modal=false);
+ void edit(const QString& moduleID);
+ void edit();
+
+ void clear();
+
+
+signals:
+ void searchStarted();
+ void searchStopped();
+ void progressed(int);
+ void progressStarts(const QString&);
+ void progressEnds();
+ void activeModuleChanged(int);
+ void activeModuleChanged(bool editable);
+ void errorInModule(const QString& error);
+
+ /**
+ * emitted when either the order
+ * or the number of modules was changed
+ */
+ void modulesChanged();
+
+protected slots:
+ void showResult(QListViewItem*);
+ void addResult(const SearchResult*);
+ void nextInfo();
+ void showDetailsOnly();
+ void showListOnly();
+ void clearModuleResults();
+ void editFile();
+ void showContextMenu(KListView *, QListViewItem *, const QPoint&);
+
+ /**
+ * This slots gets connected to a SearchEngine's searchStopped() signal,
+ * when a new search is requested although a search is currently active.
+ */
+ void startDelayedSearch();
+ void startDelayedTranslationSearch();
+
+
+ /**
+ * This slot is connected to the finished signal of @ref KDialogBase
+ * to destroy this dialog after the user has closed it.
+ */
+ void destroyConfigDialog();
+
+protected:
+ virtual void wheelEvent(QWheelEvent*);
+
+private:
+ /**
+ * Register the module and connect the slots
+ */
+ void registerModule( SearchEngine* module);
+
+ QPtrList<SearchEngine> moduleList;
+ int active;
+ int currentResult;
+ int currentInfo;
+ int total;
+
+ /** stores a string to be used with delayed search */
+ QString searchText;
+
+ QDict<QWidget> prefDialogs;
+
+ QLabel *translatorLabel;
+ QLabel *locationLabel;
+ QLabel *totalResultsLabel;
+ QLabel *currentLabel;
+ QLabel *dateLabel;
+ QPushButton *moreButton;
+ QPushButton *nextButton;
+ QPushButton *prevButton;
+ QTextView *origView;
+ QTextView *translationView;
+ QSplitter *viewContainer;
+ KListView *resultListView;
+ QSplitter *resultSplitter;
+
+ QToolButton *listButton;
+ QToolButton *detailButton;
+
+ int editFileIndex;
+ QGuardedPtr<QPopupMenu> rmbPopup;
+};
+
+#endif // KBABELDICTBOX_H
diff --git a/kbabel/kbabeldict/kbabeldictiface.h b/kbabel/kbabeldict/kbabeldictiface.h
new file mode 100644
index 00000000..0b98a565
--- /dev/null
+++ b/kbabel/kbabeldict/kbabeldictiface.h
@@ -0,0 +1,56 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 1999-2001 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#ifndef KBABELDICTINTERFACE_H
+#define KBABELDICTINTERFACE_H
+
+#include <dcopobject.h>
+#include <qstringlist.h>
+
+class KBabelDictIFace : virtual public DCOPObject
+{
+ K_DCOP
+
+k_dcop:
+ virtual QStringList modules() = 0;
+ virtual ASYNC setActiveModule(QString modulename) = 0;
+
+ virtual ASYNC startSearch(const QString searchstring) = 0;
+ virtual ASYNC stopSearch() = 0;
+
+ virtual ASYNC nextResult()=0;
+ virtual ASYNC prevResult()=0;
+
+};
+
+#endif
diff --git a/kbabel/kbabeldict/kbabeldictview.cpp b/kbabel/kbabeldict/kbabeldictview.cpp
new file mode 100644
index 00000000..26afd981
--- /dev/null
+++ b/kbabel/kbabeldict/kbabeldictview.cpp
@@ -0,0 +1,294 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#include "kbabeldictview.h"
+#include "kbabeldictbox.h"
+#include "searchengine.h"
+
+
+#include <qcheckbox.h>
+#include <qgroupbox.h>
+#include <qhbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qptrlist.h>
+#include <qpushbutton.h>
+#include <qstringlist.h>
+#include <qwidgetstack.h>
+#include <qsplitter.h>
+#include <qvbox.h>
+
+#include <kcombobox.h>
+#include <kconfig.h>
+#include <kdialog.h>
+#include <kglobal.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <kprogress.h>
+#include <kseparator.h>
+#include <kdebug.h>
+#include <kiconloader.h>
+
+/*
+ * Constructs a KBabelDictView which is a child of 'parent', with the
+ * name 'name' and widget flags set to 'f'
+ */
+KBabelDictView::KBabelDictView( QWidget* parent, const char* name, WFlags fl )
+ : QWidget( parent, name, fl )
+{
+ QVBoxLayout *mainLayout = new QVBoxLayout(this);
+ mainLayout->setSpacing(KDialog::spacingHint());
+ mainLayout->setMargin(KDialog::marginHint());
+
+ splitter = new QSplitter(this);
+ mainLayout->addWidget(splitter);
+
+ QWidget *w = new QWidget(splitter);
+ QVBoxLayout *wLayout= new QVBoxLayout(w);
+ wLayout->setSpacing(KDialog::spacingHint());
+ wLayout->setMargin(KDialog::marginHint());
+
+ QHBoxLayout *hbox = new QHBoxLayout(wLayout);
+ QLabel *label = new QLabel(i18n("Search in module:"), w);
+ hbox->addWidget(label);
+ moduleCombo = new KComboBox(w);
+ hbox->addWidget(moduleCombo);
+
+ QWidget *temp = new QWidget(w);
+ hbox->addWidget(temp);
+ hbox->setStretchFactor(temp,2);
+ editButton = new QPushButton(i18n("&Edit"),w);
+ editButton->setEnabled(false);
+ hbox->addWidget(editButton);
+
+ // added a button "clear search" here
+ hbox = new QHBoxLayout(wLayout);
+ QPushButton* clearButton = new QPushButton(w);
+ clearButton->setFlat(true);
+ clearButton->setPixmap(SmallIcon("locationbar_erase"));
+ hbox->addWidget(clearButton);
+ textEdit = new KLineEdit(w,"textedit");
+ textEdit->setFocus();
+ hbox->addWidget(textEdit);
+
+ hbox = new QHBoxLayout(wLayout);
+ startButton = new QPushButton(i18n("&Start Search"),w);
+ hbox->addWidget(startButton);
+ inTransButton = new QCheckBox(i18n("Sea&rch in translations"),w);
+ hbox->addWidget(inTransButton);
+ hbox->addStretch(1);
+ stopButton = new QPushButton(i18n("S&top"),w);
+ stopButton->setEnabled(false);
+ hbox->addWidget(stopButton);
+
+ KSeparator *sep = new KSeparator(w);
+ wLayout->addWidget(sep);
+ dictBox = new KBabelDictBox(w,"kbabeldictbox");
+ wLayout->addWidget(dictBox);
+
+ prefWidget = new QWidget(splitter);
+ QVBoxLayout *tempLayout= new QVBoxLayout(prefWidget);
+ tempLayout->setSpacing(KDialog::spacingHint());
+ tempLayout->setMargin(KDialog::marginHint());
+
+ label = new QLabel(i18n("Settings:"),prefWidget);
+ tempLayout->addWidget(label);
+
+ prefStack = new QWidgetStack(prefWidget);
+ tempLayout->addWidget(prefStack);
+ tempLayout->addStretch(1);
+
+ KConfig *config = KGlobal::config();
+ dictBox->readSettings(config);
+ dictBox->setAutoUpdateOptions(true);
+
+ QStringList modules = dictBox->moduleNames();
+ moduleCombo->insertStringList(modules);
+
+ QPtrList<PrefWidget> prefs = dictBox->modPrefWidgets(prefStack);
+ prefs.setAutoDelete(false);
+
+ PrefWidget *p;
+ int i=0;
+ for(p = prefs.first(); p != 0; p=prefs.next())
+ {
+ prefStack->addWidget(p,i);
+ i++;
+ }
+
+ int active=dictBox->activeModule();
+ prefStack->raiseWidget(active);
+ moduleCombo->setCurrentItem(active);
+
+
+ QHBox *h = new QHBox(this);
+ h->setSpacing(KDialog::spacingHint());
+ mainLayout->addWidget(h);
+ progressLabel = new QLabel(h);
+ progressBar = new KProgress(h);
+
+ connect(textEdit,SIGNAL(returnPressed()),startButton,SLOT(animateClick()));
+ connect(startButton,SIGNAL(clicked()),this, SLOT(startSearch()));
+ connect(stopButton, SIGNAL(clicked()), dictBox,SLOT(slotStopSearch()));
+ connect(editButton, SIGNAL(clicked()), dictBox, SLOT(edit()));
+ connect(dictBox, SIGNAL(searchStarted()), this, SLOT(searchStarted()));
+ connect(dictBox, SIGNAL(searchStopped()), this, SLOT(searchStopped()));
+ connect(dictBox, SIGNAL(progressed(int)), progressBar, SLOT(setProgress(int)));
+ connect(dictBox, SIGNAL(activeModuleChanged(bool))
+ , editButton, SLOT(setEnabled(bool)));
+
+ connect(dictBox, SIGNAL(progressStarts(const QString&))
+ , this, SLOT(progressStarted(const QString&)));
+ connect(dictBox, SIGNAL(progressEnds()), this, SLOT(progressStopped()));
+
+ connect(moduleCombo, SIGNAL(activated(int)),
+ dictBox, SLOT(setActiveModule(int)));
+ connect(dictBox, SIGNAL(activeModuleChanged(int))
+ , this, SLOT(switchModule(int)));
+ connect(clearButton, SIGNAL(clicked()), this, SLOT(slotClearSearch()));
+}
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+KBabelDictView::~KBabelDictView()
+{
+ // no need to delete child widgets, Qt does it all for us
+ KConfig *config = KGlobal::config();
+ dictBox->saveSettings(config);
+}
+
+/*
+ * public slot
+ */
+void KBabelDictView::startSearch()
+{
+ QString text = textEdit->text();
+
+ if(!text.isEmpty())
+ {
+ if(inTransButton->isChecked())
+ {
+ dictBox->startTranslationSearch(text);
+ }
+ else
+ {
+ dictBox->startSearch(text);
+ }
+ }
+
+
+}
+
+void KBabelDictView::progressStopped()
+{
+ progressBar->setProgress(0);
+ progressLabel->setText("");
+ startButton->setEnabled(true);
+ stopButton->setEnabled(false);
+}
+
+void KBabelDictView::progressStarted(const QString& msg)
+{
+ progressLabel->setText(msg);
+ startButton->setEnabled(false);
+ stopButton->setEnabled(true);
+}
+
+void KBabelDictView::searchStopped()
+{
+ progressLabel->setText("");
+ progressBar->setProgress(0);
+ startButton->setEnabled(true);
+ stopButton->setEnabled(false);
+}
+
+void KBabelDictView::searchStarted()
+{
+ progressLabel->setText(i18n("Searching"));
+ startButton->setEnabled(false);
+ stopButton->setEnabled(true);
+}
+
+void KBabelDictView::switchModule(int m)
+{
+ moduleCombo->blockSignals(true);
+ moduleCombo->setCurrentItem(m);
+ moduleCombo->blockSignals(false);
+
+ prefStack->raiseWidget(m);
+}
+
+
+void KBabelDictView::about()
+{
+ dictBox->about();
+}
+
+
+void KBabelDictView::aboutModule()
+{
+ dictBox->aboutActiveModule();
+}
+
+int KBabelDictView::togglePref()
+{
+ int prefWidth=0;
+ if(prefWidget->isVisibleTo(this))
+ {
+ prefWidget->hide();
+ prefWidth=prefWidget->width();
+ }
+ else
+ {
+ prefWidget->show();
+ prefWidth=prefWidget->width();
+ }
+
+ return prefWidth;
+}
+
+bool KBabelDictView::prefVisible()
+{
+ return prefWidget->isVisibleTo(this);
+}
+
+void KBabelDictView::slotClearSearch()
+{
+ textEdit->clear();
+ textEdit->setFocus();
+}
+
+#include "kbabeldictview.moc"
+
diff --git a/kbabel/kbabeldict/kbabeldictview.h b/kbabel/kbabeldict/kbabeldictview.h
new file mode 100644
index 00000000..510936c4
--- /dev/null
+++ b/kbabel/kbabeldict/kbabeldictview.h
@@ -0,0 +1,92 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#ifndef KBABELDICTVIEW_H
+#define KBABELDICTVIEW_H
+
+#include <qwidget.h>
+
+class KComboBox;
+class KLineEdit;
+class KProgress;
+class QCheckBox;
+class QLabel;
+class QPushButton;
+class QSplitter;
+class QWidgetStack;
+
+class KBabelDictBox;
+
+class KBabelDictView : public QWidget
+{
+ Q_OBJECT
+
+public:
+ KBabelDictView( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 );
+ ~KBabelDictView();
+
+ bool prefVisible();
+
+public slots:
+ void startSearch();
+ void about();
+ void aboutModule();
+ int togglePref();
+
+private slots:
+ void searchStopped();
+ void searchStarted();
+ void switchModule(int);
+ void progressStopped();
+ void progressStarted(const QString&);
+ void slotClearSearch();
+
+private:
+ KBabelDictBox *dictBox;
+
+ KComboBox *moduleCombo;
+ KLineEdit *textEdit;
+ QCheckBox *inTransButton;
+ QPushButton *startButton;
+ QPushButton *stopButton;
+ QPushButton *editButton;
+ QWidgetStack *prefStack;
+ KProgress *progressBar;
+ QLabel *progressLabel;
+ QSplitter *splitter;
+
+ QWidget *prefWidget;
+};
+
+#endif // KBABELDICTVIEW_H
diff --git a/kbabel/kbabeldict/kbabelsplash.cpp b/kbabel/kbabeldict/kbabelsplash.cpp
new file mode 100644
index 00000000..16ac2352
--- /dev/null
+++ b/kbabel/kbabeldict/kbabelsplash.cpp
@@ -0,0 +1,73 @@
+/*
+ *
+ * $Id$
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ * 2003 Stanislav Visnovsky <visnovsky@kde.org>
+ *
+ * This file is part of the KBabel project. It's taken from the K3b project,
+ * Copyright (C) 1998-2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * 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.
+ * See the file "COPYING" for the exact licensing terms.
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of this program with any edition of
+ * the Qt library by Trolltech AS, Norway (or with modified versions
+ * of Qt that use the same license as Qt), and distribute linked
+ * combinations including the two. You must obey the GNU General
+ * Public License in all respects for all of the code used other than
+ * Qt. If you modify this file, you may extend this exception to
+ * your version of the file, but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from
+ * your version.
+ *
+ */
+
+#include "kbabelsplash.h"
+
+#include <qapplication.h>
+#include <qlabel.h>
+#include <qpixmap.h>
+#include <qevent.h>
+#include <qstring.h>
+#include <qfontmetrics.h>
+#include <qpainter.h>
+
+#include <kstandarddirs.h>
+
+KBabelSplash* KBabelSplash::instance = 0;
+
+KBabelSplash::KBabelSplash( QWidget* parent, const char* name )
+ : QVBox( parent, name, WType_Dialog|WShowModal|WStyle_Customize|WStyle_NoBorder|WDestructiveClose )
+{
+ setMargin( 0 );
+ setSpacing( 0 );
+
+ QLabel* picLabel = new QLabel( this );
+ QPixmap pixmap;
+ if( pixmap.load( locate( "data", "kbabel/pics/splash.png" ) ) )
+ picLabel->setPixmap( pixmap );
+
+ picLabel->setFrameStyle(QFrame::WinPanel | QFrame::Raised);
+
+ // Set geometry, with support for Xinerama systems
+ QRect r;
+ r.setSize(sizeHint());
+ int ps = QApplication::desktop()->primaryScreen();
+ r.moveCenter( QApplication::desktop()->screenGeometry(ps).center() );
+ setGeometry(r);
+
+ if( instance ) delete instance;
+ instance = this;
+}
+
+
+void KBabelSplash::mousePressEvent( QMouseEvent* )
+{
+ close();
+}
+
+#include "kbabelsplash.moc"
diff --git a/kbabel/kbabeldict/kbabelsplash.h b/kbabel/kbabeldict/kbabelsplash.h
new file mode 100644
index 00000000..c10b4fec
--- /dev/null
+++ b/kbabel/kbabeldict/kbabelsplash.h
@@ -0,0 +1,55 @@
+/*
+ *
+ * $Id$
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ * 2003 Stanislav Visnovsky <visnovsky@kde.org>
+ *
+ * This file is part of the KBabel project. It's taken from the K3b project,
+ * Copyright (C) 1998-2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * 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.
+ * See the file "COPYING" for the exact licensing terms.
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of this program with any edition of
+ * the Qt library by Trolltech AS, Norway (or with modified versions
+ * of Qt that use the same license as Qt), and distribute linked
+ * combinations including the two. You must obey the GNU General
+ * Public License in all respects for all of the code used other than
+ * Qt. If you modify this file, you may extend this exception to
+ * your version of the file, but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from
+ * your version.
+ *
+ */
+
+
+#ifndef KBABELSPLASH_H
+#define KBABELSPLASH_H
+
+#include <qvbox.h>
+
+class QLabel;
+class QMouseEvent;
+class QPaintEvent;
+class QString;
+
+
+class KBabelSplash : public QVBox
+{
+Q_OBJECT
+
+ public:
+ KBabelSplash( QWidget* parent = 0, const char* name = 0 );
+ ~KBabelSplash() { instance = 0; }
+
+ static KBabelSplash* instance;
+
+ protected:
+ void mousePressEvent( QMouseEvent* );
+};
+
+#endif
diff --git a/kbabel/kbabeldict/lo16-app-kbabeldict.png b/kbabel/kbabeldict/lo16-app-kbabeldict.png
new file mode 100644
index 00000000..a296a94f
--- /dev/null
+++ b/kbabel/kbabeldict/lo16-app-kbabeldict.png
Binary files differ
diff --git a/kbabel/kbabeldict/lo32-app-kbabeldict.png b/kbabel/kbabeldict/lo32-app-kbabeldict.png
new file mode 100644
index 00000000..6cc4e301
--- /dev/null
+++ b/kbabel/kbabeldict/lo32-app-kbabeldict.png
Binary files differ
diff --git a/kbabel/kbabeldict/main.cpp b/kbabel/kbabeldict/main.cpp
new file mode 100644
index 00000000..30d5a6c9
--- /dev/null
+++ b/kbabel/kbabeldict/main.cpp
@@ -0,0 +1,136 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2003 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include <dcopclient.h>
+#include <kaboutdata.h>
+#include <kcmdlineargs.h>
+#include <kcursor.h>
+#include <klocale.h>
+#include <kapplication.h>
+#include <kwin.h>
+
+#include <qtimer.h>
+
+#include "kbabeldict.h"
+#include "kbabelsplash.h"
+#include <version.h>
+
+class KBabelDictApplication : public KApplication
+{
+public:
+ KBabelDictApplication();
+ ~KBabelDictApplication();
+
+private:
+ KBabelDict *topLevel;
+};
+
+KBabelDictApplication::KBabelDictApplication()
+ : KApplication()
+ , topLevel(0)
+{
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+ QTimer timer;
+ QWidget *splash=0;
+ bool showSplash=args->isSet("splash");
+ if(showSplash)
+ {
+ timer.start(2000,true);
+ KApplication::setOverrideCursor(KCursor::waitCursor());
+ splash = new KBabelSplash();
+ splash->show();
+ }
+
+ topLevel = new KBabelDict();
+
+ while(timer.isActive()) // let the user admire the splash screen ;-)
+ processEvents();
+
+ setTopWidget(topLevel);
+ topLevel->show();
+
+ if(KBabelSplash::instance)
+ {
+ delete KBabelSplash::instance;
+ }
+ if(showSplash)
+ {
+ KApplication::restoreOverrideCursor();
+ }
+
+ QObject::connect( topLevel, SIGNAL( destroyed() ),
+ this, SLOT( quit() ) );
+}
+
+KBabelDictApplication::~KBabelDictApplication()
+{
+ delete(topLevel);
+}
+
+static KCmdLineOptions options[] =
+{
+ {"nosplash",I18N_NOOP("Disable splashscreen at startup"),0},
+ KCmdLineLastOption
+};
+
+
+int main(int argc, char **argv)
+{
+ KLocale::setMainCatalogue("kbabel");
+
+ KAboutData about("kbabeldict",I18N_NOOP("KBabel - Dictionary"),VERSION,
+ I18N_NOOP("A dictionary for translators"),KAboutData::License_GPL,
+ I18N_NOOP("(c) 2000,2001,2002,2003 The KBabeldict developers"),0,"http://kbabel.kde.org");
+
+ about.addAuthor("Matthias Kiefer",I18N_NOOP("Original author"),"kiefer@kde.org");
+ about.addAuthor("Stanislav Visnovsky",I18N_NOOP("Current maintainer"),"visnovsky@kde.org");
+
+ about.setTranslator( I18N_NOOP("_: NAME OF TRANSLATORS\nYour names")
+ , I18N_NOOP("_: EMAIL OF TRANSLATORS\nYour emails"));
+
+ // Initialize command line args
+ KCmdLineArgs::init(argc, argv, &about);
+
+ // Tell which options are supported
+ KCmdLineArgs::addCmdLineOptions( options );
+
+ // Add options from other components
+ KApplication::addCmdLineOptions();
+
+ KBabelDictApplication app;
+
+ return app.exec();
+}
diff --git a/kbabel/kbabeldict/modules/Makefile.am b/kbabel/kbabeldict/modules/Makefile.am
new file mode 100644
index 00000000..1807fb23
--- /dev/null
+++ b/kbabel/kbabeldict/modules/Makefile.am
@@ -0,0 +1,7 @@
+
+if include_DBSEARCHENGINE
+DB_SUBDIR=dbsearchengine
+endif
+
+SUBDIRS = pocompendium poauxiliary $(DB_SUBDIR) tmx
+
diff --git a/kbabel/kbabeldict/modules/dbsearchengine/AUTHOR b/kbabel/kbabeldict/modules/dbsearchengine/AUTHOR
new file mode 100644
index 00000000..2a79312d
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine/AUTHOR
@@ -0,0 +1 @@
+Andrea Rizzi <rizzi@kde.org> \ No newline at end of file
diff --git a/kbabel/kbabeldict/modules/dbsearchengine/KDBSearchEngine.cpp b/kbabel/kbabeldict/modules/dbsearchengine/KDBSearchEngine.cpp
new file mode 100644
index 00000000..ac55335d
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine/KDBSearchEngine.cpp
@@ -0,0 +1,1899 @@
+/***************************************************************************
+ KDBSearchEngine.cpp - description
+ -------------------
+ begin : Fri Sep 8 2000
+ copyright : (C) 2000 by Andrea Rizzi
+ (C) 2005 by Stanislav Visnovsky
+ email : rizzi@kde.org
+ ***************************************************************************/
+
+/*
+ Translation search engine
+
+
+ Copyright 2000
+ Andrea Rizzi rizzi@kde.org
+
+ License GPL v 2.0
+ * *
+ * In addition, as a special exception, the copyright holders give *
+ * permission to link the code of this program with any edition of *
+ * the Qt library by Trolltech AS, Norway (or with modified versions *
+ * of Qt that use the same license as Qt), and distribute linked *
+ * combinations including the two. You must obey the GNU General *
+ * Public License in all respects for all of the code used other than *
+ * Qt. If you modify this file, you may extend this exception to *
+ * your version of the file, but you are not obligated to do so. If *
+ * you do not wish to do so, delete this exception statement from *
+ * your version. *
+*/
+
+#include <qtextedit.h>
+#include <qprogressdialog.h>
+
+#include <qinputdialog.h>
+#include <kdeversion.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kio/netaccess.h>
+#include <kmessagebox.h>
+#include <kfiledialog.h>
+#include <kurlrequester.h>
+#include <kstandarddirs.h>
+
+#include "kapplication.h"
+#include "KDBSearchEngine.h"
+
+#include "dbscan.h"
+
+#include "errno.h"
+#include "stdio.h"
+#include "stdlib.h"
+#include <sys/time.h>
+#include "preferenceswidget.h"
+#include "dbse_factory.h"
+#include <qprogressbar.h>
+#include <qpushbutton.h>
+#include <klineedit.h>
+#include <kconfig.h>
+
+#include <qdir.h>
+#include <qradiobutton.h>
+#include <qcheckbox.h>
+#include <qspinbox.h>
+#include <qslider.h>
+#include <qmemarray.h>
+
+#include "database.h"
+
+#include "catalogsettings.h"
+
+#define BIGNUMBER 400000000
+
+using namespace KBabel;
+
+KDBSearchEngine::KDBSearchEngine (QObject * parent, const char *name):
+SearchEngine (parent, name)
+{
+ edited = "unknown";
+ dm = 0; //Database Manager
+ pw = 0; //Preference widget
+ lang = "";
+ dbOpened = false;
+ dbname = "";
+ lasterror = i18n ("No error");
+ connect (this, SIGNAL (hasError (const QString &)),
+ SLOT (setLastError (const QString &)));
+
+ IAmReady = true; // I don't know if it is a good idea, no DB loaded!!!
+
+ scanInProgress = false;
+ searching = false;
+ stopNow = false;
+
+ norm = false; // Normalize white space = FALSE
+ comm = true; // Remove Comments = TRUE
+
+}
+
+
+KDBSearchEngine::~KDBSearchEngine ()
+{
+}
+
+
+
+bool
+KDBSearchEngine::loadDatabase (QString database, bool noask = false)
+{
+ bool ret = true;
+ bool asked = false;
+ if (noask)
+ asked = true;
+ if (dm != 0)
+ {
+ delete dm;
+ dm = 0;
+ }
+
+ QDir dir (database);
+ if (!dir.exists ())
+ {
+ if (asked
+ || KMessageBox::questionYesNo (0,
+ i18n
+ ("Database folder does not exist:\n%1\n"
+ "Do you want to create it now?").
+ arg (database), QString::null, i18n("Create Folder"), i18n("Do Not Create")) ==
+ KMessageBox::Yes)
+ {
+ asked = true;
+
+ QStringList dirList;
+ while (!dir.exists () && !dir.dirName ().isEmpty ())
+ {
+ dirList.prepend (dir.dirName ());
+ dir.setPath (dir.path () + "/..");
+ }
+
+ for (QStringList::Iterator it = dirList.begin ();
+ it != dirList.end (); ++it)
+ {
+ if (!dir.mkdir (*it))
+ {
+ KMessageBox::sorry (0,
+ i18n
+ ("It was not possible to create folder %1").
+ arg (dir.path () + "/" +
+ (*it)));
+ ret = false;
+ break;
+ }
+ dir.cd (*it);
+ }
+ }
+ else
+ {
+ ret = false;
+ }
+ }
+
+ if (ret)
+ {
+ // test, if there are both of ,old and standard databases
+ QString transFile = database + "/translations." + lang + ".db";
+
+ bool oldstuff = QFile::exists (transFile + ",old");
+ bool newstuff = QFile::exists (transFile);
+
+ if (oldstuff && newstuff)
+ {
+ // there is an old db2 database, ask user
+
+ if (KMessageBox::
+ questionYesNo (0,
+ i18n
+ ("<p>There are backup database files from previous versions "
+ "of KBabel. However, another version of KBabel (probably from KDE 3.1.1 or 3.1.2) "
+ "created a new database. As a result, your KBabel installation contains two versions "
+ "of database files. Unfortunatelly, the old and new version "
+ "can not be merged. You need to choose one of them.<br/><br/>"
+ "If you choose the old version, the new one will be removed. "
+ "If you choose the new version, the old database files will be left alone "
+ "and you need to remove them manually. Otherwise this message will be displayed "
+ "again (the old files are at $KDEHOME/share/apps/kbabeldict/dbsearchengine/*,old).</p>"),
+ i18n ("Old Database Found"),
+ i18n ("Use &Old Database"),
+ i18n ("Use &New Database")) ==
+ KMessageBox::Yes)
+ {
+ // remove the new files
+ QFile::remove (transFile);
+ QFile::remove (database + "/wordsindex." + lang +
+ ".db");
+ QFile::remove (database + "/keysindex." + lang + ".db");
+ QFile::remove (database + "/catalogsinfo." + lang +
+ ".db");
+
+ // rename the old files
+ KIO::NetAccess::copy (KURL (transFile + ",old"),
+ KURL (transFile), 0);
+ KIO::NetAccess::
+ copy (KURL
+ (database + "/wordsindex." + lang +
+ ".db,old"),
+ KURL (database + "/wordsindex." + lang +
+ ".db"), 0);
+ KIO::NetAccess::
+ copy (KURL
+ (database + "/keysindex." + lang + ".db,old"),
+ KURL (database + "/keysindex." + lang +
+ ".db"), 0);
+ KIO::NetAccess::
+ copy (KURL
+ (database + "/catalogsinfo." + lang +
+ ".db,old"),
+ KURL (database + "/catalogsinfo." + lang +
+ ".db"), 0);
+
+ QFile::remove (transFile + ",old");
+ QFile::remove (database + "/wordsindex." + lang +
+ ".db,old");
+ QFile::remove (database + "/keysindex." + lang +
+ ".db,old");
+ QFile::remove (database + "/catalogsinfo." + lang +
+ ".db,old");
+ }
+ }
+ else if (oldstuff)
+ {
+ // rename the old files
+ KIO::NetAccess::copy (KURL (transFile + ",old"),
+ KURL (transFile), 0);
+ KIO::NetAccess::
+ copy (KURL (database + "/wordsindex." + lang + ".db,old"),
+ KURL (database + "/wordsindex." + lang + ".db"), 0);
+ KIO::NetAccess::
+ copy (KURL (database + "/keysindex." + lang + ".db,old"),
+ KURL (database + "/keysindex." + lang + ".db"), 0);
+ KIO::NetAccess::
+ copy (KURL
+ (database + "/catalogsinfo." + lang + ".db,old"),
+ KURL (database + "/catalogsinfo." + lang + ".db"), 0);
+
+ QFile::remove (transFile + ",old");
+ QFile::remove (database + "/wordsindex." + lang + ".db,old");
+ QFile::remove (database + "/keysindex." + lang + ".db,old");
+ QFile::remove (database + "/catalogsinfo." + lang +
+ ".db,old");
+ }
+
+ dm = new DataBaseManager (database, lang, this, "Database manager");
+
+ if (!dm->isOk ())
+ {
+ if (asked
+ || KMessageBox::questionYesNo (0,
+ i18n
+ ("Database files not found.\nDo you want to create them now?"), QString::null, i18n("Create"), i18n("Do Not Create"))
+ == KMessageBox::Yes)
+ {
+ //fprintf(stderr,"SI\n");
+ ret = dm->createDataBase (database, lang);
+ }
+ else
+ ret = false;
+ }
+ else
+ ret = true;
+ }
+
+//Wrong errore hangdling
+
+ if (ret)
+ totalRecord = dm->count ();
+ else
+ totalRecord = 0;
+
+ return ret;
+}
+
+
+/*
+ Set if the research have to consider multiple spaces as a single one.
+ */
+
+void
+KDBSearchEngine::setNormalizeSpace (bool normalize)
+{
+ norm = normalize;
+}
+
+
+void
+KDBSearchEngine::setRemoveInternalComment (bool internalcomment)
+{
+ comm = internalcomment;
+}
+
+/*
+ Set if the research have to be Case Sensitive or not
+ */
+
+void
+KDBSearchEngine::setCaseSensitive (bool sensitive)
+{
+ sens = sensitive;
+}
+
+/*
+ Set the a string containing all char that must be ignored
+ during the search.
+ */
+
+void
+KDBSearchEngine::setRemoveCharString (QString chartoremove)
+{
+ remchar = chartoremove;
+}
+
+/*
+ Return true if there's a search in progress.
+ */
+bool
+KDBSearchEngine::isSearching () const
+{
+ return searching;
+}
+
+
+
+
+/*
+ Add a search string in the list of the string to search for.
+ Returns the ID of the string in the list.
+ Returns -1 if there is a problem (may be search in progress)
+ */
+
+int
+KDBSearchEngine::addSearchString (QString searchString, int rule)
+{
+ if (searching || scanInProgress)
+ return -1;
+ SearchEntry e;
+ e.string = QString (searchString);
+ e.rules = rule;
+ searchStringList.append (e);
+ return searchStringList.count ();
+}
+
+
+/*
+ Start the research in the database of all the string in the list
+
+ */
+
+bool
+KDBSearchEngine::startSearch (const QString & str, uint pluralForm,
+ const SearchFilter * filter)
+{
+
+ if (autoUpdate)
+ {
+ updateSettings ();
+ }
+
+
+ int l1 = 0, l2 = 0;
+ if (defSub1)
+ l1 = defLimit1;
+ if (defSub2)
+ l2 = defLimit2;
+
+ return startSingleSearch (str, l1, l2);
+
+
+}
+
+bool
+KDBSearchEngine::startSearchInTranslation (QString s)
+{
+
+ if (autoUpdate)
+ {
+ updateSettings ();
+ }
+
+
+ int l1 = 0, l2 = 0;
+ if (defSub1)
+ l1 = defLimit1;
+ if (defSub2)
+ l2 = defLimit2;
+
+
+ return startSingleSearch (s, l1, l2, true);
+
+}
+
+
+bool
+KDBSearchEngine::openDb (bool noask = false)
+{
+ if (!dbOpened)
+ {
+ dbOpened = loadDatabase (dbname, noask); //Try first to open it now
+ if (!dbOpened) // Still not opened!!
+ {
+ hasError (i18n ("Cannot open the database"));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+
+
+bool
+KDBSearchEngine::messagesForFilter (const SearchFilter * filter,
+ QValueList < SearchResult > &resultList,
+ QString & error)
+{
+
+ int count = 0;
+ stopNow = false; // Remove dirty.
+ SearchResult m;
+
+ if (searching)
+ {
+ error = i18n ("Another search has already been started");
+ return false;
+ }
+
+ if (scanInProgress)
+ {
+ error =
+ i18n ("Unable to search now: a PO file scan is in progress");
+ return false;
+ }
+
+
+ if (!openDb ())
+ {
+ error = i18n ("Unable to open the database");
+ return false;
+ }
+
+ if (totalRecord <= 0)
+ {
+ error = i18n ("Database empty");
+ return false;
+ }
+
+ QString package = filter->location ();
+
+ int step = (totalRecord / 30) + 1;
+ int ntra, nref;
+ int req = dm->searchCatalogInfo (package);
+ if (req == -1)
+ {
+ error = i18n ("No entry for this package in the database.");
+ return false;
+ }
+ DataBaseItem item;
+ int i, h;
+ kdDebug (0) << "looking for catalog " << req << endl;
+
+ progressStarts (i18n ("Searching for %1 in database").arg (package));
+
+ for (item = dm->firstItem (); !item.isNull (); item = dm->nextItem ())
+ {
+ count++;
+ if (count % step == 0)
+ {
+ emit progress (100 * count / totalRecord);
+ kapp->processEvents (100);
+ }
+ if (stopNow)
+ {
+ stopNow = false;
+ searching = false;
+ emit finished ();
+ return true; // No error, stopped!
+ }
+
+ ntra = item.numTra;
+ for (i = 0; i < ntra; i++)
+ {
+ nref = item.translations[i].numRef;
+
+ for (h = 0; h < nref; h++)
+ {
+ if (item.translations[i].infoRef[h] == req)
+ {
+ m.found = item.key;
+ m.translation = item.translations[i].translation;
+ resultList.append (m);
+ }
+ }
+ }
+
+ }
+
+ return true;
+}
+
+void
+KDBSearchEngine::repeat ()
+{
+
+ int count = 0;
+ stopNow = false; // Remove dirty.
+
+ if (searching)
+ {
+ return;
+ }
+
+ if (scanInProgress)
+ {
+ return;
+ }
+
+
+ if (!openDb ())
+ {
+ return;
+ }
+
+ if (totalRecord <= 0)
+ {
+ return;
+ }
+
+ int step = (totalRecord / 30) + 1;
+ int ntra, nref;
+
+ DataBaseItem item;
+ int i, h, tot;
+
+ int req = dm->searchCatalogInfo ("kdelibs.po");
+ if (req == -1)
+ kdDebug (0) << "No kdelibs.po found!" << endl;
+
+
+ QProgressDialog *pd =
+ new QProgressDialog (i18n ("Looking for repetitions"), i18n ("Stop"),
+ 100);
+
+ connect (this, SIGNAL (progress (int)), pd, SLOT (setProgress (int)));
+ connect (this, SIGNAL (finished ()), pd, SLOT (close ()));
+ connect (pd, SIGNAL (cancelled ()), this, SLOT (stopSearch ()));
+
+
+ QString txt = "// %1 repetitions, %2 translation(s)\ni18n(\"%3\");\n";
+ QString id;
+ int min;
+ bool ok = false;
+
+ min =
+ QInputDialog::getInteger (i18n ("Minimum Repetition"),
+ i18n
+ ("Insert the minimum number of repetitions for a string:"),
+ 2, 1, 999999, 1, &ok);
+
+ if (!ok)
+ return;
+
+ pd->show ();
+
+ progressStarts (i18n ("Searching repeated string"));
+
+ static QTextEdit *mle = new QTextEdit ();
+ mle->clear ();
+
+ bool inlibs;
+
+ for (item = dm->firstItem (); !item.isNull (); item = dm->nextItem ())
+ {
+ count++;
+ if (count % step == 0)
+ {
+ emit progress (100 * count / totalRecord);
+ kapp->processEvents (100);
+ }
+ if (stopNow)
+ {
+ stopNow = false;
+ searching = false;
+ emit finished ();
+ return; // No error, stopped!
+ }
+ tot = 0;
+ inlibs = false;
+ ntra = item.numTra;
+ for (i = 0; i < ntra; i++)
+ {
+ nref = item.translations[i].numRef;
+ for (h = 0; h < nref; h++)
+ if (item.translations[i].infoRef[h] == req)
+ inlibs = true;
+
+ tot += nref;
+ }
+
+ if (tot >= min && !inlibs)
+ {
+ id = item.key;
+ id = id.replace ("\n", "\"\n\"");
+ mle->append (txt.arg (tot).arg (ntra).arg (id));
+
+ }
+ }
+
+
+ emit progress (100);
+ emit finished ();
+ mle->resize (400, 400);
+ mle->show ();
+
+ delete pd;
+ return;
+}
+
+
+
+bool
+KDBSearchEngine::startSearchNow (int searchmode)
+{
+ if (searchmode == -1)
+ searchmode = mode;
+ int count = 0;
+ stopNow = false; // Remove dirty.
+ clearResults ();
+
+
+ if (searching)
+ {
+ hasError (i18n ("Another search has already been started"));
+ return false;
+ }
+
+ if (scanInProgress)
+ {
+ hasError (i18n
+ ("Unable to search now: a PO file scan is in progress"));
+ return false;
+ }
+
+
+ if (!openDb ())
+ return false;
+
+
+ if (totalRecord <= 0)
+ {
+ hasError (i18n ("Database empty"));
+ return false;
+ }
+
+
+
+ searching = true;
+
+ emit started ();
+
+ bool allkey = (searchmode == MD_ALL_GOOD_KEYS);
+
+ bool equal, contains, contained, regexp, intra;
+
+ intra = searchmode & MD_IN_TRANSLATION;
+
+ QString msgIdFound;
+ QString msgId;
+ QString msgStr;
+ //QString msgIdRequested;
+ SearchResult *aresult;
+ TranslationInfo *adescription;
+ SearchList searchList;
+ int i, len, files, h;
+ len = remchar.length ();
+
+ int n, m; //,word;
+ QString *id;
+
+ QString mainRequest = searchStringList[0].string;
+
+
+ SearchList::Iterator it, it1;
+ QString *idMod;
+ bool foundSomething = false;
+
+ searchList = searchStringList; //Create a copy and modify it
+ if (!allkey)
+ {
+ for (it = searchList.begin (); it != searchList.end (); ++it)
+ {
+ idMod = &((*it).string);
+ int pos;
+ for (i = 0; i < len; i++)
+ {
+ while ((pos = idMod->find (remchar.at (i))) != -1)
+ idMod->remove (pos, 1);
+ }
+
+ if (comm)
+ idMod->replace (QRegExp ("\\_\\:.*\\\\n"), ""); //Read it from catalog !!! (NOT ONLY HERE)
+
+
+ if (norm)
+ idMod->simplifyWhiteSpace ();
+ if (!sens)
+ *idMod = idMod->upper ();
+ }
+
+ }
+
+ timeval now;
+ gettimeofday (&now, NULL);
+ //fprintf(stderr,"\n%ld.%ld\n",now.tv_sec,now.tv_usec);
+ //double tim=1.0*now.tv_usec/1000000.0+now.tv_sec;
+ int pos;
+
+
+
+ DataBaseItem item;
+
+
+ //Now we can browse the whole db or the "good keys"
+ QValueList < KeyAndScore > goodkeys;
+ int totalprogress;
+
+ bool gk = (searchmode == MD_GOOD_KEYS) || allkey;
+ int k = 0;
+
+ if (gk)
+ {
+ goodkeys = searchWords (mainRequest, thre, threorig, listmax); //FIX IT, mainReq?
+ if (stopNow)
+ {
+ stopNow = false;
+ searching = false;
+ emit finished ();
+ return false;
+ }
+ if (goodkeys.count () == 0)
+ gk = false; // if no good keys, use the whole database
+ }
+
+ // prepare progress values
+ totalprogress = gk ? goodkeys.count () : totalRecord;
+ int step = (totalprogress / 30) + 1;
+ if( step > 100 )
+ step = 100;
+
+ emit progress (0);
+ kapp->processEvents (100);
+ if (stopNow)
+ {
+ stopNow = false;
+ searching = false;
+ emit finished ();
+ return true; // No error, stopped!
+ }
+
+
+ for (item = gk ? (dm->getItem (goodkeys[0])) : (dm->firstItem ());
+ !item.isNull ();
+ item = gk ? (dm->getItem (goodkeys[++k])) : (dm->nextItem ()))
+ {
+
+// Emit progress, process event and check stop now
+ if (count % step == 0)
+ {
+ emit progress (100 * count / /*QMAX( */
+ totalprogress /*,1) */ );
+ kapp->processEvents (100);
+
+ if (stopNow)
+ {
+ stopNow = false;
+ searching = false;
+ emit finished ();
+ return true; // No error, stopped!
+ }
+ }
+
+ // fprintf(stderr,"%s\n",(const char *)item.key.utf8());
+ msgIdFound = item.key; //Check if this is OK with UTF8
+
+// searchmode && MD_IN_TRANSLATION)
+
+ count++;
+
+
+
+ msgId = msgIdFound;
+
+ if (!allkey)
+ {
+
+ //Remove character in list of character to be ignored
+ for (i = 0; i < len; i++)
+ while ((pos = msgId.find (remchar.at (i))) != -1)
+ msgId.remove (pos, 1);
+
+ //Remove context information from id found
+ if (comm)
+ msgId.replace (QRegExp ("\\_\\:.*\\\\n"), "");
+
+
+ if (norm)
+ msgId.simplifyWhiteSpace ();
+ if (!sens)
+ msgId = msgId.upper ();
+ }
+
+
+
+ it = searchList.begin ();
+ idMod = &((*it).string);
+ bool foundExact = false;
+
+ for (it1 = searchStringList.begin ();
+ it1 != searchStringList.end (); it1++)
+ {
+
+ id = &((*it1).string);
+ uint nn = 0;
+ do
+ {
+ if (intra)
+ {
+ msgId = item.translations[nn].translation;
+ if (!allkey)
+ {
+ //Remove character in list of character to be ignored
+ for (i = 0; i < len; i++)
+ while ((pos =
+ msgId.find (remchar.at (i))) !=
+ -1)
+ msgId.remove (pos, 1);
+
+ //Remove context information from id found
+ if (comm)
+ msgId.
+ replace (QRegExp ("\\_\\:.*\\\\n"),
+ "");
+
+
+ if (norm)
+ msgId.simplifyWhiteSpace ();
+ if (!sens)
+ msgId = msgId.upper ();
+ }
+
+
+ }
+
+
+ int rules = (*it).rules;
+
+ if (rules & Equal)
+ equal = (*idMod == msgId);
+ else
+ equal = false;
+
+ if (rules & Contains)
+ contains = idMod->contains (msgId);
+ else
+ contains = false;
+
+ if (rules & Contained)
+ contained = msgId.contains (*idMod);
+ else
+ contained = false;
+
+ if (!foundExact && (rules & RegExp))
+ {
+ QRegExp reg (*idMod);
+ regexp = (reg.search (msgId) != -1);
+ }
+ else
+ regexp = false;
+ nn++;
+ }
+ while (intra && nn < item.numTra);
+
+ if (equal || contains || contained || regexp || allkey)
+ {
+
+ if (equal)
+ foundExact = true;
+
+ m = item.numTra; //Translations found.
+
+ for (n = 0; n < m; n++)
+ {
+
+ foundSomething = true;
+
+
+ msgStr = item.translations[n].translation;
+
+ files = item.translations[n].numRef;
+
+ aresult = new SearchResult ();
+
+ results.setAutoDelete (true);
+ if (!gk)
+ aresult->score =
+ score (mainRequest, msgIdFound);
+ else
+ aresult->score = goodkeys[k].score;
+
+ if (intra)
+ aresult->score =
+ score (mainRequest,
+ item.translations[n].translation);
+
+
+ SearchResult *s = 0;
+ for (s = results.first (); s != 0;
+ s = results.next ())
+ {
+ if (s->score > aresult->score)
+ {
+ results.insert (results.at (),
+ aresult);
+ break;
+ }
+
+ }
+ if (s == 0) //no break or empty list
+ results.append (aresult);
+
+
+/* if(*id==msgIdFound) //Put it first of the list
+ results.prepend(aresult);
+ else
+ results.append(aresult);
+*/
+ aresult->requested = *id;
+ aresult->found = msgIdFound;
+ aresult->translation = msgStr;
+ aresult->descriptions.setAutoDelete (true);
+ for (h = 0; h < files; h++)
+ {
+
+ aresult->descriptions.append (adescription =
+ new
+ TranslationInfo
+ ());
+ int rr = item.translations[n].infoRef[h];
+
+ InfoItem info = dm->getCatalogInfo (rr);
+
+
+ adescription->location = info.catalogName;
+ adescription->translator =
+ info.lastTranslator;
+ adescription->filePath = info.lastFullPath;
+ }
+
+ emit numberOfResultsChanged (results.count ());
+ emit resultFound (aresult);
+
+// if(*id==msgIdFound) //Put it first of the list so th order change
+ emit resultsReordered ();
+
+
+
+ }
+ }
+ // idMod=searchList.next();
+ it++;
+ idMod = &((*it).string);
+ }
+
+
+ }
+ gettimeofday (&now, NULL);
+ //fprintf(stderr,"%ld.%ld\n",now.tv_sec,now.tv_usec);
+
+ //fprintf(stderr,"Finish, %d (of %d) records in %f seconds!!\n",count,totalRecord, 1.0*now.tv_usec/1000000.0+now.tv_sec-tim);
+ emit progress (100);
+ emit finished ();
+
+ searching = false;
+ return true; //foundSomething;
+}
+
+/*
+ Start a search for a single string
+ */
+
+bool
+KDBSearchEngine::startSingleSearch (QString searchString,
+ unsigned int pattern1Limit,
+ unsigned int /*pattern2Limit */ ,
+ bool inTranslation)
+{
+ /*
+ Check Ret
+ value.
+ */
+
+ unsigned int nw = 0;
+ int in = 0, len = 0;
+ clearList ();
+ addSearchString (searchString, defRule);
+
+
+
+ QRegExp reg ("[a-zA-Z0-9_%" /*+remchar */ + regaddchar + "]+");
+ while ((in = reg.search (searchString, in + len)) != -1)
+ {
+ nw++;
+ len = reg.matchedLength ();
+ }
+ in = 0;
+ len = 0;
+ // fprintf(stderr,"asas %d\n",nw);
+
+ if (mode == MD_ALL_GOOD_KEYS && !inTranslation)
+ return startSearchNow ();
+
+
+
+ if ((nw < pattern1Limit) && (nw > 1))
+ for (unsigned int k = 0; k < nw; k++)
+ {
+ in = reg.search (searchString, in + len);
+ len = reg.matchedLength ();
+ QString regToAdd = searchString;
+ regToAdd.replace (in, len, "[a-zA-Z0-9_%" + regaddchar + "]*");
+ regToAdd.append ("$");
+ regToAdd.prepend ("^");
+// fprintf(stderr,"%s",(const char *)regToAdd.local8Bit());
+ addSearchString (regToAdd, RegExp);
+ }
+
+ if (inTranslation)
+ return startSearchNow (MD_IN_TRANSLATION);
+ else
+ return startSearchNow ();
+
+ return false;
+
+}
+
+
+/*
+ Start a search for a list of string
+ */
+
+//bool KDBSearchEngine::startListSearch(QPtrList<QString> searchStrList)
+//{
+ // searchStringList=searchStrList;
+// return startSearchNow();
+//}
+/*
+ Stop the current search
+ */
+
+
+
+void
+KDBSearchEngine::setLanguageCode (const QString & ll)
+{
+ if (ll == lang)
+ return;
+
+ lang = ll;
+ if (dbOpened) //if opened open it again with new code, what about close before open ?
+ dbOpened = loadDatabase (dbname);
+
+}
+
+void
+KDBSearchEngine::setLanguage (const QString & languageCode,
+ const QString & /*languageName */ )
+{
+ setLanguageCode (languageCode);
+}
+
+void
+KDBSearchEngine::stopSearch ()
+{
+ stopNow = true;
+}
+
+
+void
+KDBSearchEngine::clearList ()
+{
+ searchStringList.clear ();
+}
+
+bool
+KDBSearchEngine::isReady () const
+{
+ return IAmReady;
+}
+
+
+void
+KDBSearchEngine::saveSettings (KConfigBase * config)
+{
+// updateSettings(); //maybe with autoupdate
+ KConfigGroupSaver cgs (config, "KDBSearchEngine");
+#if KDE_IS_VERSION(3,1,3)
+ config->writePathEntry ("Filename", dbname);
+#else
+ config->writeEntry ("Filename", dbname);
+#endif
+ config->writeEntry ("Language", lang);
+
+
+ config->writeEntry ("CaseSensitive", sens);
+ config->writeEntry ("Normalize", norm);
+ config->writeEntry ("RemoveContext", comm);
+
+ config->writeEntry ("Rules", defRule);
+ config->writeEntry ("Limit1", defLimit1);
+ config->writeEntry ("Limit2", defLimit2);
+ config->writeEntry ("Substitution1", defSub1);
+ config->writeEntry ("Substitution2", defSub2);
+
+ config->writeEntry ("RegExp", regaddchar);
+ config->writeEntry ("RemoveCharacter", remchar);
+
+ config->writeEntry ("Threshold1", thre);
+ config->writeEntry ("Threshold2", threorig);
+ config->writeEntry ("ListMax", listmax);
+ config->writeEntry ("Mode", mode);
+ config->writeEntry ("CommonThrs", commonthre);
+ config->writeEntry ("ReturnNothing", retnot);
+
+ config->writeEntry ("AutoAuthor", autoauthor);
+ config->writeEntry ("AutoUp", autoup);
+
+}
+
+
+void
+KDBSearchEngine::readSettings (KConfigBase * config)
+{
+ QString newName;
+
+ KConfigGroupSaver cgs (config, "KDBSearchEngine");
+
+ QString defaultLang;
+ QString oldLang = lang;
+ Defaults::Identity def;
+ defaultLang = def.languageCode ();
+ lang = config->readEntry ("Language", defaultLang);
+
+ QString defaultDir;
+ KStandardDirs *dirs = KGlobal::dirs ();
+ if (dirs)
+ {
+ defaultDir = dirs->saveLocation ("data");
+ if (defaultDir.right (1) != "/")
+ defaultDir += "/";
+ defaultDir += "kbabeldict/dbsearchengine";
+ }
+
+ newName = config->readPathEntry ("Filename", defaultDir);
+
+ if (newName != dbname || oldLang != lang)
+ {
+ dbname = newName;
+ if (dbOpened) //Reload only if it is opened
+ dbOpened = loadDatabase (dbname);
+ }
+
+ sens = config->readBoolEntry ("CaseSensitive", false);
+ norm = config->readBoolEntry ("Normalize", true);
+ comm = config->readBoolEntry ("RemoveContext", true);
+
+ defRule = config->readNumEntry ("Rules", 1);
+ defLimit1 = config->readNumEntry ("Limit1", 20);
+ defLimit2 = config->readNumEntry ("Limit2", 8);
+
+ thre = config->readNumEntry ("Threshold1", 50);
+ threorig = config->readNumEntry ("Threshold2", 50);
+ listmax = config->readNumEntry ("ListMax", 500);
+ mode = config->readNumEntry ("Mode", MD_GOOD_KEYS);
+
+ defSub1 = config->readBoolEntry ("Substitution1", true);
+ defSub2 = config->readBoolEntry ("Substitution2", false);
+
+ regaddchar = config->readEntry ("RegExp");
+ remchar = config->readEntry ("RemoveCharacter", "&.:");
+ commonthre = config->readNumEntry ("CommonThrs", 300);
+ retnot = config->readBoolEntry ("ReturnNothing", false);
+ autoauthor = config->readEntry ("AutoAuthor");
+ autoup = config->readBoolEntry ("AutoUp", true);
+
+ setSettings ();
+}
+
+PrefWidget *
+KDBSearchEngine::preferencesWidget (QWidget * parent)
+{
+
+ pw = new PreferencesWidget (parent);
+ setSettings ();
+ connect (pw, SIGNAL (restoreNow ()), this, SLOT (setSettings ()));
+ connect (pw, SIGNAL (applyNow ()), this, SLOT (updateSettings ()));
+ connect (pw, SIGNAL (destroyed ()), this, SLOT (prefDestr ()));
+ connect (pw->dbpw->scanPB_2, SIGNAL (clicked ()), this, SLOT (scan ()));
+ connect (pw->dbpw->scanrecPB, SIGNAL (clicked ()), this,
+ SLOT (scanRecur ()));
+ connect (pw->dbpw->scanFilePB, SIGNAL (clicked ()), this,
+ SLOT (scanFile ()));
+ connect (pw->dbpw->repeatPB, SIGNAL (clicked ()), this, SLOT (repeat ()));
+
+
+ return pw;
+}
+
+void
+KDBSearchEngine::scanRecur ()
+{
+ if (scanInProgress)
+ return;
+ updateSettings ();
+
+ if (!openDb ())
+ return;
+ scanInProgress = true;
+ PoScanner *sca = new PoScanner (dm, this, "Po Scanner");
+ QString cvsdir;
+ cvsdir =
+ KFileDialog::getExistingDirectory ("", 0,
+ i18n
+ ("Select Folder to Scan Recursively"));
+
+ if (cvsdir.isEmpty ())
+ {
+ scanInProgress = false;
+ return;
+ }
+ if (pw)
+ {
+ connect (sca, SIGNAL (patternProgress (int)), pw->dbpw->totalPB,
+ SLOT (setProgress (int)));
+ connect (sca, SIGNAL (fileLoading (int)), pw->dbpw->loadingPB,
+ SLOT (setProgress (int)));
+ connect (sca, SIGNAL (fileProgress (int)), pw->dbpw->processPB,
+ SLOT (setProgress (int)));
+ }
+
+ connect (sca, SIGNAL (patternProgress (int)), SIGNAL (progress (int))); //Kbabel progress bar
+
+ connect (sca, SIGNAL (added (int)), pw, SLOT (setEntries (int)));
+ connect (sca, SIGNAL (filename (QString)), pw, SLOT (setName (QString)));
+
+
+ progressStarts (i18n ("Scanning folder %1").arg (cvsdir));
+ connect (sca, SIGNAL (patternFinished ()), SIGNAL (progressEnds ()));
+
+ sca->scanPattern (cvsdir, "*.po", true);
+ disconnect (this, SIGNAL (progress (int)));
+//disconnect(SIGNAL(patternStarted()),this,SIGNAL(started()) );
+ disconnect (this, SIGNAL (progressEnds ()));
+ if (pw)
+ {
+ disconnect (pw->dbpw->totalPB, SLOT (setProgress (int)));
+ disconnect (pw->dbpw->loadingPB, SLOT (setProgress (int)));
+ disconnect (pw->dbpw->processPB, SLOT (setProgress (int)));
+ }
+ totalRecord = dm->count ();
+
+ scanInProgress = false;
+ dm->sync ();
+ delete sca;
+}
+
+
+void
+KDBSearchEngine::scan ()
+{
+ if (scanInProgress)
+ return;
+ updateSettings ();
+
+ if (!openDb ())
+ return;
+ scanInProgress = true;
+ PoScanner *sca = new PoScanner (dm, this, "Po Scanner");
+ QString cvsdir;
+
+ cvsdir =
+ KFileDialog::getExistingDirectory ("", 0,
+ i18n ("Select Folder to Scan"));
+ if (cvsdir.isEmpty ())
+ {
+ scanInProgress = false;
+ return;
+ }
+ if (pw)
+ {
+ connect (sca, SIGNAL (patternProgress (int)), pw->dbpw->totalPB,
+ SLOT (setProgress (int)));
+ connect (sca, SIGNAL (fileLoading (int)), pw->dbpw->loadingPB,
+ SLOT (setProgress (int)));
+ connect (sca, SIGNAL (fileProgress (int)), pw->dbpw->processPB,
+ SLOT (setProgress (int)));
+ }
+ connect (sca, SIGNAL (patternProgress (int)), SIGNAL (progress (int)));
+ progressStarts (i18n ("Scanning folder %1").arg (cvsdir));
+ connect (sca, SIGNAL (patternFinished ()), SIGNAL (progressEnds ()));
+
+ connect (sca, SIGNAL (added (int)), pw, SLOT (setEntries (int)));
+ connect (sca, SIGNAL (filename (QString)), pw, SLOT (setName (QString)));
+
+
+
+ sca->scanPattern (cvsdir, "*.po", false);
+
+ disconnect (this, SIGNAL (progress (int)));
+//disconnect(SIGNAL(patternStarted()),this,SIGNAL(started()) );
+ disconnect (this, SIGNAL (progressEnds ()));
+ if (pw)
+ {
+ disconnect (pw->dbpw->totalPB, SLOT (setProgress (int)));
+ disconnect (pw->dbpw->loadingPB, SLOT (setProgress (int)));
+ disconnect (pw->dbpw->processPB, SLOT (setProgress (int)));
+ }
+ totalRecord = dm->count ();
+
+ scanInProgress = false;
+
+ dm->sync ();
+ delete sca;
+}
+
+void
+KDBSearchEngine::scanFile ()
+{
+ if (scanInProgress)
+ return;
+ updateSettings ();
+
+ if (!openDb ())
+ return;
+ scanInProgress = true;
+ PoScanner *sca = new PoScanner (dm, this, "Po Scanner");
+ QString cvsdir;
+ pw->dbpw->totalPB->setProgress (0);
+
+ cvsdir =
+ KFileDialog::getOpenFileName ("", "*.po", 0,
+ i18n ("Select PO File to Scan"));
+ if (cvsdir.isEmpty ())
+ {
+ scanInProgress = false;
+ return;
+ }
+ if (pw)
+ {
+ connect (sca, SIGNAL (fileLoading (int)), pw->dbpw->loadingPB,
+ SLOT (setProgress (int)));
+ connect (sca, SIGNAL (fileProgress (int)), pw->dbpw->processPB,
+ SLOT (setProgress (int)));
+ }
+ connect (sca, SIGNAL (fileProgress (int)), SIGNAL (progress (int)));
+ progressStarts (i18n ("Scanning file %1").arg (directory (cvsdir, 0)));
+ connect (sca, SIGNAL (fileFinished ()), SIGNAL (progressEnds ()));
+
+ connect (sca, SIGNAL (added (int)), pw, SLOT (setEntries (int)));
+ connect (sca, SIGNAL (filename (QString)), pw, SLOT (setName (QString)));
+
+
+
+ sca->scanFile (cvsdir);
+
+ sca->disconnect (SIGNAL (fileProgress (int)), this,
+ SIGNAL (progress (int)));
+//disconnect(SIGNAL(patternStarted()),this,SIGNAL(started()) );
+ sca->disconnect (SIGNAL (fileFinished ()), this,
+ SIGNAL (progressEnds ()));
+ if (pw)
+ {
+ disconnect (pw->dbpw->loadingPB, SLOT (setProgress (int)));
+ disconnect (pw->dbpw->processPB, SLOT (setProgress (int)));
+ }
+
+ totalRecord = dm->count ();
+
+ scanInProgress = false;
+
+ dm->sync ();
+ delete sca;
+}
+
+const KAboutData *
+KDBSearchEngine::about () const
+{
+
+ return DbSeFactory::instance ()->aboutData ();
+
+}
+
+QString
+KDBSearchEngine::name () const
+{
+ return i18n ("Translation Database");
+}
+
+QString
+KDBSearchEngine::id () const
+{
+ return QString ("KDBSearchEngine");
+}
+
+QString
+KDBSearchEngine::lastError ()
+{
+ return lasterror;
+}
+
+void
+KDBSearchEngine::prefDestr ()
+{
+ pw = 0;
+}
+
+
+void
+KDBSearchEngine::setSettings ()
+{
+
+ if (pw == 0)
+ return;
+
+ pw->dbpw->dirInput->setURL (dbname);
+ pw->dbpw->caseSensitiveCB->setChecked (sens);
+ pw->dbpw->normalizeCB->setChecked (norm);
+ pw->dbpw->removeContextCB->setChecked (comm);
+
+ pw->dbpw->oneWordSubCB->setChecked (defSub1);
+ pw->dbpw->twoWordSubCB->setChecked (defSub2);
+
+
+ if (defRule == 8)
+ pw->dbpw->RegExpRB->setChecked (true);
+ else
+ {
+ pw->dbpw->normalTextRB->setChecked (true);
+ pw->dbpw->equalCB->setChecked (defRule & Equal);
+ pw->dbpw->containsCB->setChecked (defRule & Contains);
+ pw->dbpw->containedCB->setChecked (defRule & Contained);
+ }
+
+ pw->dbpw->oneWordSubSB->setValue (defLimit1);
+ pw->dbpw->twoWordSubSB->setValue (defLimit2);
+
+ pw->dbpw->maxSB->setValue (listmax);
+ pw->dbpw->thresholdSL->setValue (thre);
+ pw->dbpw->thresholdOrigSL->setValue (threorig);
+
+ pw->dbpw->allRB->setChecked (mode == MD_ALL_DB);
+ pw->dbpw->slistRB->setChecked (mode == MD_GOOD_KEYS);
+ pw->dbpw->rlistRB->setChecked (mode == MD_ALL_GOOD_KEYS);
+
+ pw->dbpw->nothingCB->setChecked (retnot);
+ pw->dbpw->freqSB->setValue (commonthre);
+
+ pw->dbpw->regExpLE->setText (regaddchar);
+ pw->dbpw->ignoreLE->setText (remchar);
+
+ pw->dbpw->authorLE->setText (autoauthor);
+ pw->dbpw->autoAddCB_2->setChecked (autoup);
+
+
+
+}
+
+
+void
+KDBSearchEngine::updateSettings ()
+{
+ if (pw == 0)
+ return;
+
+ QString newName = pw->dbpw->dirInput->url ();
+
+ if (newName != dbname)
+ {
+ kdDebug (0) << "Database changed" << endl;
+ dbname = newName;
+ if (dbOpened)
+ dbOpened = loadDatabase (dbname);
+ }
+
+ sens = pw->dbpw->caseSensitiveCB->isChecked ();
+ norm = pw->dbpw->normalizeCB->isChecked ();
+ comm = pw->dbpw->removeContextCB->isChecked ();
+
+ int tmpRule = 0;
+ if (pw->dbpw->RegExpRB->isChecked ())
+ tmpRule = RegExp;
+ else
+ {
+ if (pw->dbpw->equalCB->isChecked ())
+ tmpRule += Equal;
+ if (pw->dbpw->containsCB->isChecked ())
+ tmpRule += Contains;
+ if (pw->dbpw->containedCB->isChecked ())
+ tmpRule += Contained;
+ }
+
+ defRule = tmpRule;
+
+ defLimit1 = pw->dbpw->oneWordSubSB->text ().toInt ();
+ defLimit2 = pw->dbpw->twoWordSubSB->text ().toInt ();
+ defSub1 = pw->dbpw->oneWordSubCB->isChecked ();
+ defSub2 = pw->dbpw->twoWordSubCB->isChecked ();
+
+ listmax = pw->dbpw->maxSB->value ();
+ thre = pw->dbpw->thresholdSL->value ();
+ threorig = pw->dbpw->thresholdOrigSL->value ();
+
+ if (pw->dbpw->allRB->isChecked ())
+ mode = MD_ALL_DB;
+ if (pw->dbpw->slistRB->isChecked ())
+ mode = MD_GOOD_KEYS;
+ if (pw->dbpw->rlistRB->isChecked ())
+ mode = MD_ALL_GOOD_KEYS;
+
+
+ regaddchar = pw->dbpw->regExpLE->text ();
+ remchar = pw->dbpw->ignoreLE->text ();
+
+ retnot = pw->dbpw->nothingCB->isChecked ();
+ commonthre = pw->dbpw->freqSB->value ();
+
+ autoauthor = pw->dbpw->authorLE->text ();
+ autoup = pw->dbpw->autoAddCB_2->isChecked ();
+
+
+}
+
+void
+KDBSearchEngine::setLastError (const QString & er)
+{
+ lasterror = er;
+}
+
+QString
+KDBSearchEngine::translate (const QString & text, const uint pluralForm)
+{
+ if (!openDb ())
+ return QString::null;
+/*
+
+if(!dbOpened)
+ {
+ dbOpened=loadDatabase(dbname); //Try first to open it now
+ if(!dbOpened) // Still not opened!!
+ {
+ //emit anerror
+ hasError(i18n("Database not opened"));
+ return QString::null;
+ }
+ }
+*/
+
+ DataBaseItem dbit = dm->getItem (text);
+
+ if (dbit.isNull ())
+ return QString::null;
+ if (dbit.numTra == 1)
+ return dbit.translations[0].translation;
+
+ uint32 n = dbit.numTra;
+ uint32 max = 0, nmax = 0;
+ for (uint32 i = 0; i < n; i++)
+ if (dbit.translations[i].numRef > max)
+ {
+ nmax = i;
+ max = dbit.translations[i].numRef;
+ }
+
+ return dbit.translations[nmax].translation;
+
+
+}
+
+QValueList < KeyAndScore > KDBSearchEngine::searchWords (QString phrase,
+ int threshold,
+ int thresholdorig,
+ uint32 max)
+{
+ QValueList < QString > wordlist;
+
+ if (!openDb ())
+ {
+ QValueList < KeyAndScore > a;
+ return a;
+ }
+
+ progressStarts (i18n ("Searching words"));
+
+ QValueList < QString >::Iterator wlit;
+ wordlist = dm->wordsIn (phrase);
+ int
+ nw = wordlist.count ();
+//QMemArray<WordItem> wi(nw);
+ QMemArray < uint32 > numofloc (nw), currentloc (nw);
+ QMemArray < int >
+ score (nw);
+ QMemArray < uint32 * >loc (nw), locorig (nw);
+ QValueList < uint32 > resloc;
+ QValueList < int >
+ resfound;
+ QValueList < KeyAndScore > keylist;
+//wi.resize(wordlist.count());
+ int
+ totalprogress = 0;
+ int
+ totrec = dm->count ();
+ uint32
+ cthre = totrec * commonthre / 10000;
+ int
+ i = 0, common = 0;
+ for (wlit = wordlist.begin (); wlit != wordlist.end (); ++wlit)
+ {
+ WordItem
+ wi = dm->getWordLocations (*wlit);
+ if (!wi.notFound ())
+ {
+ if (wi.count < cthre)
+ score[i] = 1;
+ else
+ {
+ score[i] = 0;
+ common++;
+ }
+
+ locorig[i] = loc[i] = wi.locations;
+ totalprogress += numofloc[i] = wi.count;
+ currentloc[i] = 0;
+// score[i]=wi.score;
+ //wi[i]=WordItem(wi[i]);
+ //wi[i].locations.detach();
+ i++;
+// }
+ // else
+ // common++;
+
+
+
+ }
+ }
+ bool
+ cs = (common == nw); //All words are common;
+ if (totalprogress == 0)
+ totalprogress = 1;
+ int
+ step = totalprogress / 30 + 1;
+ int
+ count = 0;
+ int
+ thrs = (wordlist.count () * threshold) / 100;
+ if (thrs < 1)
+ thrs = 1; // whole database ???
+
+ int
+ tot = i;
+//nt32 jmin=0;
+ int
+ found;
+ uint32
+ min; //Big ?
+ bool
+ empty = false;
+
+
+ while (!empty)
+ {
+
+ empty = true;
+ found = retnot ? common : 0;
+ if (thrs <= found)
+ thrs = found + 1; // whole database ???
+
+ min = BIGNUMBER;
+ for (int j = 0; j < tot; j++)
+ if (cs || score[j])
+ {
+ if (numofloc[j] > currentloc[j]) // Check if there's still something to do.
+ empty = false;
+ if (loc[j][0] < min) //Found the minimum head
+ min = loc[j][0];
+
+
+ }
+ if (min != BIGNUMBER)
+ {
+ for (int j = 0; j < tot; j++)
+ if (cs || score[j])
+ {
+ if (loc[j][0] == min) //Count the heads, move forward
+ {
+ found++;
+ count++;
+ //check stopnow here
+ if (count % step == 0)
+ {
+ emit
+ progress (100 * count / totalprogress);
+ kapp->processEvents (100);
+ }
+ if (stopNow)
+ {
+ return keylist;
+ }
+
+ currentloc[j]++;
+ if (numofloc[j] == currentloc[j]) //End reached
+ loc[j][0] = BIGNUMBER; //so set head to a big number
+ else //Go on..
+ {
+ loc[j]++;
+ }
+ }
+ } //end of for
+ bool
+ inserted = false;
+
+
+
+ if (found >= thrs)
+ {
+ //Words count in key.
+ int
+ nword = 0;
+
+ int
+ in = 0, len = 0;
+ QString
+ keyst = dm->getKey (min);
+ QRegExp
+ reg ("[a-zA-Z0-9_%" /*+remchar */ + regaddchar + "]+");
+ while ((in = reg.search (keyst, in + len)) != -1)
+ {
+ nword++;
+ len = reg.matchedLength ();
+ }
+
+ if (found >= nword * thresholdorig / 100) //
+ {
+
+ if (resfound.count () <= max
+ || (*resfound.end () < found))
+ if ((*resfound.end ()) >= found)
+ {
+ inserted = true;
+ resloc.append (min);
+ resfound.append (found);
+
+ }
+ else
+ for (uint32 j = 0; j < resloc.count ();
+ j++)
+ {
+ if (resfound[j] < found || (resfound[j] == found && 0)) //Orig word
+ {
+ resloc.insert (resloc.at (j),
+ min);
+ resfound.insert (resfound.
+ at (j),
+ found);
+ inserted = true;
+ break;
+ }
+ }
+ if (!inserted)
+ {
+ resloc.append (min);
+ resfound.append (found);
+ }
+
+ }
+ }
+
+ }
+
+ }
+ int
+ nres = (resloc.count () < max) ? resloc.count () : max;
+
+ for (int j = 0; j < nres; j++)
+ {
+ QString
+ strkey = dm->getKey (resloc[j]);
+ int
+ stdscore = KDBSearchEngine::score (phrase, strkey);
+ int
+ sc = 0;
+
+ if (stdscore < 99)
+ {
+ int
+ in = 0, len = 0, nword = 0;
+ int
+ remove = retnot ? common : 0;
+ QRegExp
+ reg ("[a-zA-Z0-9_%" /*+remchar */ + regaddchar + "]+");
+ while ((in = reg.search (strkey, in + len)) != -1)
+ {
+ nword++;
+ len = reg.matchedLength ();
+ }
+
+// kdDebug(0) << nword << "NWORD " << resfound[j] << "FOUND "
+// << resfound[j]-remove << "REAL " << remove << "to be remove " << endl;
+ if (nword < 1)
+ nword = 1;
+ sc = 70 - resfound[j] * 70 / nw + abs (nword -
+ (resfound[j] -
+ remove)) * 30 /
+ nword + 2;
+ sc = 100 - sc;
+// kdDebug(0) <<" Score : " << sc << endl;
+
+ }
+ else
+ sc = stdscore;
+
+ KeyAndScore
+ key (strkey, sc);
+
+// kdDebug(0) << (QString) key << " [" << key.score << "]" << endl;
+ keylist.append (key);
+ }
+
+//kdDebug(0) << "Here!" << endl;
+
+ for (int j = 0; j < tot; j++)
+ {
+ free (locorig[j]);
+ }
+ progressStarts (i18n ("Process output"));
+ return keylist;
+}
+
+void
+KDBSearchEngine::stringChanged (const QStringList & o,
+ const QString & translated, const uint,
+ const QString &)
+{
+
+ QString orig = o.first (); // FIXME: plural forms
+
+ // skip empty originals or translated texts
+ if (orig.isEmpty () || translated.isEmpty ())
+ return;
+
+ if (autoup)
+ {
+ if (openDb (true)) //true= no ask
+ {
+
+ dm->putNewTranslation (orig, translated,
+ dm->catalogRef (directory (edited, 0),
+ autoauthor, edited));
+ //kdDebug(0) << "Changed " << orig << " " << translated << endl;
+ dm->sync ();
+ }
+ }
+
+}
+
+void
+KDBSearchEngine::setEditedFile (const QString & file)
+{
+
+ edited = file; //kdDebug(0) << edited << endl;
+}
+
+KeyAndScore::KeyAndScore (const QString & a, int sc):
+QString (a)
+{
+ score = sc;
+}
+
+KeyAndScore::KeyAndScore ():QString ()
+{
+ score = 0;
+}
+
+#include "KDBSearchEngine.moc"
diff --git a/kbabel/kbabeldict/modules/dbsearchengine/KDBSearchEngine.h b/kbabel/kbabeldict/modules/dbsearchengine/KDBSearchEngine.h
new file mode 100644
index 00000000..058444db
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine/KDBSearchEngine.h
@@ -0,0 +1,333 @@
+
+/***************************************************************************
+ KDBSearchEngine.h - description
+ -------------------
+ begin : Fri Sep 8 2000
+ copyright : (C) 2000 by Andrea Rizzi
+ email : rizzi@kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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; version 2 of the License. *
+ * *
+ * In addition, as a special exception, the copyright holders give *
+ * permission to link the code of this program with any edition of *
+ * the Qt library by Trolltech AS, Norway (or with modified versions *
+ * of Qt that use the same license as Qt), and distribute linked *
+ * combinations including the two. You must obey the GNU General *
+ * Public License in all respects for all of the code used other than *
+ * Qt. If you modify this file, you may extend this exception to *
+ * your version of the file, but you are not obligated to do so. If *
+ * you do not wish to do so, delete this exception statement from *
+ * your version. *
+ ***************************************************************************/
+/*
+ Translation search engine
+
+
+ Copyright 2000
+ Andrea Rizzi rizzi@kde.org
+
+*/
+
+
+/*
+ * This is a database engine specific
+ * structure, I think I must found a way to
+ * make it more "standard"
+ */
+
+#ifndef _KDBSEARCH_ENGINE_
+#define _KDBSEARCH_ENGINE_
+#include <qobject.h>
+#include <qptrlist.h>
+#include <qstring.h>
+#include <qmemarray.h>
+#include <qvaluelist.h>
+
+
+#include "database.h"
+#include "searchengine.h"
+#include "preferenceswidget.h"
+
+
+//value of mode
+#define MD_ALL_DB 1
+#define MD_GOOD_KEYS 2
+#define MD_ALL_GOOD_KEYS 3
+#define MD_IN_TRANSLATION 4
+
+class SearchEntry
+{
+ public:
+ QString string;
+ int rules;
+};
+
+class KeyAndScore : public QString
+{
+ public:
+ KeyAndScore();
+ KeyAndScore(const QString &a,int sc);
+ int score;
+};
+
+typedef QValueList<SearchEntry> SearchList;
+
+/* USE searchengine.h structure
+class CatalogDescription
+{
+ public:
+ char language[6]; // How many character chinese language needs?
+ // QString is better ?
+ QString filename;
+ QString dateOfScan; //When you add this to database (last time)
+ QString authorOfScan;
+ QString fileHeader; //msgid ""
+};
+
+ */
+
+class KDBSearchEngine : public SearchEngine
+{
+ Q_OBJECT
+
+public:
+
+
+ KDBSearchEngine(QObject *parent=0,const char *name=0);
+ ~KDBSearchEngine();
+ enum Rules {Equal = 1, Contains = 2, Contained = 4, RegExp = 8};
+ enum FormatRules { Dots = 1, Ampersand = 2, FirstWordUpper = 4, //Not yet used
+ AllWordUpper = 8, AmpersanAlwaysFirst = 16 };
+
+ /*
+ Set the directory where db file are located
+ */
+
+ void setDBName(QString filename);
+
+ /*
+ Set if the research have to consider multiple spaces as a single one.
+ */
+
+ void setNormalizeSpace(bool normalize);
+
+ /*
+ Set if the research have to be Case Sensitive or not
+ */
+
+ void setCaseSensitive(bool sensitive);
+
+
+ /*
+ ignore ":_ bla bla \n" in msgid
+
+ */
+
+ void setRemoveInternalComment(bool internalcomment);
+
+ /*
+ Set the a string containing all char that must be ignored
+ during the search.
+ */
+
+
+ void setRemoveCharString(QString chartoremove);
+
+ /*
+ Enable an output filter that format Uppercase/lowercase
+ method could be;
+ 0 = Disabled;
+ 1 = English pattern;
+ 2 = Only first;
+ */
+
+ void enableCapitalFilter(int method);
+
+ /*
+ Enable an output filter that format special characters
+ method could be;
+ 0 = Disabled;
+ 1 = Put ... at the end if needed (remove if present but no needed);
+ 2 = Put an accelerator (or remove);
+ 4 = Remove %* if not present in msgid.
+ 8 = Change %d,%s etc with %1 %2 etc if needed.
+ */
+
+ void enableCharFilter(int method);
+
+ /*
+ Sets the rules to decide when 2 string match (Uppercase and remove char
+ are not set here)
+ 1 = EQUAL
+ 2 = SEARCH STRING IS CONTAINED IN DATABASE STRING (use with care, if you search nothing
+ it will produce a dangerouse output)
+ 4 = DATABASE STRING IS CONTAINED IN SEARCH STRING (it exclude msgid "")
+ 8 = String is a regexp. (exclude 1 2 4)
+ */
+
+ void setMatchingRules(int rules);
+
+ /*
+ Search Engine methods reimplemented
+ */
+
+
+
+ virtual bool messagesForFilter(const SearchFilter* filter
+ , QValueList<SearchResult>& resultList, QString& error);
+
+
+ virtual void setLanguageCode(const QString& lang);
+ virtual void setLanguage(const QString& languageCode, const QString& languageName);
+
+ virtual void setEditedFile(const QString& file);
+
+ virtual bool isReady() const ;
+ virtual bool isSearching() const;
+
+ virtual void saveSettings(KConfigBase *config);
+ virtual void readSettings(KConfigBase *config);
+
+ virtual PrefWidget *preferencesWidget(QWidget *parent);
+
+ virtual const KAboutData *about() const;
+
+ virtual QString name() const;
+
+ virtual QString id() const;
+
+ virtual QString lastError();
+
+ virtual QString translate(const QString& text, uint pluralForm);
+
+ virtual void stringChanged( const QStringList& orig, const QString& translated
+ , const uint translationPluralForm, const QString& description);
+
+
+public slots:
+
+ void scan();
+ void scanRecur();
+ void scanFile();
+ /*
+ Add a search string in the list of the string to search for.
+ Returns the ID of the string in the list.
+ Returns -1 if there is a problem (may be search in
+ progress)
+ */
+
+ int addSearchString(QString searchString, int rule=Equal);
+
+ /*
+ Start the research in the database of all the string in the list
+ search mode -1 means use global mode;
+ */
+ bool startSearchNow(int searchmode=-1);
+
+ /*
+ Start a search for a single string
+ If the number of word of your string is less than patternXlimit
+ the KDBSearchEngine will search for all string with X * substituted to
+ X word.
+ For example if pattern1limit is 4 and you search "My name is Andrea"
+ This string will also match with:
+ "Your name is Andrea", "My dog is Andrea", "My name was Andrea", "My name is Joe"
+
+ Do not set pattern2limit too high.
+
+ If a patternlimit is > 0 rules 8 (* means any word) is added.
+
+ */
+
+ bool startSingleSearch(QString searchString,unsigned int pattern1Limit,unsigned int pattern2Limit,
+ bool inTranslation=false);
+
+ /*
+ Start a search for a list of string
+ */
+
+// bool startListSearch(QPtrList<QString> searchStrList);
+
+/*
+ * Return a list of key in database that contains some
+ * words of the given string phrase.
+ * thresholdin is a number from 0 to 100 a key is good
+ * if at least the threshold% of words are found
+ * thresholdout a key is good if the found words represnt
+ * at least the thresholdorig% of the words in the key
+ * max is the maximum number of results
+ */
+
+QValueList<KeyAndScore> searchWords(QString phrase,int threshold,
+ int thresholdorig ,uint32 max);
+
+
+ /*
+ Stop the current search
+ */
+
+ virtual void stopSearch();
+ virtual bool startSearch(const QString& text, uint pluralForm, const SearchFilter* filter);
+ virtual bool startSearchInTranslation(QString s);
+
+ void clearList();
+signals:
+ void found(SearchResult *);
+private slots:
+ void updateSettings(); //Use widget settings
+ void setSettings(); //Fill widget with actual settings
+ void prefDestr();
+ void setLastError(const QString&);
+ void repeat();
+private:
+ /*
+ Reload database info (and keep the dbase opened).
+ */
+ bool loadDatabase(QString database,bool);
+
+ bool openDb(bool);
+
+ PreferencesWidget *pw;
+ bool IAmReady;
+ int methodFilterChar;
+ int methodFilterCapital;
+ int defRule;
+ int defLimit1;
+ int defLimit2;
+ int thre;
+ int threorig;
+ int commonthre;
+ int listmax;
+ int mode;
+ bool retnot;
+ bool defSub1;
+ bool defSub2;
+ bool stopNow;
+ bool searching;
+ bool norm,sens,comm;
+ int numofresult;
+ char * filename;
+ QString remchar;
+ QString regaddchar;
+ QString dbname;
+ bool dbOpened;
+// GDBM_FILE db;
+ DataBaseManager * dm;
+// datum key, value;
+// QMemArray<CatalogDescription *> catinfo;
+ SearchList searchStringList;
+ int totalRecord;
+ QString lasterror;
+ QString lang;
+ bool scanInProgress;
+ QString edited;
+ bool autoup;
+ QString autoauthor;
+};
+
+#endif
diff --git a/kbabel/kbabeldict/modules/dbsearchengine/Makefile.am b/kbabel/kbabeldict/modules/dbsearchengine/Makefile.am
new file mode 100644
index 00000000..8504999a
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine/Makefile.am
@@ -0,0 +1,34 @@
+## Makefile.am for DBSE
+
+# this has all of the subdirectories that make will recurse into. if
+# there are none, comment this out
+#SUBDIRS =
+
+
+# this is the program that gets installed. it's name is used for all
+# of the other Makefile.am variables
+kde_module_LTLIBRARIES = kbabeldict_dbsearchengine.la
+
+# set the include path for X, qt and KDE
+INCLUDES = -I$(srcdir)/../.. -I../../../common -I$(srcdir)/../../../common $(all_includes) $(DBIV_INCLUDES)
+
+# which sources should be compiled for kbabel
+kbabeldict_dbsearchengine_la_SOURCES = KDBSearchEngine.cpp preferenceswidget.cpp \
+ dbse_factory.cpp dbseprefwidget.ui database.cpp dbscan.cpp
+#database.cpp dbscan.cpp
+kbabeldict_dbsearchengine_la_LIBADD = ../../libkbabeldictplugin.la ../../../common/libkbabelcommon.la $(LIB_KDEUI) $(LIB_KIO) $(LIB_DBIV)
+kbabeldict_dbsearchengine_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined \
+ $(DBIV_LDFLAGS)
+
+
+# these are the headers for your project
+noinst_HEADERS = KDBSearchEngine.h preferenceswidget.h dbse_factory.h \
+ database.h dbscan.h
+
+
+# let automoc handle all of the meta source files (moc)
+METASOURCES = AUTO
+
+kde_services_DATA = dbsearchengine.desktop
+EXTRA_DIST = $(kde_services_DATA)
+
diff --git a/kbabel/kbabeldict/modules/dbsearchengine/STRUCTURE b/kbabel/kbabeldict/modules/dbsearchengine/STRUCTURE
new file mode 100644
index 00000000..0a53a0fe
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine/STRUCTURE
@@ -0,0 +1,25 @@
+
+
+key = original text
+
+data
+ 0..3 num of translation (n)
+
+ translations
+ 0..3 num of file references (m)
+ 4..(4+m*4) file references
+ 4+m*4..first\0 translation
+
+
+----------------------------------------------------
+Files structure.
+
+
+"it" is the language
+
+catalogsinfo.it.db //Info about the catalog
+keysindex.it.db //index of numofkeys->key
+translations.it.db //guess.. (key->translation)
+wordsindex.it.db //index of word->numofkey
+
+
diff --git a/kbabel/kbabeldict/modules/dbsearchengine/TODO b/kbabel/kbabeldict/modules/dbsearchengine/TODO
new file mode 100644
index 00000000..0e7fbd3a
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine/TODO
@@ -0,0 +1,27 @@
+TODO List fore KDE Database Translation Search Engine
+
+-Finish the port (use settings) done
+-Improve settings (filter output)
+-Database handling (and creation...) Done
+-output filters
+-fix fix fix...
+
+-delete item if putItem(nullitem)
+-use matthias mask function for regexp
+-remove bug of word split F&ormat is F ormat <- add remchar to charregexp
+
+
+Major rewrite:
+-New settings interface.
+-addFunction from dbscan to database Done ?
+-Edit function
+-database manager
+-download compendium from the internet
+
+Matthias ask:
+- searching in translations, equivalent to searching in msgids (SearchEngine::startTranslationSearch(QString s) )
+- the absolute path of the files and maybe the number of the entry in the file ( maybe I will add this information to the TranslationInfo )
+- the possibility to get a list of all entries in a po file from the database. For this, I think, I will create a interface and send it to you. Maybe something like this: class TranslationDatabase {
+public: // name is something like "kbabel.po" QList<CatalogItem> entriesOfFile(QString name); }
+
+
diff --git a/kbabel/kbabeldict/modules/dbsearchengine/configure.in.bot b/kbabel/kbabeldict/modules/dbsearchengine/configure.in.bot
new file mode 100644
index 00000000..58d6118f
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine/configure.in.bot
@@ -0,0 +1,5 @@
+if test "x$with_berkeley_db" = xcheck && test -z "$LIB_DBIV"; then
+ echo ""
+ echo "Dictionary plugin \"Translation Database\" for KBabel will not be built! Please install Berkeley Database IV. See http://www.sleepycat.com for more information.)"
+ echo ""
+fi
diff --git a/kbabel/kbabeldict/modules/dbsearchengine/configure.in.in b/kbabel/kbabeldict/modules/dbsearchengine/configure.in.in
new file mode 100644
index 00000000..fbc3f1a8
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine/configure.in.in
@@ -0,0 +1,143 @@
+AC_ARG_WITH(berkeley-db,
+ [AC_HELP_STRING(--with-berkeley-db,
+ [enable the dictionary plugin based on Berkeley DB IV @<:@default=check@:>@])],
+ [], with_berkeley_db=check)
+
+LIB_DBIV=""
+if test "x$with_berkeley_db" != xno; then
+
+AC_MSG_CHECKING([for Berkeley Database IV])
+
+db_libraries=""
+db_includes=""
+db_name=""
+ac_db_name="db"
+ac_db_includes=""
+ac_db_libraries=""
+ac_db_include_file="db.h"
+
+AC_ARG_WITH(db-dir,
+ AC_HELP_STRING([--with-db-dir=DIR],[where the root of Berkeley DB IV is installed]),
+ [ ac_db_includes=-I"$withval"/include
+ ac_db_libraries=-L"$withval"/lib
+ ])
+AC_ARG_WITH(db-include-dir,
+ AC_HELP_STRING([--with-db-include-dir=DIR],[where the includes of Berkeley DB IV are installed]),
+ [ ac_db_includes=-I"$withval"
+ ])
+AC_ARG_WITH(db-include,
+ AC_HELP_STRING([--with-db-include=FILE],[path to the Berkeley DB IV header file]),
+ [ ac_db_include_file=-I"$withval"
+ ])
+AC_ARG_WITH(db-lib-dir,
+ AC_HELP_STRING([--with-db-lib-dir=DIR],[where the libs of Berkeley DB IV are installed]),
+ [ ac_db_libraries=-L"$withval"
+ ])
+AC_ARG_WITH(db-name,
+ AC_HELP_STRING([--with-db-name=NAME],[name of the Berkeley DB IV library (default db)]),
+ [ ac_db_name="$withval"
+ ])
+
+AC_DEFUN([KDE_CHECK_DB_VERSION],
+[
+ifelse($3,,,[LIBS="$kde_db_safe -l$3"])
+AC_TRY_LINK([
+#include <$2>
+],
+[
+#if DB_VERSION_MAJOR == 4
+DB *db;
+#if DB_VERSION_MINOR > 0
+db->open( db, NULL, "test.db", NULL, DB_BTREE, DB_CREATE, 0644 );
+#else
+db->open( db, "test.db", NULL, DB_BTREE, DB_CREATE, 0644 );
+#endif
+#else
+error
+#endif
+],
+kde_cv_berk_database=$1
+)
+])
+
+AC_CACHE_VAL(kde_cv_berk_database,
+[
+kde_safe_LDFLAGS=$LDFLAGS
+kde_db_safe_LIBS=$LIBS
+LDFLAGS="$LDFLAGS $X_LDFLAGS $USER_LDFLAGS $all_libraries $ac_db_libraries $all_includes $ac_db_includes"
+
+kde_cv_berk_database=NO
+if test "xNO" = "x$kde_cv_berk_database" ; then
+ KDE_CHECK_DB_VERSION($ac_db_name, $ac_db_include_file, $ac_db_name)
+fi
+if test "xNO" = "x$kde_cv_berk_database" ; then
+ KDE_CHECK_DB_VERSION(db4, db4/db.h, db4)
+fi
+if test "xNO" = "x$kde_cv_berk_database" ; then
+ KDE_CHECK_DB_VERSION(db4-db, db.h, db4)
+fi
+if test "xNO" = "x$kde_cv_berk_database" ; then
+ KDE_CHECK_DB_VERSION(db, db.h, db)
+fi
+
+LIBS=$kde_db_safe_LIBS
+LDFLAGS=$kde_safe_LDFLAGS
+
+])
+
+kde_db_header=""
+DBSEARCHENGINE=dbsearchengine
+
+case "$kde_cv_berk_database" in
+ NO)
+ AC_MSG_RESULT(no)
+ LIB_DBIV=""
+ DBSEARCHENGINE=""
+ ;;
+ db)
+ LIB_DBIV="-l$ac_db_name"
+ kde_db_header=db.h
+ AC_MSG_RESULT(-l$ac_db_name)
+ AC_DEFINE_UNQUOTED(HAVE_DB_DB_H, 1, [DB 4 header location] )
+ ;;
+ db4-db)
+ LIB_DBIV='-ldb4'
+ kde_db_header=db.h
+ AC_MSG_RESULT("flag is -ldb4 and header is db.h")
+ AC_DEFINE_UNQUOTED(HAVE_DB_DB_H, 1, [DB 4 header location] )
+ ;;
+ db4)
+ LIB_DBIV='-ldb4'
+ kde_db_header=db4/db.h
+ AC_MSG_RESULT(-ldb4)
+ AC_DEFINE_UNQUOTED(HAVE_DB4_DB_H, 1, [DB 4 header location] )
+ ;;
+ $ac_db_name)
+ LIB_DBIV="-l$ac_db_name"
+ kde_db_header="$ac_db_include_file"
+ AC_MSG_RESULT(user specified $ac_db_name)
+ if test "x$ac_db_include_file" = "xdb.h" ; then
+ AC_DEFINE_UNQUOTED(HAVE_DB_DB_H, 1, [DB 4 header location] )
+ else
+ AC_DEFINE_UNQUOTED(USE_DB_H_PATH, <$ac_db_include_file>, [DB 4 header path])
+ fi
+
+ ;;
+esac
+
+DBIV_LDFLAGS="$ac_db_libraries"
+DBIV_INCLUDES="$ac_db_includes"
+DBIV_NAME="$ac_db_name"
+
+if test "x$with_berkeley_db" != xcheck && test -z "$LIB_DBIV"; then
+ AC_MSG_ERROR([--with-berkeley-db was given, but test for Berkeley DB IV failed])
+fi
+fi
+
+AC_SUBST(DBIV_INCLUDES)
+AC_SUBST(DBIV_LDFLAGS)
+AC_SUBST(DBIV_NAME)
+
+AC_SUBST(LIB_DBIV)
+
+AM_CONDITIONAL(include_DBSEARCHENGINE, test -n "$DBSEARCHENGINE")
diff --git a/kbabel/kbabeldict/modules/dbsearchengine/database.cpp b/kbabel/kbabeldict/modules/dbsearchengine/database.cpp
new file mode 100644
index 00000000..003a3a95
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine/database.cpp
@@ -0,0 +1,1533 @@
+/***************************************************************************
+ database.cpp -
+ -------------------
+ begin : Fri Sep 8 2000
+ copyright : (C) 2000 by Andrea Rizzi
+ email : rizzi@kde.org
+ ***************************************************************************/
+
+/*
+ Translation search engine
+
+
+ Copyright 2000
+ Andrea Rizzi rizzi@kde.org
+ Copyright 2003 Stanislav Visnovsky visnovsky@kde.org
+
+ License GPL v 2.0
+
+ * *
+ * In addition, as a special exception, the copyright holders give *
+ * permission to link the code of this program with any edition of *
+ * the Qt library by Trolltech AS, Norway (or with modified versions *
+ * of Qt that use the same license as Qt), and distribute linked *
+ * combinations including the two. You must obey the GNU General *
+ * Public License in all respects for all of the code used other than *
+ * Qt. If you modify this file, you may extend this exception to *
+ * your version of the file, but you are not obligated to do so. If *
+ * you do not wish to do so, delete this exception statement from *
+ * your version. *
+
+*/
+#include <stdlib.h>
+#include <kdebug.h>
+#include <string.h>
+#include <resources.h>
+#include "database.h"
+#include <unistd.h>
+
+#include <qfile.h>
+
+#include <ktempfile.h>
+#include <kio/netaccess.h>
+
+WordItem::WordItem (char *data, QString w)
+{
+ word = w;
+
+ count = *(uint32 *) data;
+
+ data += 4;
+//score=*(int *)data;
+ data += 4;
+
+
+ locations = (uint32 *) malloc (4 * count);
+ memcpy (locations, data, 4 * count);
+
+
+}
+
+WordItem::WordItem (QString w)
+{
+ locations = NULL;
+ count = 0;
+ word = w;
+ score = -1; // it means no references found.
+}
+
+/*
+
+WordItem::WordItem(const WordItem &wi)
+{
+ count=wi.count;
+ score=wi.score;
+ word=wi.word;
+ locations.duplicate(wi.locations);
+ locations.detach();
+}
+
+WordItem& WordItem::operator=(const WordItem & wi )
+{
+WordItem *i=new WordItem(wi);
+i->locations.detach();
+return *i;
+}
+*/
+
+bool
+WordItem::notFound ()
+{
+ return (score == -1);
+}
+
+InfoItem::InfoItem ()
+{
+ catalogName = "No catalog";
+ lastTranslator = "No translator";
+ lastFullPath = "";
+ charset = "No charset";
+ language = "No language";
+}
+
+InfoItem::InfoItem (const char *rawData, QString lang)
+{
+ const char *rd;
+ rd = rawData;
+ int len;
+ unsigned int secs;
+ // I'll change the charset handling if needed
+
+ charset = "Utf8";
+
+ catalogName = QString::fromUtf8 (rd);
+ len = strlen (rd) + 1;
+ rd += len;
+ lastTranslator = QString::fromUtf8 (rd);
+ len = strlen (rd) + 1;
+ rd += len;
+ secs = *(unsigned int *) rd;
+ revisionDate.setTime_t (secs);
+ rd += 4;
+ lastFullPath = QString::fromUtf8 (rd);
+ len = strlen (rd) + 1;
+ rd += len;
+
+
+ language = lang;
+}
+
+void
+InfoItem::rawData (char *rawData)
+{
+ char *rd;
+ rd = rawData;
+
+ strcpy (rd, catalogName.utf8 ());
+ rd += strlen (rd) + 1;
+ strcpy (rd, lastTranslator.utf8 ());
+ rd += strlen (rd) + 1;
+
+
+ //QDate Time problem!!!!!!!!!!!
+ QDateTime zeroDate;
+ zeroDate.setTime_t (0);
+ *(unsigned int *) rd = -revisionDate.secsTo (zeroDate);
+ rd += 4;
+ strcpy (rd, lastFullPath.utf8 ());
+ rd += strlen (rd) + 1;
+
+ *rd = 0; //Empty for further info
+
+}
+
+int
+InfoItem::size ()
+{
+ int _size;
+ _size = 0;
+ _size += 1; // 1 Empty field;
+ _size += 3; // Terminating \0 of next 3 strings
+ _size += 4; // Int size (date)
+ _size += strlen (catalogName.utf8 ());
+ _size += strlen (lastTranslator.utf8 ());
+ _size += strlen (lastFullPath.utf8 ());
+
+ return _size;
+}
+
+// this is a quick hack to copy a local file
+int
+copy_hack (QFile & input, QFile & output)
+{
+ if (!input.isOpen ())
+ {
+ if (!input.open (IO_ReadOnly))
+ return -1;
+ }
+
+ if (!output.isOpen ())
+ {
+ if (!output.open (IO_WriteOnly))
+ return -1;
+ }
+
+ char buffer[10240];
+ int s = 0;
+ while (!input.atEnd ())
+ {
+ s = input.readBlock (buffer, 10240);
+ output.writeBlock (buffer, s);
+ }
+ output.close ();
+ input.close ();
+ return 0;
+}
+
+DataBaseItem::DataBaseItem ()
+{
+ numTra = 0;
+ location = 0;
+}
+
+DataBaseItem::DataBaseItem (char *_key, char *_data)
+{
+
+ char *data = _data;
+ key = QString::fromUtf8 (_key);
+
+ unsigned int i, r;
+ numTra = *(uint32 *) data;
+ data += 4;
+ location = *(uint32 *) data;
+ data += 4;
+
+ for (i = 0; i < numTra; i++)
+ {
+
+ TranslationItem tr;
+ tr.numRef = *(uint32 *) data;
+
+ data += 4;
+ for (r = 0; r < tr.numRef; r++)
+ {
+
+ int ref;
+ ref = *(uint32 *) data;
+ data += 4;
+
+ tr.infoRef.append (ref);
+ }
+ tr.translation = QString::fromUtf8 ((const char *) data);
+ translations.append (tr);
+ data += strlen (data) + 1;
+
+ }
+
+}
+
+uint32
+DataBaseItem::sizeKey ()
+{
+ return strlen (key.utf8 ()) + 1;
+}
+
+uint32
+DataBaseItem::sizeData ()
+{
+ unsigned int i, _size = 4;
+ _size += numTra * 4;
+ _size += 4; // location
+ for (i = 0; i < numTra; i++)
+ {
+ _size += strlen (translations[i].translation.utf8 ()) + 1; // +1 is for \0
+ _size += translations[i].numRef * 4;
+ }
+ return _size;
+}
+
+void
+DataBaseItem::toRawKey (char *_key)
+{
+ strcpy (_key, key.utf8 ());
+}
+
+void
+DataBaseItem::toRawData (char *_data)
+{
+ char *data = _data;
+ unsigned int i, r;
+
+ *(uint32 *) data = numTra;
+
+ data += 4;
+
+ *(uint32 *) data = location;
+ data += 4;
+
+ for (i = 0; i < numTra; i++)
+ {
+ TranslationItem tr (translations[i]);
+ *(uint32 *) data = tr.numRef;
+ data += 4;
+ for (r = 0; r < tr.numRef; r++)
+ {
+ *(uint32 *) data = tr.infoRef[r]; //sub i with r
+
+ data += 4;
+ }
+ strcpy ((char *) data, tr.translation.utf8 ());
+ data += strlen (tr.translation.utf8 ()) + 1;
+ }
+
+}
+
+
+DataBaseManager::DataBaseManager (QString directory, QString lang,
+ QObject * parent, const char *name):
+QObject (parent, name)
+{
+ QString filename;
+
+ language = lang;
+ iAmOk = true;
+ basedir = directory;
+ indexDb = wordDb = infoDb = db = 0;
+ openDataBase ();
+
+
+}
+
+void
+DataBaseManager::openDataBase ()
+{
+ kdDebug () << "Opendatabase" << endl;
+ QString directory;
+ directory = basedir;
+ QString ll = "." + language;
+ if (ll == ".")
+ ll = ".NOLANG";
+
+ QString transfilename = "%1/translations%2.db";
+ transfilename = transfilename.arg (directory).arg (ll);
+
+ QString infofilename = "%1/catalogsinfo%2.db";
+ infofilename = infofilename.arg (directory).arg (ll);
+
+ QString wordsfilename = "%1/wordsindex%2.db";
+ wordsfilename = wordsfilename.arg (directory).arg (ll);
+
+ QString keysfilename = "%1/keysindex%2.db";
+ keysfilename = keysfilename.arg (directory).arg (ll);
+
+ cursor = 0;
+ int ret;
+
+ if (!db)
+ db_create (&db, 0, 0);
+
+ db_create (&infoDb, 0, 0);
+ db_create (&wordDb, 0, 0);
+ db_create (&indexDb, 0, 0);
+
+ ret = db->open (db,
+#if DB_VERSION_MINOR > 0
+ NULL,
+#endif
+ transfilename.local8Bit (), 0, DB_BTREE, 0, 0644);
+
+ if (ret == DB_OLD_VERSION)
+ {
+ kdDebug (KBABEL_SEARCH) << "Trying upgrade" << endl;
+ // try upgrade
+
+ KTempFile transFile, infoFile, keysFile, wordsFile;
+
+ // do the upgrade on the translation file
+ QFile transfilenameFile (transfilename);
+
+ if ((ret = copy_hack (transfilenameFile, *transFile.file ())) == 0)
+ {
+ ret = db->upgrade (db, transFile.name ().local8Bit (), 0);
+ }
+
+ if (ret != 0)
+ {
+ kdDebug (KBABEL_SEARCH) << "Cannot upgrade translations, " <<
+ ret << endl;
+ // cleanup
+ transFile.unlink ();
+ iAmOk = false;
+ emit cannotOpenDB (ret);
+ return;
+ }
+
+ // do the upgrade on the info file
+ QFile infofilenameFile (infofilename);
+ if ((ret = copy_hack (infofilenameFile, *infoFile.file ())) == 0)
+ {
+ ret =
+ infoDb->upgrade (infoDb, infoFile.name ().local8Bit (),
+ 0);
+ }
+
+ if (ret != 0)
+ {
+ kdDebug (KBABEL_SEARCH) << "Cannot upgrade catalogsinfo" <<
+ endl;
+ // cleanup
+ transFile.unlink ();
+ infoFile.unlink ();
+ iAmOk = false;
+ emit cannotOpenDB (ret);
+ return;
+ }
+
+ // do the upgrade on the words file
+ QFile wordfilenameFile (wordsfilename);
+ if ((ret = copy_hack (wordfilenameFile, *wordsFile.file ())) == 0)
+ {
+ ret =
+ wordDb->upgrade (wordDb, wordsFile.name ().local8Bit (),
+ 0);
+ }
+
+ if (ret != 0)
+ {
+ kdDebug (KBABEL_SEARCH) << "Cannot upgrade words" << endl;
+ // cleanup
+ transFile.unlink ();
+ infoFile.unlink ();
+ wordsFile.unlink ();
+ iAmOk = false;
+ emit cannotOpenDB (ret);
+ return;
+ }
+
+ // do the upgrade on the keys file
+ QFile keysfilenameFile (keysfilename);
+ if ((ret = copy_hack (keysfilenameFile, *keysFile.file ())) == 0)
+ {
+ ret =
+ indexDb->upgrade (indexDb, keysFile.name ().local8Bit (),
+ 0);
+ }
+
+ if (ret != 0)
+ {
+ kdDebug (KBABEL_SEARCH) << "Cannot upgrade keys" << endl;
+ // cleanup
+ transFile.unlink ();
+ infoFile.unlink ();
+ wordsFile.unlink ();
+ keysFile.unlink ();
+ iAmOk = false;
+ emit cannotOpenDB (ret);
+ return;
+ }
+
+ kdDebug (KBABEL_SEARCH) << "Files upgraded, copying" << endl;
+ // use temporary file instead
+ if (ret == 0)
+ {
+ KIO::NetAccess::del (KURL::fromPathOrURL (transfilename));
+ copy_hack (*transFile.file (), transfilenameFile);
+ transFile.unlink ();
+
+ KIO::NetAccess::del (KURL::fromPathOrURL (infofilename));
+ copy_hack (*infoFile.file (), infofilenameFile);
+ infoFile.unlink ();
+
+ KIO::NetAccess::del (KURL::fromPathOrURL (wordsfilename));
+ copy_hack (*wordsFile.file (), wordfilenameFile);
+ wordsFile.unlink ();
+
+ KIO::NetAccess::del (KURL::fromPathOrURL (keysfilename));
+ copy_hack (*keysFile.file (), keysfilenameFile);
+ keysFile.unlink ();
+
+ ret = db->open (db,
+#if DB_VERSION_MINOR > 0
+ NULL,
+#endif
+ transfilename.local8Bit (), 0, DB_BTREE, 0,
+ 0644);
+ if (ret != 0)
+ {
+ kdWarning (KBABEL_SEARCH) <<
+ "transFilename database can't be opened." << endl;
+ kdWarning (KBABEL_SEARCH) <<
+ "Please, report this incident and how to reproduce it to kbabel@kde.org."
+ << endl;
+ iAmOk = false;
+ emit cannotOpenDB (ret);
+ return;
+ }
+
+ }
+ kdDebug (KBABEL_SEARCH) << "Upgrade done OK" << endl;
+ }
+
+// Open catalogs information database
+
+
+
+ ret = infoDb->open (infoDb,
+#if DB_VERSION_MINOR > 0
+ NULL,
+#endif
+ infofilename.local8Bit (), 0, DB_RECNO, 0, 0644);
+ if (ret != 0)
+ {
+ iAmOk = false;
+ emit cannotOpenDB (ret);
+ //Process error here.
+ }
+ else
+ loadInfo ();
+
+
+
+// Words index database
+
+ ret = wordDb->open (wordDb,
+#if DB_VERSION_MINOR > 0
+ NULL,
+#endif
+ wordsfilename.local8Bit (), 0, DB_BTREE, 0, 0644);
+ if (ret != 0)
+ {
+ iAmOk = false;
+ emit cannotOpenDB (ret);
+ //Process error here.
+ }
+
+//Index of keys.
+
+ ret = indexDb->open (indexDb,
+#if DB_VERSION_MINOR > 0
+ NULL,
+#endif
+ keysfilename.local8Bit (), 0, DB_RECNO, 0, 0644);
+ if (ret != 0)
+ {
+ iAmOk = false;
+ emit cannotOpenDB (ret);
+ //Process error here.
+ }
+
+
+}
+
+void
+DataBaseManager::closeDataBase ()
+{
+ if (iAmOk)
+ {
+ db->sync (db, 0);
+ db->close (db, 0);
+
+ infoDb->sync (infoDb, 0);
+ infoDb->close (infoDb, 0);
+
+ wordDb->sync (wordDb, 0);
+ wordDb->close (wordDb, 0);
+
+ indexDb->sync (indexDb, 0);
+ indexDb->close (indexDb, 0);
+
+ // can not be opened again
+ indexDb = wordDb = infoDb = db = 0;
+
+ }
+
+}
+
+
+// I'm not sure this is a good function !!!
+
+void
+DataBaseManager::sync ()
+{
+// if(iAmOk)
+// {
+// db->sync(db,0);
+// infoDb->sync(infoDb,0);
+// cursor=0;
+// }
+
+ // closeDataBase();
+// openDataBase();
+
+ db->sync (db, 0);
+ infoDb->sync (infoDb, 0);
+ wordDb->sync (wordDb, 0);
+ indexDb->sync (indexDb, 0);
+ loadInfo ();
+}
+
+
+DataBaseManager::~DataBaseManager ()
+{
+ closeDataBase ();
+}
+
+int
+DataBaseManager::putItem (DataBaseItem * item, bool ow)
+{
+ DBT key, data;
+
+ memset (&key, 0, sizeof (DBT));
+ memset (&data, 0, sizeof (DBT));
+
+ bool ret;
+
+ uint32 loc = 0;
+ if (item->location == 0)
+ {
+ loc = item->location = appendKey (item->key);
+// kdDebug(0) << "New key " << item->location << endl;
+ }
+ key.size = item->sizeKey ();
+ data.size = item->sizeData ();
+
+ key.data = malloc (key.size);
+ data.data = malloc (data.size);
+
+
+ item->toRawKey ((char *) key.data);
+ item->toRawData ((char *) data.data);
+
+
+ if (ow)
+ ret = db->put (db, 0, &key, &data, 0);
+ else
+ ret = db->put (db, 0, &key, &data, DB_NOOVERWRITE);
+
+//check ret
+
+ if (loc != 0) //I'm new!
+ {
+ uint32 location = loc;
+
+ QValueList < QString > wlist;
+
+ wlist = wordsIn (item->key);
+
+ QValueList < QString >::Iterator wlistit;
+
+ for (wlistit = wlist.begin (); wlistit != wlist.end (); ++wlistit)
+ {
+ addLocation (*wlistit, location);
+ }
+
+ }
+
+ free (key.data);
+ free (data.data); //READ DOCU !!!!
+
+ return ret;
+
+}
+
+DataBaseItem
+DataBaseManager::getItem (QString key)
+{
+ if (!iAmOk)
+ return DataBaseItem ();
+
+
+ DBT _key, data;
+
+ memset (&_key, 0, sizeof (DBT));
+
+ memset (&data, 0, sizeof (DBT));
+
+ int len = strlen (key.utf8 ());
+ _key.data = malloc (len + 1);
+ _key.size = len + 1;
+ strcpy ((char *) _key.data, key.utf8 ());
+
+
+ int ret;
+ ret = db->get (db, 0, &_key, &data, 0);
+
+ if (ret != 0)
+ {
+ free (_key.data);
+ return DataBaseItem (); //return an empty database item
+ }
+
+ DataBaseItem returnItem =
+ DataBaseItem ((char *) _key.data, (char *) data.data);
+
+ free (_key.data);
+ return returnItem;
+
+}
+
+
+
+
+DataBaseItem
+DataBaseManager::cursorGet (uint32 flags)
+{
+
+ if (!iAmOk)
+ return DataBaseItem ();
+ int re;
+ DBT key, data;
+
+ memset (&key, 0, sizeof (DBT));
+
+ memset (&data, 0, sizeof (DBT));
+
+ if (cursor == 0)
+ re = db->cursor (db, 0, &cursor, 0);
+
+ int ret;
+ if ((ret = cursor->c_get (cursor, &key, &data, flags)) == 0)
+ {
+ return DataBaseItem ((char *) key.data, (char *) data.data);
+ }
+ else
+ {
+ kdDebug (KBABEL_SEARCH) << QString ("...cursor getting...%1").
+ arg (ret) << endl;
+
+ return DataBaseItem ();
+ }
+}
+
+
+DataBaseItem
+DataBaseManager::firstItem ()
+{
+ return cursorGet (DB_FIRST);
+}
+
+DataBaseItem
+DataBaseManager::currentItem ()
+{
+ return cursorGet (DB_CURRENT);
+}
+
+
+DataBaseItem
+DataBaseManager::nextItem ()
+{
+ return cursorGet (DB_NEXT);
+}
+
+
+bool
+DataBaseManager::isOk ()
+{
+ return iAmOk;
+}
+
+int
+DataBaseManager::count ()
+{
+ DB_BTREE_STAT *dstat = 0;
+#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3
+ db->stat (db, NULL, &dstat, DB_FAST_STAT);
+#else
+ db->stat (db, &dstat, DB_FAST_STAT);
+#endif
+ int ret = dstat->bt_nkeys;
+ free (dstat);
+
+ return ret;
+}
+
+int
+DataBaseManager::current ()
+{
+// THIS FUNCTION SEEM TO NOT WORK (not used)
+ if (!iAmOk)
+ return 0;
+
+ DBT key, data;
+ memset (&key, 0, sizeof (DBT));
+ memset (&data, 0, sizeof (DBT));
+
+ if (cursor != 0)
+ db->cursor (db, 0, &cursor, 0);
+ cursor->c_get (cursor, &key, &data, DB_GET_RECNO);
+ return *(uint32 *) (data.data);
+
+}
+
+int
+DataBaseManager::createDataBase (QString directory,
+ QString language, int mode)
+{
+ QString filename;
+ QString ll = "." + language;
+ if (ll == ".")
+ ll = ".NOLANG";
+ filename = "%1/translations%2.db";
+ filename = filename.arg (directory).arg (ll);
+
+ rename (filename.local8Bit (), filename.local8Bit () + ",old");
+
+//kdDebug(0) << QString("Creating %1").arg(filename) << endl;
+
+ iAmOk = true;
+
+ int ret;
+
+ if (!db)
+ {
+ if (db_create (&db, 0, 0) != 0)
+ {
+ kdDebug() << "db_create db failed" << endl;
+ iAmOk = false;
+ return false;
+ }
+ }
+
+ db->set_flags (db, DB_RECNUM);
+ ret = db->open (db,
+#if DB_VERSION_MINOR > 0
+ NULL,
+#endif
+ filename.local8Bit (), 0, DB_BTREE, DB_CREATE | DB_EXCL,
+ mode);
+ if (ret != 0)
+ {
+ kdDebug() << "db->open " << filename << " " << mode << " failed" << endl;
+ iAmOk = false;
+ }
+
+
+ filename = "%1/catalogsinfo%2.db";
+ filename = filename.arg (directory).arg (ll);
+ rename (filename.local8Bit (), filename.local8Bit () + ",old");
+
+ db_create (&infoDb, 0, 0);
+ ret = infoDb->open (infoDb,
+#if DB_VERSION_MINOR > 0
+ NULL,
+#endif
+ filename.local8Bit (), 0, DB_RECNO, DB_CREATE, mode);
+ if (ret != 0)
+ iAmOk = false;
+
+
+
+ filename = "%1/wordsindex%2.db";
+ filename = filename.arg (directory).arg (ll);
+ rename (filename.local8Bit (), filename.local8Bit () + ",old");
+
+ db_create (&wordDb, 0, 0);
+ ret = wordDb->open (wordDb,
+#if DB_VERSION_MINOR > 0
+ NULL,
+#endif
+ filename.local8Bit (), 0, DB_BTREE, DB_CREATE, mode);
+ if (ret != 0)
+ iAmOk = false;
+
+
+
+ filename = "%1/keysindex%2.db";
+ filename = filename.arg (directory).arg (ll);
+ rename (filename.local8Bit (), filename.local8Bit () + ",old");
+
+ db_create (&indexDb, 0, 0);
+ ret = indexDb->open (indexDb,
+#if DB_VERSION_MINOR > 0
+ NULL,
+#endif
+ filename.local8Bit (), 0, DB_RECNO, DB_CREATE, mode);
+ if (ret != 0)
+ iAmOk = false;
+
+
+
+ if (iAmOk)
+ loadInfo ();
+ else
+ kdDebug (KBABEL_SEARCH) << QString ("I am NOT ok : %1").
+ arg (ret) << endl;
+
+//THIS IS WRONG, rewrite the error handling.
+ return iAmOk;
+
+}
+
+InfoItem
+DataBaseManager::getCatalogInfo (int n)
+{
+
+ DBT key;
+ DBT data;
+
+ memset (&key, 0, sizeof (DBT));
+ memset (&data, 0, sizeof (DBT));
+
+ key.data = &n;
+ key.size = 4;
+
+//Check for errors
+ int ret = infoDb->get (infoDb, 0, &key, &data, 0); //DB_SET_RECNO);
+
+ if (ret)
+ {
+ return InfoItem ();
+ }
+
+// kdDebug(0) << QString("Trad %1").arg(ret) << endl;
+
+ InfoItem it ((char *) data.data, language);
+//free(data.data); // Read docu for this!!!!
+
+ return it;
+
+}
+
+int
+DataBaseManager::addCatalogInfo (InfoItem * catInfo, int cat = -1)
+{
+ DBT data;
+ DBT key;
+
+ // clean up data
+ memset (&data, 0, sizeof (DBT));
+ memset (&key, 0, sizeof (DBT));
+
+ int ret = 0, err;
+ if (cat >= 0)
+ ret = cat;
+ key.size = 4;
+ key.data = &ret;
+ data.size = catInfo->size ();
+ data.data = malloc (data.size);
+
+ catInfo->rawData ((char *) data.data);
+
+ // store the catalog data into database
+ if (cat >= 0)
+ err = infoDb->put (infoDb, 0, &key, &data, 0);
+ else
+ err = infoDb->put (infoDb, 0, &key, &data, DB_APPEND);
+
+
+ ret = *(int *) key.data;
+
+ // Append to the list of catalogInfo
+ info.append (*catInfo);
+
+ // cleanup unneeded data memory
+ free (data.data);
+ return ret;
+}
+
+int
+DataBaseManager::searchCatalogInfo (QString location)
+{
+ int n = 0;
+ QValueList < InfoItem >::Iterator it;
+ for (it = info.begin (); it != info.end (); ++it)
+ {
+ n++;
+ if ((*it).catalogName == location)
+ return n;
+ }
+ return -1;
+}
+
+bool
+DataBaseManager::putCatalogInfo (int refnum, InfoItem * catInfo)
+{
+ DBT data;
+ DBT key;
+
+ memset (&key, 0, sizeof (DBT));
+ memset (&data, 0, sizeof (DBT));
+
+ int ret;
+ key.size = 4;
+ key.data = &refnum;
+
+ data.size = catInfo->size ();
+ data.data = malloc (data.size);
+ catInfo->rawData ((char *) data.data);
+
+ ret = infoDb->put (infoDb, 0, &key, &data, 0);
+
+ free (data.data);
+
+ return (ret == 0);
+}
+
+void
+DataBaseManager::loadInfo ()
+{
+ int nrec;
+ DB_BTREE_STAT *stat;
+// memset(&stat,0,sizeof(DB_BTREE_STAT));
+#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3
+ if (infoDb->stat (infoDb, NULL, &stat, DB_FAST_STAT))
+ fprintf (stderr, "Cannot stat\n");
+#else
+ if (infoDb->stat (infoDb, &stat, DB_FAST_STAT))
+ fprintf (stderr, "Cannot stat\n");
+#endif
+ nrec = stat->bt_nkeys;
+ free (stat);
+
+ info.clear ();
+ for (int i = 1; i <= nrec; i++) // I think DB2 Recno are 1 based.
+ {
+ info.append (getCatalogInfo (i));
+ }
+
+}
+
+
+QValueList < QString > DataBaseManager::wordsIn (QString string)
+{
+ QString
+ a;
+ QValueList < QString > words;
+ int
+ i,
+ l;
+
+ a = string.simplifyWhiteSpace ();
+ a = a.stripWhiteSpace ();
+ a = a.lower ();
+ l = a.length ();
+
+ int
+ c = 0;
+ //words.setAutoDelete(true); //Not sure... check if it is en.
+ QString
+ m;
+ for (i = 0; i < l; i++)
+ if (a[i].isLetterOrNumber ())
+ {
+ m += a[i];
+ }
+ else if (a[i].isSpace ())
+ {
+ words.append (m);
+ c++; // C++ ;-)
+ m = "";
+ }
+ words.append (m);
+
+ return words;
+}
+
+
+
+WordItem
+DataBaseManager::getWordLocations (QString word)
+{
+
+ QString keystring = word.lower ();
+
+ DBT key;
+ DBT data;
+
+ char *keydata;
+
+ int intlen = strlen (keystring.utf8 ());
+
+ keydata = (char *) malloc (intlen + 1);
+ strcpy (keydata, keystring.utf8 ());
+
+ memset (&key, 0, sizeof (DBT));
+ memset (&data, 0, sizeof (DBT));
+
+ key.data = keydata;
+ key.size = intlen + 1;
+
+//Check for errors
+ int ret = wordDb->get (wordDb, 0, &key, &data, 0); //DB_SET_RECNO);
+//MAYBE THIS WORD IS NO WHERE!!
+ if (ret)
+ {
+ free (keydata);
+ return WordItem (keystring);
+ }
+
+
+ WordItem it ((char *) data.data, keystring);
+
+ free (keydata);
+
+
+// kdDebug(0) << ((uint32 *)it.locations.data())[0] << endl;
+
+ return it;
+
+}
+
+
+bool
+DataBaseManager::addLocation (QString word, unsigned int location)
+{
+
+ QString keystring = word.lower ();
+
+
+ DBT key;
+ DBT data;
+
+ char *keydata;
+ char *newdata;
+
+ int intlen = strlen (keystring.utf8 ());
+
+ keydata = (char *) malloc (intlen + 1);
+ strcpy (keydata, keystring.utf8 ());
+
+ memset (&key, 0, sizeof (DBT));
+ memset (&data, 0, sizeof (DBT));
+
+ key.data = keydata;
+ key.size = intlen + 1;
+
+ strcpy ((char *) key.data, keystring.utf8 ());
+
+//Check for errors
+ int ret = wordDb->get (wordDb, 0, &key, &data, 0); //DB_SET_RECNO);
+
+//Check if you get something or not
+ if (ret == 0) // CHANGE IT!!!!! if found something
+ {
+ uint32 *d;
+ d = (uint32 *) data.data;
+ uint32 num = d[0];
+ uint32 loc = 0; //Position from 0 to num-1
+ int totalrecord = count ();
+ uint32 step = 1;
+
+ int antibounce = 0;
+//d+=4;
+//int score=d[1];
+//d+=4;
+ bool forward, end = false;
+
+ d[1] = 0; //Before the begin...
+
+ d += 2; //1 uint32!
+
+
+//Try to guess...
+ loc = location * num / totalrecord + 1;
+ if (loc >= num)
+ loc = num - 1;
+
+
+
+
+//Continue if next is smaller or if previous is greater
+//before the while check if it is ok
+ if (loc == 0)
+ {
+ if (d[loc] > location)
+ end = true;
+ else
+ loc = 1;
+ }
+
+ if ((loc == num) && !end)
+ {
+ if (d[loc - 1] < location)
+ end = true;
+ else
+ loc = num - 1;
+ }
+
+
+
+ while ((!end) && ((forward = (d[loc]) < location)
+ || ((loc > 0) && (d[loc - 1] > location))))
+ {
+
+ antibounce++;
+ //calculate step or use antibounce
+ if (abs ((int) d[loc] - (int) location) < 50
+ || antibounce > 100)
+ step = 1; //Go linear...
+ else
+ {
+ step =
+ (abs (d[loc] - location) * num) / totalrecord + 1;
+
+ }
+
+ kdDebug (KBABEL_SEARCH) << "Insert:" << location <<
+ " We are at: " << loc << " i.e. " << d[loc] << " Step:"
+ << step << endl;
+ if (loc > 0)
+ {
+ if (forward)
+ kdDebug (KBABEL_SEARCH) << "Go " << "forward" <<
+ " prev is " << d[loc - 1] << endl;
+ else
+ kdDebug (KBABEL_SEARCH) << "Go " << "backward" <<
+ " prev is " << d[loc - 1] << endl;
+ }
+
+ if (forward)
+ {
+ if (loc + step < num)
+ loc += step; // Go forward
+ else
+ loc = num; // Go to num
+ }
+ else
+ {
+ if (loc > step)
+ loc -= step; //Go backward
+ else
+ loc = 0; // Go to 0
+ }
+
+ //Now check if I am in the right place [THIS IS NOT NECESSARY]
+
+ //check if loc and loc -1 are well defined 1<loc<num-1
+ if (loc > num)
+ loc = num; //Must not happen, idem
+
+ if (loc == 0)
+ {
+ if (d[loc] > location)
+ end = true;
+ else
+ loc = 1;
+ }
+
+ if ((loc == num) && !end)
+ {
+ if (d[loc - 1] < location)
+ end = true;
+ else
+ loc = num - 1;
+ }
+
+ }
+
+ if (loc == num)
+ kdDebug (KBABEL_SEARCH) << "END" << endl;
+ if (loc == 0)
+ kdDebug (KBABEL_SEARCH) << "BEGIN" << endl;
+
+ if (loc > 0)
+ kdDebug (KBABEL_SEARCH) << location << " inserted between " <<
+ d[loc - 1] << " and " << d[loc] << endl;
+
+ if ((loc < num && location == d[loc]) || (loc > 0 && location == d[loc - 1])) //What about word repetition
+ {
+ free (keydata);
+ return true; //Why true ??
+ }
+
+
+
+//Now insert and put back in the database!
+ newdata = (char *) malloc (4 * (num + 3)); //uint32*(num+score+1..NUM+new)
+ memcpy (newdata, data.data, 4 + 4 + 4 * loc);
+ char *secondpart = (char *) data.data;
+ secondpart += 4 * (loc + 2);
+ memcpy ((newdata + 4 * (loc + 3)), secondpart, (num - loc) * 4);
+ uint32 *intdata = (uint32 *) newdata;
+ intdata[0] = num + 1;
+ //ADD HERE code to recalc score
+ intdata[loc + 2] = location;
+
+//ok send it to database!
+ memset (&data, 0, sizeof (DBT));
+
+ data.data = newdata;
+ data.size = 4 * (3 + num);
+ } //found sounthing
+ else
+ { //found nothing
+ newdata = (char *) malloc (4 * 3);
+ uint32 *intdata = (uint32 *) newdata;
+ intdata[0] = 1;
+ intdata[1] = 1;
+ intdata[2] = location;
+ memset (&data, 0, sizeof (DBT));
+ data.data = newdata;
+ data.size = 4 * 3;
+ }
+
+ memset (&key, 0, sizeof (DBT));
+//memset(&data,0,sizeof(DBT));
+
+ key.data = keydata;
+ key.size = intlen + 1;
+
+ ret = wordDb->put (wordDb, 0, &key, &data, 0); //DB_SET_RECNO);
+
+
+ free (newdata);
+ free (keydata);
+//return it;
+
+ return true;
+}
+
+
+bool
+DataBaseManager::removeLocation (QString /*word */ , int /*location */ )
+{
+
+//#warning TODO: REMOVE LOCATION
+ return true;
+
+}
+
+uint32
+DataBaseManager::appendKey (QString _key)
+{
+
+ DBT key;
+ DBT data;
+
+ memset (&key, 0, sizeof (DBT));
+ memset (&data, 0, sizeof (DBT));
+
+
+ uint32 ret = 0, err;
+ key.size = 4;
+ key.data = &ret;
+
+ data.size = strlen (_key.utf8 ()) + 1;
+ data.data = malloc (data.size);
+
+ strcpy ((char *) data.data, _key.utf8 ());
+
+ err = indexDb->put (indexDb, 0, &key, &data, DB_APPEND);
+
+ if (err)
+ ret = 0;
+ else
+ ret = *(uint32 *) key.data;
+
+//kdDebug(0) << QString("Append result %1,err = %1").arg(ret).arg(err) << endl;
+
+
+ free (data.data);
+
+ return ret;
+
+}
+
+QString
+DataBaseManager::getKey (uint32 n)
+{
+
+ DBT key;
+ DBT data;
+
+ memset (&key, 0, sizeof (DBT));
+ memset (&data, 0, sizeof (DBT));
+
+ key.data = &n;
+ key.size = 4;
+
+//Check for errors
+ int ret = indexDb->get (indexDb, 0, &key, &data, 0); //DB_SET_RECNO);
+ if (ret)
+ return QString::null;
+
+ return QString::fromUtf8 ((char *) data.data);
+
+// kdDebug(0) << QString("Trad %1").arg(ret) << endl;
+
+}
+
+int
+DataBaseManager::catalogRef (QString location, QString author, QString path)
+{
+ InfoItem cinfo;
+ int cat, catnum;
+ cat = searchCatalogInfo (location);
+
+ if (cat == -1) //Not exist
+ {
+ cinfo.catalogName = location;
+ cinfo.lastTranslator = author;
+ cinfo.lastFullPath = path;
+ //TO DO:
+ // //Add date info
+
+ kdDebug (0) << "New catalog " << endl;
+ catnum = addCatalogInfo (&cinfo);
+ //sync();
+ kdDebug (0) << "Ref " << catnum << endl;
+ }
+ else
+ {
+ cinfo = getCatalogInfo (cat);
+ //Update date.
+
+ //last path must be updated
+ cinfo.lastFullPath = path;
+ kdDebug (0) << "New full path " << path << endl;
+ kdDebug (0) << "Ref " << cat << endl;
+
+ catnum = addCatalogInfo (&cinfo, cat);
+ kdDebug (0) << " must be equal to " << catnum << endl;
+
+ catnum = cat;
+ }
+
+ return catnum;
+}
+
+int
+DataBaseManager::putNewTranslation (QString key, QString tran, int catalog,
+ bool ow)
+{
+ int catnum = catalog;
+ int count = 0;
+ QString msgid = key;
+ DataBaseItem dbit = getItem (msgid);
+
+ if (dbit.numTra == 0) //Not found
+ {
+ dbit.numTra += 1;
+
+ // use local variable, dbit.translations is QValueList and
+ // will create own copy
+ TranslationItem tra;
+ tra.numRef = 1;
+ tra.translation = tran;
+ tra.infoRef.append (catnum);
+ dbit.translations.append (tra);
+ dbit.key = key;
+
+ //Check ret value
+ count++;
+
+ int aa = putItem (&dbit);
+ if (aa)
+ kdDebug (0) << QString ("-----------put code ") << aa << endl;
+ }
+ else
+ {
+ // key exists
+
+ QString msgstr = tran;
+ bool found_catalog_info = false, foundTr = false, isThisOne = false;
+
+ QValueList < TranslationItem >::Iterator ittr;
+ bool rem = false;
+
+ // check all translations in the list
+ for (ittr = dbit.translations.begin ();
+ ittr != dbit.translations.end (); rem ? ittr : ++ittr)
+ {
+ rem = false;
+ found_catalog_info = false;
+
+ // is the translation one we should put there?
+ isThisOne = (*ittr).translation == msgstr;
+
+ // is there the catnum we are looking for?
+ if ((*ittr).infoRef.find (catnum) != (*ittr).infoRef.end ())
+ {
+ found_catalog_info = true;
+ if (ow && !isThisOne)
+ {
+ // I'll look for my catalog reference to del old
+ kdDebug (0) << "Removing the old translation " << endl;
+ (*ittr).numRef -= 1;
+ (*ittr).infoRef.remove (catnum);
+ if ((*ittr).numRef == 0)
+ {
+ dbit.numTra -= 1;
+ // point the iterator to the next valid item
+ ittr = dbit.translations.remove (ittr);
+ rem = true;
+ }
+ }
+ }
+
+ if (isThisOne)
+ {
+ if (!found_catalog_info)
+ {
+ //There are no reference of this catalog for this translation => add it
+ (*ittr).infoRef.append (catnum);
+ (*ittr).numRef += 1;
+ }
+ foundTr = true; // Ok, we found this translation, no need to add it.
+ }
+ }
+
+ if (!foundTr) //This translation is new => Add it !
+ {
+ count++;
+ TranslationItem tra;
+ tra.numRef = 1;
+ tra.translation = msgstr;
+ tra.infoRef.append (catnum);
+
+ dbit.translations.append (tra);
+ dbit.numTra += 1;
+ }
+
+ //put the new item in database overwriting the old one.
+ //Check ret value
+ int aa = putItem (&dbit, true);
+ if (aa)
+ kdDebug (0) << QString ("-----------put code ") << aa << endl;
+
+ }
+ return count;
+}
+
+
+void
+DataBaseManager::rebuildIndexes ()
+{
+// uint32 loc;
+#if 0
+//Reset the 2 databases here.
+
+ while (0 /*browse keys here */ )
+ {
+ loc = item->location = appendKey (item->key);
+
+ uint32 location = loc;
+
+ QValueList < QString > wlist;
+
+ wlist = wordsIn (item->key);
+
+ QValueList < QString >::Iterator wlistit;
+
+ for (wlistit = wlist.begin (); wlistit != wlist.end (); ++wlistit)
+ {
+ addLocation (*wlistit, location);
+ }
+
+ }
+#endif
+}
+
+
+
+#include "database.moc"
diff --git a/kbabel/kbabeldict/modules/dbsearchengine/database.h b/kbabel/kbabeldict/modules/dbsearchengine/database.h
new file mode 100644
index 00000000..bf4767df
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine/database.h
@@ -0,0 +1,329 @@
+/***************************************************************************
+ database.h -
+ -------------------
+ begin : Fri Sep 8 2000
+ copyright : (C) 2000 by Andrea Rizzi
+ email : rizzi@kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ * *
+ * In addition, as a special exception, the copyright holders give *
+ * permission to link the code of this program with any edition of *
+ * the Qt library by Trolltech AS, Norway (or with modified versions *
+ * of Qt that use the same license as Qt), and distribute linked *
+ * combinations including the two. You must obey the GNU General *
+ * Public License in all respects for all of the code used other than *
+ * Qt. If you modify this file, you may extend this exception to *
+ * your version of the file, but you are not obligated to do so. If *
+ * you do not wish to do so, delete this exception statement from *
+ * your version. *
+ ***************************************************************************/
+/*
+ Translation search engine
+
+
+ Copyright 2000
+ Andrea Rizzi rizzi@kde.org
+
+*/
+
+
+#ifndef _DATABASE_H_
+#define _DATABASE_H_
+
+#include <config.h>
+
+#ifdef USE_DB_H_PATH
+#include USE_DB_H_PATH
+#else
+#ifdef HAVE_DB4_DB_H
+#include <db4/db.h>
+#else
+#include <db.h>
+#endif
+#endif
+
+#define uint32 u_int32_t
+
+#include <qvaluelist.h>
+#include <qptrlist.h>
+#include <qstring.h>
+#include <qobject.h>
+#include <qdatetime.h>
+#include <qcstring.h> //bytearray
+
+
+class WordItem // Returned by getWordLocations
+{
+ public:
+
+ WordItem(char *data,QString w);
+ WordItem(QString w);
+ //WordItem(const WordItem &wi);
+ //WordItem& operator=(const WordItem & wi );
+
+ //The word (key in database)
+ QString word;
+ //Sorted locations
+ //QByteArray locations; //too many problems with this..
+ //NOTE:
+ //This is allocated only if you call WordItem(char *data,QString w);
+ //YOU MUST FREE IT when you do not need it anymore
+ //No destructor will do it !!!
+
+ uint32 *locations;
+
+
+ uint32 count;
+ //Is this word common ?
+ int score;
+
+ bool notFound();
+};
+
+
+class InfoItem
+{
+ public:
+
+ //Create the NO INFO item
+ InfoItem();
+
+ // Create an info item from raw data
+ InfoItem(const char *rawData,QString lang);
+
+ QString catalogName;
+ QString lastFullPath;
+
+ QString lastTranslator;
+ QDateTime revisionDate;
+ QString charset;
+ QString language;
+
+
+ int size();
+ void rawData(char *);
+
+};
+
+class TranslationItem
+{
+ public:
+ QString translation;
+ QValueList<int> infoRef;
+ uint32 numRef;
+
+};
+
+class DataBaseItem
+{
+ public:
+ /*
+ Create empty class;
+ */
+ DataBaseItem();
+
+ /*
+ Create a DataBaseItem from raw data
+ */
+ DataBaseItem(char *_key,char *_data);
+
+ /*
+ return the size (in raw data) of this item.
+ */
+ uint32 sizeData();
+ uint32 sizeKey();
+
+ bool isNull() { return (numTra==0); }
+
+ /*
+ You MUST allocate data of sizeData() byte.
+ */
+ void toRawData(char *_data);
+ void toRawKey(char *_key);
+
+ QString key;
+ QValueList<TranslationItem> translations;
+ uint32 numTra;
+ uint32 location;
+};
+
+class DataBaseManager : public QObject
+{
+
+ Q_OBJECT
+
+ public:
+ /*
+ Main constructor.
+ directory is the name of the directory where the database structre
+ is stored.
+
+ DIRECTORY/translations.$LANG.db The trasnaltion archive
+ DIRECTORY/catalogsinfo.$LANG.db Info about catalogs
+
+ //Not yet implemented
+ DIRECTORY/wordsindex.$LANG.db Index of words
+
+
+ */
+
+ DataBaseManager(QString directory,QString lang,QObject *parent=0,const char *name=0);
+ ~DataBaseManager();
+ /*
+ Create a new databse structure.
+
+ */
+ int createDataBase(QString directory,QString language,int mode=0664);
+
+
+
+
+ /*
+ Put a DataBaseItem into the database.
+
+ if ow==false enter the new DataBaseItem only
+ if the key of DataBaseItem does not previously exist
+
+ It also update the wordIndex.
+
+ */
+
+ int putItem(DataBaseItem *item,bool ow=false);
+
+ DataBaseItem getItem(QString key);
+
+ /*
+ @return the first entry in the database.
+ */
+
+ DataBaseItem firstItem();
+
+ /*
+ @return the current entry of the database.
+ */
+
+ DataBaseItem currentItem();
+
+ /*
+ @return the next entry in the database.
+ */
+
+ DataBaseItem nextItem();
+
+
+ /*
+ * Add a new translation to the database
+ * catalog is a valid catalog refnum (use catalogRef to get one)
+ * if ow is true a translation of a key coming from catalog is
+ * overwritten if you provide a new translation
+ */
+
+ int putNewTranslation(QString key,QString tran,int catalog,bool ow=true);
+
+ /*
+ @return info about catalog n
+ */
+
+ InfoItem getCatalogInfo(int n);
+
+ /*
+ Add an entry to catalogsinfo database and
+ @return a refnum for the new added item
+ */
+
+ int addCatalogInfo(InfoItem *catInfo,int);
+
+ /*
+ Search an Item with the same "location" and
+ @return its refnum.
+ */
+
+ int searchCatalogInfo(QString location);
+
+ /* Get a catalog info for location,
+ * if it doesn't exist it will create one.
+ * @return the refnum
+ */
+
+ int catalogRef(QString location,QString author,QString path);
+
+ /*
+ Put at refnum the catInfo
+ @return true if everything is OK
+ */
+
+ bool putCatalogInfo(int refnum, InfoItem *catInfo);
+
+ /*
+ Get word info
+ */
+ WordItem getWordLocations(QString word);
+
+ /*
+ Add a location for word
+ */
+ bool addLocation(QString word, unsigned int location);
+
+ /*
+ Remove location for word
+ */
+ bool removeLocation(QString word, int location);
+
+
+ /*
+ * Rebuild location and word indexes
+ */
+ void rebuildIndexes();
+
+ uint32 appendKey(class QString);
+
+ QString getKey(uint32 n);
+
+ /*
+ Load the catalogs info.
+ */
+ void loadInfo();
+
+
+ void sync();
+
+ bool isOk();
+ int count();
+ int current();
+
+ void openDataBase();
+ void closeDataBase();
+
+ static QValueList<QString> wordsIn(QString string);
+
+ signals:
+
+ void cannotOpenDB(int);
+
+
+ protected:
+ DataBaseItem cursorGet(uint32 flags);
+
+ QString language;
+ QString basedir;
+ QValueList<InfoItem> info;
+
+ DB *db,*infoDb,*wordDb,*indexDb;
+ DBC *cursor;
+ bool iAmOk;
+ bool indexOk; //Database could word without word index
+};
+
+
+
+
+
+#endif
diff --git a/kbabel/kbabeldict/modules/dbsearchengine/dbscan.cpp b/kbabel/kbabeldict/modules/dbsearchengine/dbscan.cpp
new file mode 100644
index 00000000..87b39e61
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine/dbscan.cpp
@@ -0,0 +1,197 @@
+/***************************************************************************
+ dbscan.cpp - Scan for po files to add in the DB
+ -------------------
+ begin : Fri Sep 8 2000
+ copyright : (C) 2000 by Andrea Rizzi
+ email : rizzi@kde.org
+ ***************************************************************************/
+
+/*
+ Translation search engine
+
+
+ Copyright 2000
+ Andrea Rizzi rizzi@kde.org
+
+ License GPL v 2.0
+
+ * *
+ * In addition, as a special exception, the copyright holders give *
+ * permission to link the code of this program with any edition of *
+ * the Qt library by Trolltech AS, Norway (or with modified versions *
+ * of Qt that use the same license as Qt), and distribute linked *
+ * combinations including the two. You must obey the GNU General *
+ * Public License in all respects for all of the code used other than *
+ * Qt. If you modify this file, you may extend this exception to *
+ * your version of the file, but you are not obligated to do so. If *
+ * you do not wish to do so, delete this exception statement from *
+ * your version. *
+
+*/
+#include "dbscan.h"
+
+#include <qdir.h>
+#include <qfile.h>
+#include <kapplication.h>
+#include <kurl.h>
+#include <kdebug.h>
+
+using namespace KBabel;
+
+PoScanner::PoScanner(DataBaseManager *dbm,
+ QObject *parent,const char *name):QObject(parent,name)
+{
+dm=dbm;
+removeOldCatalogTranslation=false; //Check if this flag do something.
+count=0;
+}
+
+bool PoScanner::scanPattern(QString pathName,QString pattern,bool rec)
+{
+int tot;
+
+//Only one progress bar!!
+bool pb=false;
+static bool called=false;
+if (!called)
+{ pb=true; count=0;}
+called=true;
+
+kdDebug(0) << QString("cat: %1, %2").arg(pathName).arg(pattern) << endl;
+
+if(pb)
+{emit patternStarted();
+emit patternProgress(0);
+}
+ QDir d(pathName,pattern);
+ d.setMatchAllDirs(true);
+ const QFileInfoList* files = d.entryInfoList();
+ tot=files->count();
+ QPtrListIterator<QFileInfo> it(*files);
+kdDebug(0) << tot << endl;
+ for ( int i=0; i<tot; i++ )
+ {
+ if ((*it)->isDir())
+ {
+ if(rec)
+ {
+ kdDebug(0) << d[i] << endl;
+ if(d[i]!="." && d[i]!="..")
+ scanPattern(pathName+"/"+d[i],pattern,true);
+ }
+ } else
+ {
+ kdDebug(0) << d[i] << endl;
+ scanFile(pathName+"/"+d[i]);
+ }
+
+ if(pb)
+
+ emit patternProgress(100*i/tot);
+
+ //printf( "%s\n", d[i] );
+
+ ++it;
+ }
+
+
+
+if(pb)
+emit patternProgress(100);
+
+
+if(pb)
+emit patternFinished();
+if(pb){called=false;count=0;}
+
+return true;
+}
+
+
+
+
+bool PoScanner::scanFile(QString fileName)
+{
+
+
+emit fileStarted();
+
+InfoItem cinfo;
+Catalog * catalog=new Catalog(this,"ScanPoCatalog");
+
+
+QString location=fileName.right(fileName.length()-fileName.findRev("/")-1);
+connect(catalog,SIGNAL(signalProgress(int)),this,SIGNAL(fileLoading(int)));
+emit filename(location);
+emit fileProgress(0);
+emit fileLoading(0);
+
+KURL u(fileName);
+
+ConversionStatus rr=catalog->openURL(u);
+if(rr != OK && rr !=RECOVERED_PARSE_ERROR )
+{
+ delete catalog;
+ return false;
+}
+emit fileLoading(100);
+
+QString author;
+if(rr != HEADER_ERROR)
+ author=catalog->lastTranslator();
+else author=QString("unknown");
+
+int catnum=dm->catalogRef(location,author,fileName);
+
+uint i,tot;
+tot=catalog->numberOfEntries();
+//DataBaseItem dbit;
+bool fuzzy;
+bool untra;
+
+//kdDebug(0) << QString("Tot: %1").arg(tot) << endl;
+
+for (i=0;i<tot;i++) //Skip header = ????
+{
+
+ //Faster ?
+ if(i % 10==0)
+ {
+ emit fileProgress(100*i/tot);
+ emit added(count);
+ kapp->processEvents(100);
+ }
+
+ fuzzy=catalog->isFuzzy(i);
+ untra=catalog->isUntranslated(i);
+
+
+ if(!fuzzy && !untra)
+ {
+ int res;
+ QString msgid,msgstr;
+ msgid=catalog->msgid(i,true).first();
+ kdWarning() << "Translation database does not support plural forms" << endl;
+ msgstr=catalog->msgstr(i).first();
+ res=dm->putNewTranslation(msgid,msgstr,catnum,false);
+ count+=res;
+ }
+
+
+}
+
+
+// kdDebug(0) << QString("File finished") << endl;
+
+emit fileProgress(0);
+emit fileLoading(0);
+emit fileFinished();
+// dm->loadInfo(); // Sync the list of catalogs NOT NEEDED (?)
+
+delete catalog;
+
+//clear();
+return true;
+
+}
+#include "dbscan.moc"
diff --git a/kbabel/kbabeldict/modules/dbsearchengine/dbscan.h b/kbabel/kbabeldict/modules/dbsearchengine/dbscan.h
new file mode 100644
index 00000000..c151509e
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine/dbscan.h
@@ -0,0 +1,86 @@
+/***************************************************************************
+ dbscan.h -
+ -------------------
+ begin : Fri Sep 8 2000
+ copyright : (C) 2000 by Andrea Rizzi
+ email : rizzi@kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ * *
+ * In addition, as a special exception, the copyright holders give *
+ * permission to link the code of this program with any edition of *
+ * the Qt library by Trolltech AS, Norway (or with modified versions *
+ * of Qt that use the same license as Qt), and distribute linked *
+ * combinations including the two. You must obey the GNU General *
+ * Public License in all respects for all of the code used other than *
+ * Qt. If you modify this file, you may extend this exception to *
+ * your version of the file, but you are not obligated to do so. If *
+ * you do not wish to do so, delete this exception statement from *
+ * your version. *
+ ***************************************************************************/
+/*
+ Translation search engine
+
+
+ Copyright 2000
+ Andrea Rizzi rizzi@kde.org
+
+*/
+
+
+#ifndef _DBSCAN_H_
+#define _DBSCAN_H_
+
+#include <catalog.h>
+#include "database.h"
+
+class PoScanner : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ PoScanner(DataBaseManager *dbm,QObject *parent=0,const char *name=0);
+
+ /*
+ Scan a single PO file.
+ */
+ bool scanFile(QString fileName);
+
+ /*
+ Scan a list of space separated files with possible MetaCharacters
+ */
+ bool scanPattern(QString pathName,QString pattern="*.po",bool rec=false);
+
+
+
+
+signals:
+ void fileStarted();
+ void fileProgress(int);
+ void fileFinished();
+ void fileLoading(int);
+ void patternStarted();
+ void patternProgress(int);
+ void patternFinished();
+ void added(int);
+ void filename(QString);
+private:
+
+ // If true when a translation is found in a CATALOG the old translation for this CATALOG
+ // will be removed
+ bool removeOldCatalogTranslation;
+ int count;
+ DataBaseManager *dm;
+// InfoItem cinfo;
+};
+
+
+#endif
diff --git a/kbabel/kbabeldict/modules/dbsearchengine/dbse_factory.cpp b/kbabel/kbabeldict/modules/dbsearchengine/dbse_factory.cpp
new file mode 100644
index 00000000..37332167
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine/dbse_factory.cpp
@@ -0,0 +1,82 @@
+
+#include <klocale.h>
+#include <kinstance.h>
+#include <kaboutdata.h>
+#include <kdebug.h>
+
+#include "dbse_factory.h"
+#include "KDBSearchEngine.h"
+
+
+extern "C"
+{
+ KDE_EXPORT void *init_kbabeldict_dbsearchengine()
+ {
+ return new DbSeFactory;
+ }
+}
+
+
+KInstance *DbSeFactory::s_instance = 0;
+KAboutData *DbSeFactory::s_about = 0;
+
+
+DbSeFactory::DbSeFactory( QObject *parent, const char *name)
+ : KLibFactory(parent,name)
+{
+}
+
+DbSeFactory::~DbSeFactory()
+{
+ if(s_instance)
+ {
+ delete s_instance;
+ s_instance=0;
+ }
+
+ if(s_about)
+ {
+ delete s_about;
+ s_about=0;
+ }
+}
+
+
+QObject *DbSeFactory::createObject( QObject *parent, const char *name,
+ const char *classname, const QStringList &)
+{
+ if(QCString(classname) != "SearchEngine")
+ {
+ kdError() << "not a SearchEngine requested" << endl;
+ return 0;
+ }
+
+ KDBSearchEngine *se = new KDBSearchEngine(parent,name);
+
+ emit objectCreated(se);
+ return se;
+}
+
+
+KInstance *DbSeFactory::instance()
+{
+ if(!s_instance)
+ {
+
+ s_about = new KAboutData( "kdbsearchengine",
+ I18N_NOOP("Translation Database")
+ , "0.3" ,
+I18N_NOOP("A fast translation search engine based on databases")
+ , KAboutData::License_GPL
+ , I18N_NOOP("Copyright 2000-2001 by Andrea Rizzi")
+ ,0,0, "rizzi@kde.org");
+
+ s_about->addAuthor("Andrea Rizzi",0,"rizzi@kde.org");
+
+ s_instance = new KInstance(s_about);
+ }
+
+ return s_instance;
+}
+
+#include "dbse_factory.moc"
diff --git a/kbabel/kbabeldict/modules/dbsearchengine/dbse_factory.h b/kbabel/kbabeldict/modules/dbsearchengine/dbse_factory.h
new file mode 100644
index 00000000..6a9f9f3d
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine/dbse_factory.h
@@ -0,0 +1,26 @@
+#ifndef DBSE_FACTORY_H
+#define DBSE_FACTORY_H
+
+#include <klibloader.h>
+class KInstance;
+class KAboutData;
+
+class DbSeFactory : public KLibFactory
+{
+ Q_OBJECT
+public:
+ DbSeFactory( QObject *parent=0, const char *name=0);
+ ~DbSeFactory();
+
+ virtual QObject *createObject( QObject *parent=0, const char *name=0,
+ const char *classname="QObject",
+ const QStringList &args = QStringList());
+
+ static KInstance *instance();
+
+private:
+ static KInstance *s_instance;
+ static KAboutData *s_about;
+};
+
+#endif
diff --git a/kbabel/kbabeldict/modules/dbsearchengine/dbsearchengine.desktop b/kbabel/kbabeldict/modules/dbsearchengine/dbsearchengine.desktop
new file mode 100644
index 00000000..6aed2e40
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine/dbsearchengine.desktop
@@ -0,0 +1,52 @@
+[Desktop Entry]
+Type=Service
+Name=Translation Database for KBabelDict
+Name[bg]=БД Ñ Ð¿Ñ€ÐµÐ²Ð¾Ð´Ð¸ за KBabelDict
+Name[br]=Stlennvon geriaoueg evit KBabelDict
+Name[bs]=Baza prijevoda za KBabelDict
+Name[ca]=Base de dades de traducció per a KBabelDict
+Name[cs]=Databáze překladů pro KBabelDict
+Name[cy]=Cronfa ddata Cyfieithiadau i KBabelDict
+Name[da]=Oversættelsesdatabase for KBabelDict
+Name[de]=Übersetzungsdatenbank für KBabelDict
+Name[el]=Βάση δεδομένων μετάφÏασης για το KBabelDict
+Name[es]=Base de datos de traducciones para KBabelDict
+Name[et]=KBabelDicti tõlgete andmebaas
+Name[eu]=Itzulpen datu-basea KBabelDict-entzat
+Name[fa]=دادگان ترجمه برای KBabelDict
+Name[fi]=KBabelDict-ohjelman käännöstietokanta
+Name[fr]=Base de données des traductions pour KBabelDict
+Name[ga]=Cuimhne Aistriúcháin le haghaidh KBabelDict
+Name[gl]=Base de datos de traducións de KBabelDict
+Name[hi]=के-बेबल-डिकà¥à¤¶ के लिठअनà¥à¤µà¤¾à¤¦ डाटाबेस
+Name[hu]=Fordítási adatbázis a KBabelDicthez
+Name[is]=Þýðingagagnagrunnur fyrir KBabel orðabókina
+Name[it]=Banca dati di traduzioni per KBabelDict
+Name[ja]=KBabelDict トランザクションデータベース
+Name[ka]=თáƒáƒ áƒ’მნის მáƒáƒœáƒáƒªáƒ”მთრბáƒáƒ–რKBabelDict-სთვის
+Name[kk]=KBabelDict-тың аударма деректер қоры
+Name[lt]=KBabelDict vertimų duomenų bazė
+Name[ms]=Pangkalan Data Penterjemahan KBabelDict
+Name[nb]=Oversettelsesdatabase for KBabelDict
+Name[nds]=Översettendatenbank för KBabelDict
+Name[ne]=KBabelDict का लागि अनà¥à¤¬à¤¾à¤¦ डाटाबेस
+Name[nl]=Vertalingendatabase voor KBabelDict
+Name[nn]=Omsetjingsdatabase for KBabelDict
+Name[pa]=ਕੇਬਬੇਲ-ਸ਼ਬਦ-ਕੋਸ਼ ਲਈ ਅਨà©à¨µà¨¾à¨¦ ਡਾਟਾਬੇਸ
+Name[pl]=Baza tłumaczeń dla KBabelDict
+Name[pt]=Base de Dados de Traduções do KBabelDict
+Name[pt_BR]=Banco de Dados de Traduções para o KBabelDict
+Name[ru]=База данных переводов Ð´Ð»Ñ KBabelDict
+Name[sk]=Databáza prekladov pre KBabelDict
+Name[sl]=Zbirka prevodov za KBabelDict
+Name[sr]=Преводилачка база података за KBabelDict
+Name[sr@Latn]=PrevodilaÄka baza podataka za KBabelDict
+Name[sv]=Översättningsdatabas för Kbabeldict
+Name[ta]=Kபாபேலà¯à®•à¯à®•à®¾à®© மொழிபெயரà¯à®ªà¯à®ªà¯ தரவà¯à®¤à¯à®¤à®³à®®à¯
+Name[tg]=Базаи маълумоти тарҷумаҳо барои KBabelDict
+Name[tr]=KBabelDict için Çeviri Veritabanı
+Name[uk]=База даних перекладів Ð´Ð»Ñ KBabelDict
+Name[zh_CN]=KBabelDict 的翻译数æ®åº“
+Name[zh_TW]=KBabelDict 翻譯資料庫
+X-KDE-Library=kbabeldict_dbsearchengine
+ServiceTypes=KBabelDictModule
diff --git a/kbabel/kbabeldict/modules/dbsearchengine/dbseprefwidget.ui b/kbabel/kbabeldict/modules/dbsearchengine/dbseprefwidget.ui
new file mode 100644
index 00000000..d18ecaef
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine/dbseprefwidget.ui
@@ -0,0 +1,1036 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>DBSearchEnginePref</class>
+<author>Andrea Rizzi &lt;rizzi@kde.org&gt;</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>DBSEPrefWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>414</width>
+ <height>426</height>
+ </rect>
+ </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="QTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>TabWidget6</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string></string>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>Widget4</cstring>
+ </property>
+ <attribute name="title">
+ <string>Generic</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>ButtonGroup2</cstring>
+ </property>
+ <property name="title">
+ <string>Search Mode</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="QRadioButton" row="0" column="0">
+ <property name="name">
+ <cstring>allRB</cstring>
+ </property>
+ <property name="text">
+ <string>Search in whole database (slow)</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qml&gt;Scroll the whole database and return everything that matches
+according to the rules defined in tabs &lt;strong&gt; Generic &lt;/strong&gt;
+and &lt;strong&gt;Match&lt;/strong&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="1" column="0">
+ <property name="name">
+ <cstring>slistRB</cstring>
+ </property>
+ <property name="text">
+ <string>Search in list of "good keys" (best)</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qml&gt;Search in a list of &lt;em&gt;good keys&lt;/em&gt; (see &lt;strong&gt;Good keys&lt;/strong&gt; tab) with rules defined in &lt;strong&gt;Search&lt;/strong&gt; tab.
+This is the best way to search because the &lt;em&gt;good keys&lt;/em&gt; list probably contains all the keys that match with your query. However, it is smaller than the whole database.</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="2" column="0">
+ <property name="name">
+ <cstring>rlistRB</cstring>
+ </property>
+ <property name="text">
+ <string>Return the list of "good keys" (fast)</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qml&gt;Returns the whole &lt;em&gt;good keys&lt;/em&gt; list. Rules defined in &lt;strong&gt;Search&lt;/strong&gt; tab are ignored.</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>caseSensitiveCB</cstring>
+ </property>
+ <property name="text">
+ <string>Case sensitive</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qml&gt;If it is checked the search will be case sensitive. It is ignored if you use &lt;em&gt;Return the list of "good keys"&lt;/em&gt; search mode.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>normalizeCB</cstring>
+ </property>
+ <property name="text">
+ <string>Normalize white space</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Remove white spaces at the beginning and at the end of the phrase.
+It also substitutes groups of more than one space character with only one space character.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>removeContextCB</cstring>
+ </property>
+ <property name="text">
+ <string>Remove context comment</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Remove, if exists, the _:comment</string>
+ </property>
+ </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>TextLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Character to be ignored:</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>ignoreLE</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>Widget5</cstring>
+ </property>
+ <attribute name="title">
+ <string>Search</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>ButtonGroup1</cstring>
+ </property>
+ <property name="title">
+ <string>Matching Method</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>Spacer4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>Spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QCheckBox" row="2" column="1">
+ <property name="name">
+ <cstring>containedCB</cstring>
+ </property>
+ <property name="text">
+ <string>Query is contained</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Match if query is contained in database string</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="3" column="1">
+ <property name="name">
+ <cstring>containsCB</cstring>
+ </property>
+ <property name="text">
+ <string>Query contains</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Match if query contains the database string</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>normalTextRB</cstring>
+ </property>
+ <property name="text">
+ <string>Normal text</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Consider the search string as normal text.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="1">
+ <property name="name">
+ <cstring>equalCB</cstring>
+ </property>
+ <property name="text">
+ <string>Equal</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="tristate">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Match if query and database string are equal</string>
+ </property>
+ </widget>
+ <spacer row="3" column="0">
+ <property name="name">
+ <cstring>Spacer7</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QRadioButton" row="4" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>RegExpRB</cstring>
+ </property>
+ <property name="text">
+ <string>Regular expression</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Consider the search string as a regular expression</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>GroupBox3</cstring>
+ </property>
+ <property name="title">
+ <string>Word Substitution</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qml&gt;If you use one or two &lt;em&gt;word substitution&lt;/em&gt; each time you search a phrase with less than the specified number of words, the search engine will also search for all phrases that differ from the original one in one or two words.&lt;p&gt;
+&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
+If you search for &lt;em&gt;My name is Andrea&lt;/em&gt; and you have activated &lt;em&gt;one word substitution&lt;/em&gt; you may also find phrases like &lt;em&gt;My name is Joe&lt;/em&gt; or &lt;em&gt;Your name is Andrea&lt;/em&gt;.</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <spacer row="3" column="0">
+ <property name="name">
+ <cstring>Spacer8</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QCheckBox" row="0" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>oneWordSubCB</cstring>
+ </property>
+ <property name="text">
+ <string>Use one word substitution</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="tristate">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>Spacer9</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel" row="1" column="1">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Max number of words in the query:</string>
+ </property>
+ </widget>
+ <widget class="QSpinBox" row="3" column="2">
+ <property name="name">
+ <cstring>twoWordSubSB</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="maxValue">
+ <number>14</number>
+ </property>
+ <property name="value">
+ <number>10</number>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>twoWordSubCB</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Use two word substitution</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QLabel" row="3" column="1">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Max number of words in the query:</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="5" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>Layout7</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>TextLabel5_3</cstring>
+ </property>
+ <property name="text">
+ <string>[A-Za-z0-9_%</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="hAlign" stdset="0">
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>regExpLE</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel6_2</cstring>
+ </property>
+ <property name="text">
+ <string>]</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel" row="4" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>TextLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>Local characters for regular expressions:</string>
+ </property>
+ </widget>
+ <widget class="QSpinBox" row="1" column="2">
+ <property name="name">
+ <cstring>oneWordSubSB</cstring>
+ </property>
+ <property name="maxValue">
+ <number>200</number>
+ </property>
+ <property name="minValue">
+ <number>2</number>
+ </property>
+ <property name="value">
+ <number>40</number>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer1_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>Widget6</cstring>
+ </property>
+ <attribute name="title">
+ <string>Database</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel" row="0" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>TextLabel7_2</cstring>
+ </property>
+ <property name="text">
+ <string>Database folder:</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="1" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>dirInput</cstring>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>autoAddCB_2</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Auto add entry to database</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Automatically add an entry to the database if a new translation is notified by someone (may be kbabel)</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="3" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>Layout3</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_4</cstring>
+ </property>
+ <property name="text">
+ <string>Auto added entry author:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>authorLE</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qml&gt;Put here the name and email address that you want to use as &lt;em&gt;last translator&lt;/em&gt; filed when you auto-add entry to the database (e.g. when you modify a translation with kbabel).&lt;p&gt;</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QPushButton" row="4" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>scanFilePB</cstring>
+ </property>
+ <property name="text">
+ <string>Scan Single PO File...</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="5" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>scanPB_2</cstring>
+ </property>
+ <property name="text">
+ <string>Scan Folder...</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="6" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>scanrecPB</cstring>
+ </property>
+ <property name="text">
+ <string>Scan Folder &amp;&amp; Subfolders...</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="8" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>Layout5</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>filenameLB</cstring>
+ </property>
+ <property name="text">
+ <string>Scanning file:</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>entriesLB</cstring>
+ </property>
+ <property name="text">
+ <string>Entries added:</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget" row="9" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>Layout4</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QProgressBar" row="2" column="1">
+ <property name="name">
+ <cstring>processPB</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>Panel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="centerIndicator">
+ <bool>true</bool>
+ </property>
+ <property name="indicatorFollowsStyle">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel1_3</cstring>
+ </property>
+ <property name="text">
+ <string>Total progress:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>TextLabel3_3</cstring>
+ </property>
+ <property name="text">
+ <string>Processing file:</string>
+ </property>
+ </widget>
+ <widget class="QProgressBar" row="0" column="1">
+ <property name="name">
+ <cstring>totalPB</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>Panel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="centerIndicator">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QProgressBar" row="1" column="1">
+ <property name="name">
+ <cstring>loadingPB</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>Panel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="centerIndicator">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>TextLabel2_3</cstring>
+ </property>
+ <property name="text">
+ <string>Loading file:</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QPushButton" row="10" column="2">
+ <property name="name">
+ <cstring>exportPB</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Export...</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="10" column="0">
+ <property name="name">
+ <cstring>statPB</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Statistics</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="10" column="1">
+ <property name="name">
+ <cstring>repeatPB</cstring>
+ </property>
+ <property name="text">
+ <string>Repeated Strings</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Good Keys</string>
+ </attribute>
+ <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>GroupBox4</cstring>
+ </property>
+ <property name="title">
+ <string>Generic</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qml&gt;Here you can define how to fill the &lt;em&gt;good keys list&lt;/em&gt;.&lt;p&gt;
+You can set the minimum number of words of the query that a key must have to be inserted in the &lt;em&gt;good keys list&lt;/em&gt;.&lt;p&gt;
+You can also set the minimum number of words of the key that the query must have to insert the key in the list.&lt;p&gt;
+These two numbers are the percentage of the total number of words. If the result of this percentage is less than one, the engine will set it to one.&lt;p&gt;
+Finally you can set the maximum number of entries in the list.</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="QLabel" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>TextLabel3_2</cstring>
+ </property>
+ <property name="text">
+ <string>Minimum number of words of the key also in the query (%):</string>
+ </property>
+ <property name="textFormat">
+ <enum>RichText</enum>
+ </property>
+ </widget>
+ <widget class="QSlider" row="1" column="0">
+ <property name="name">
+ <cstring>thresholdSL</cstring>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>50</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="QSpinBox" row="1" column="1">
+ <property name="name">
+ <cstring>SpinBox5</cstring>
+ </property>
+ <property name="suffix">
+ <string>%</string>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>50</number>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>TextLabel2_2</cstring>
+ </property>
+ <property name="text">
+ <string>Minimum number of query words in the key (%):</string>
+ </property>
+ </widget>
+ <widget class="QSpinBox" row="4" column="1">
+ <property name="name">
+ <cstring>maxSB</cstring>
+ </property>
+ <property name="maxValue">
+ <number>5000</number>
+ </property>
+ <property name="value">
+ <number>30</number>
+ </property>
+ </widget>
+ <widget class="QSpinBox" row="3" column="1">
+ <property name="name">
+ <cstring>SpinBox6</cstring>
+ </property>
+ <property name="suffix">
+ <string>%</string>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>50</number>
+ </property>
+ </widget>
+ <widget class="QLabel" row="4" column="0">
+ <property name="name">
+ <cstring>TextLabel4_2</cstring>
+ </property>
+ <property name="text">
+ <string>Max list length:</string>
+ </property>
+ </widget>
+ <widget class="QSlider" row="3" column="0">
+ <property name="name">
+ <cstring>thresholdOrigSL</cstring>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>50</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>GroupBox3_2</cstring>
+ </property>
+ <property name="title">
+ <string>Frequent Words</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="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Discard words more frequent than:</string>
+ </property>
+ </widget>
+ <widget class="QSpinBox" row="0" column="1">
+ <property name="name">
+ <cstring>freqSB</cstring>
+ </property>
+ <property name="suffix">
+ <string>/10000</string>
+ </property>
+ <property name="maxValue">
+ <number>10000</number>
+ </property>
+ <property name="lineStep">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>nothingCB</cstring>
+ </property>
+ <property name="text">
+ <string>Frequent words are considered as in every key</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>thresholdSL</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>SpinBox5</receiver>
+ <slot>setValue(int)</slot>
+ </connection>
+ <connection>
+ <sender>thresholdOrigSL</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>SpinBox6</receiver>
+ <slot>setValue(int)</slot>
+ </connection>
+ <connection>
+ <sender>SpinBox5</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>thresholdSL</receiver>
+ <slot>setValue(int)</slot>
+ </connection>
+ <connection>
+ <sender>SpinBox6</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>thresholdOrigSL</receiver>
+ <slot>setValue(int)</slot>
+ </connection>
+</connections>
+<includes>
+ <include location="local" impldecl="in declaration">klocale.h</include>
+ <include location="global" impldecl="in declaration">kseparator.h</include>
+</includes>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kbabel/kbabeldict/modules/dbsearchengine/makemsgdb.C b/kbabel/kbabeldict/modules/dbsearchengine/makemsgdb.C
new file mode 100644
index 00000000..a83d947b
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine/makemsgdb.C
@@ -0,0 +1,327 @@
+#include <stdio.h>
+#include <time.h>
+#include <errno.h>
+#include <gdbm.h>
+#include <string.h>
+
+void removechar (char *s, int c)
+{
+ int i, l;
+ l = strlen (s);
+ if ((c >= l) || (c < 0))
+ return;
+ for (i = c; i < l; i++)
+ s[i] = s[i + 1];
+}
+void removeallc (char *s, char c)
+{
+ char *pos;
+ while ((pos = strchr (s, c)) != 0)
+ removechar (s, (long int) pos - (long int) s);
+
+}
+
+void normalizestr (char *s)
+{
+ char *pos;
+ while ((pos = strstr (s, "#~")) != 0) {
+ removechar (s, (long int) pos - (long int) s);
+ removechar (s, (long int) pos - (long int) s);
+ }
+ while (strchr (s, ' ') == s)
+ removechar (s, 0);
+}
+
+void freadline(char *buff,FILE *f)
+{
+char c;
+while ((fread(&c,1,1,f)==1) && (c!='\n'))
+ {
+ *buff=c;
+ buff++;
+ }
+*buff=0;
+
+}
+
+int makePoDb(const char* sourceName,const char* outputName)
+{
+static bool open = false;
+int m=0,n=0,h=0;
+GDBM_FILE db;
+datum key,value;
+char *s,a[20000],b[2000],k[2000],v[2000];
+int i,*np,nmax=0,co=-1,oldref[2000];
+long int tim;
+FILE *mlf;
+bool nextIsFuzzy;
+bool isAMsgId=true;
+/* char keystring[1000],valuestring[1000]; */
+
+/*Read headers, refnum end other info */
+db = gdbm_open((char *)outputName,1024,GDBM_READER,0666,0);
+mlf = fopen(sourceName,"r");
+if(strrchr(sourceName,'/')!=0)
+sourceName=strrchr(sourceName,'/')+1;
+
+if(!(db==0))
+ {
+ printf("ciao\n");
+ key.dptr=a;
+ strcpy(a,"__@REFNUM__");
+ key.dsize=strlen(a)+1;
+ value = gdbm_fetch(db,key);
+ np=(int*)value.dptr;
+ nmax=*np;
+ for(i=0;i<nmax;i++) {
+ sprintf(a,"__@%d__",i);
+ key.dsize=strlen(a)+1;
+ value = gdbm_fetch(db,key);
+ if(strcmp(value.dptr,sourceName)==0)
+ oldref[++co]=i;
+ // printf("File %s in Date %s\nRef # %d, oldref[%d]=%d\n",value.dptr,value.dptr+1+strlen(value.dptr),i,co,oldref[co]);
+ }
+ gdbm_close(db);
+ }
+
+
+db = gdbm_open((char *)outputName,1024,GDBM_WRCREAT,0666,0);
+if(db==0) return 0;
+
+nmax++;
+//sourceName=strrchr(sourceName,'/')+1;
+ if(open) return 0;
+ open=true;
+
+ key.dptr=a;
+ strcpy(a,"__@REFNUM__");
+ key.dsize=strlen(a)+1;
+ value.dptr=(char *)&nmax;
+ value.dsize=4;
+ gdbm_store(db,key,value,GDBM_REPLACE);
+ sprintf(a,"__@%d__",nmax-1);
+ key.dsize=strlen(a)+1;
+ strcpy(v,sourceName);
+ value.dptr=v;
+ time(&tim);
+// ctime(&tim);
+ // fprintf(stderr,"%s %s\n",v,ctime(&tim));
+ strcpy(v+strlen(v)+1,ctime(&tim));
+ value.dsize=strlen(v)+2+strlen(v+strlen(v)+1);
+ gdbm_store(db,key,value,GDBM_REPLACE);
+
+ while(!feof(mlf))
+ {
+ freadline(a,mlf);
+ normalizestr(a);
+// printf("#%s#\n",a);
+
+// while (st.find("#~")==0)
+// st = st.right(st.length()-2);
+// while (st.find(" ")==0)
+// st = st.right(st.length()-1);
+
+ if(isAMsgId) nextIsFuzzy=false;
+ if(strstr(a,"#,")==a)
+ if(strstr(a,"fuzzy")!=0) nextIsFuzzy=true;
+ isAMsgId=(strstr(a,"msgid"));
+ if(isAMsgId && !nextIsFuzzy)
+ {
+ *b='\0';
+ clearerr(mlf);
+ while(!feof(mlf) && !(strstr(a,"msgstr")==a))
+ {
+ strcat(b,strchr(a,'"')+1);
+ *strrchr(b,'\"')= '\0'; //"
+ freadline(a,mlf);
+ normalizestr(a);
+
+
+ if(b+strlen(b)==strstr(b,"\\n")+2)
+ {
+ b[strlen(b)-2]='\n';
+ b[strlen(b)-1]='\0';
+ }
+ }
+
+ // fprintf(stderr,"MSGID#%s#\n",b);
+ //}
+
+ if(b[0]!='\0') {
+ key.dptr=k;
+ strcpy(k,b);
+ key.dsize=strlen(key.dptr)+1;
+ int lines=0;
+ *b='\0';
+ while(!feof(mlf) && !(strstr(a,"msgid")==a) && !(strchr(a,'"')==0))
+ {
+ lines++;
+ strcat(b,strchr(a,'"')+1);
+ *strrchr(b,'\"')= '\0'; //"
+ freadline(a,mlf);
+ normalizestr(a);
+
+
+ if(b+strlen(b)==strstr(b,"\\n")+2)
+ {
+ b[strlen(b)-2]='\n';
+ b[strlen(b)-1]='\0';
+ }
+ }
+ value.dptr=v;
+ int *t;
+ int *nr,*re; //,*md; //Number of references,ref
+
+ t=(int *)value.dptr;
+ *t=1;
+ strcpy(value.dptr+4,b);
+ nr=(int *)(value.dptr+4+strlen(value.dptr+4)+1);
+ *nr=1;
+ nr++;
+ *nr=nmax-1;
+ value.dsize=strlen(value.dptr+4)+1+4+8;
+ // fprintf(stderr,"MSGSTR#%s#nref=%d\n",value.dptr+4,
+// *(int*)(value.dptr+4+strlen(value.dptr+4)+1 ));
+
+ if(b[0]!='\0') {
+ if(gdbm_store(db,key,value,GDBM_INSERT))
+ {
+ // fprintf(stderr,"*** Key exists ***\n");
+
+ gdbm_sync(db);
+ gdbm_close(db);
+ db = gdbm_open((char *)outputName,1024,GDBM_READER,0,0);
+ datum oldvalue;
+ oldvalue= gdbm_fetch(db,key);
+ gdbm_sync(db);
+ gdbm_close(db);
+ db = gdbm_open((char *)outputName,1024,GDBM_WRCREAT,0,0);
+
+ t=(int *)oldvalue.dptr;
+ int i,r,j; //counters
+ int v=*t; //Number of strings
+ int *nr,*re,*md; //Number of references,ref
+ bool exist=false,here,modif=false;
+ char *os=oldvalue.dptr+4;
+ // fprintf(stderr,"**Searching string #%s#\n",b);
+ for(i=0;i<v;i++)
+ {
+
+ exist=false; //REMOVE THIS LINE!!!
+ here=false;
+ // fprintf(stderr,"**STRING %d #%s# len=%d %s\n",i,os,strlen(os),b);
+ if(strcmp(os,b)==0) {
+ exist=true;
+ here=true;
+ // fprintf(stderr,"That's good\n");
+ }
+ os+=strlen(os)+1; //End of string
+ nr=(int *)os;
+ os+=(*nr+1)*4;
+ re=nr;
+ modif=false;
+ // fprintf(stderr,"refernces %d\n",*nr);
+ for(j=0;j<*nr;j++)
+ {
+ re++;
+
+ if(here)
+ {
+ // printf("reference #%d\n",*re);
+ for(r=0;r<=co;r++)
+ {
+ // fprintf(stderr,"%d==%d ?-->",oldref[co],*re);
+ if(oldref[r]==*re)
+ {
+ modif=true;
+ // fprintf(stderr,"Yes\n");
+ *re=(nmax-1);
+ } //else fprintf(stderr,"No\n");
+ }
+ // fprintf(stderr,"qui\n");
+ if(!modif)
+ md=nr;
+ // fprintf(stderr,"modif %s\n",modif ? "true":"false");
+ }
+ }
+
+ }
+
+ if(!exist)
+ {
+ int oldlen=(long int)os-(long int)oldvalue.dptr-4;
+ memcpy(a+4,oldvalue.dptr+4,oldlen);
+// fprintf(stderr,"***!exist Old len is %d+4 1st str is %s\n",oldlen,a+4);
+ v++;
+ t=(int *)a;
+ *t=v;
+ // fprintf(stderr,"b=%s",b);
+ strcpy(a+4+oldlen,b);
+ re=(int *)(a+4+oldlen+strlen(b)+1);
+ *re=1;
+ re++;
+ *re=nmax-1;
+ //fprintf(stderr,"a+4=%s a+4+oldlen=%s",a+4,a+4+oldlen);
+ value.dptr=a;
+ value.dsize=oldlen+strlen(b)+1+4+8;
+ gdbm_store(db,key,value,GDBM_REPLACE);
+ n++;
+ } else
+ {
+ if(!modif)
+ {
+// fprintf(stderr,"grossa crisi %d\n",*md);
+// fprintf(stderr,"Old num of ref \n");
+ int oldlen1=(long int)(md)-(long int)(oldvalue.dptr)-4;
+ int oldlen2=(long int)(os)-(long int)(md)-4; //-4 because nr
+ memcpy(a+4,oldvalue.dptr+4,oldlen1);
+ memcpy(a+4+oldlen1+8,oldvalue.dptr+4+oldlen1+4,oldlen2);
+ re=(int *)(a+4+oldlen1);
+ *re=(*md )+1;
+ // *re++;
+ re++;
+ *re=nmax-1;
+ t=(int *)a;
+ *t=v;
+ value.dptr=a;
+ value.dsize=oldlen1+oldlen2+4+8;
+ gdbm_store(db,key,value,GDBM_REPLACE);
+ n++;
+ }
+ else //if (modif)
+ {
+ value.dptr=oldvalue.dptr;
+ value.dsize=oldvalue.dsize;
+ gdbm_store(db,key,value,GDBM_REPLACE);
+ }
+ }
+
+ h++;
+ } else {
+
+ m++;
+ }
+ }
+ }
+
+ }
+
+
+ }
+
+ fclose(mlf);
+ gdbm_close(db);
+ open=false;
+ printf("new Key in database %d\n old key found %d\n value added %d\n",m,h,n);
+ return m+n;
+}
+
+
+
+main(int argc,char **argv)
+{
+int i;
+for(i=1;i<argc;i++)
+ printf("File %s:\nEntry added to dbase: %d\n",argv[i],makePoDb(argv[i],"messages2.db"));
+
+}
diff --git a/kbabel/kbabeldict/modules/dbsearchengine/preferenceswidget.cpp b/kbabel/kbabeldict/modules/dbsearchengine/preferenceswidget.cpp
new file mode 100644
index 00000000..3bb65934
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine/preferenceswidget.cpp
@@ -0,0 +1,111 @@
+#include <qradiobutton.h>
+#include <qslider.h>
+#include <qspinbox.h>
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <klocale.h>
+#include <kfiledialog.h>
+#include <kurlrequester.h>
+#include <qtoolbutton.h>
+#include <klineedit.h>
+#include <kstandarddirs.h>
+
+#include "dbseprefwidget.h"
+#include "preferenceswidget.h"
+
+PreferencesWidget::PreferencesWidget(QWidget *parent, const char* name)
+ : PrefWidget(parent,name)
+{
+ QVBoxLayout *layout = new QVBoxLayout(this);
+// QLabel *label = new QLabel(i18n("Settings for KDE database search engine"),this);
+// layout->addWidget(label);
+
+ dbpw = new DBSearchEnginePref(this);
+ dbpw->dirInput->setMode(KFile::Directory | KFile::LocalOnly);
+
+ layout->addWidget(dbpw);
+ resize(QSize(200,200).expandedTo(minimumSizeHint()));
+
+// connect(dbpw->browseTB_3,SIGNAL(clicked()),SLOT(browse1()));
+
+ emit restoreNow(); //Fill with actual params.
+
+}
+
+PreferencesWidget::~PreferencesWidget()
+{
+}
+
+void PreferencesWidget::apply()
+{
+emit applyNow();
+}
+
+void PreferencesWidget::cancel()
+{
+emit restoreNow();
+}
+
+void PreferencesWidget::standard()
+{
+
+
+dbpw->caseSensitiveCB->setChecked(false);
+dbpw->normalizeCB->setChecked(true);
+dbpw->removeContextCB->setChecked(true);
+
+dbpw->oneWordSubCB->setChecked(true);
+dbpw->twoWordSubCB->setChecked(false);
+
+
+dbpw->RegExpRB->setChecked(false);
+dbpw->normalTextRB->setChecked(true);
+dbpw->equalCB->setChecked( true );
+dbpw->containsCB->setChecked( true);
+dbpw->containedCB->setChecked( true );
+
+
+dbpw->oneWordSubSB->setValue(20);
+dbpw->twoWordSubSB->setValue(8);
+
+dbpw->maxSB->setValue(500);
+dbpw->thresholdSL->setValue(50);
+dbpw->thresholdOrigSL->setValue(50);
+
+dbpw->allRB->setChecked( false);
+dbpw->slistRB->setChecked( true);
+dbpw->rlistRB->setChecked( false );
+
+dbpw->nothingCB->setChecked(true);
+dbpw->freqSB->setValue(300);
+
+dbpw->ignoreLE->setText("&.:");
+
+dbpw->autoAddCB_2->setChecked(true);
+
+QString defaultDir;
+ KStandardDirs * dirs = KGlobal::dirs();
+ if(dirs)
+ {
+ defaultDir = dirs->saveLocation("data");
+ if(defaultDir.right(1)!="/")
+ defaultDir+="/";
+ defaultDir += "kbabeldict/dbsearchengine";
+ }
+
+ dbpw->dirInput->setURL(defaultDir);
+}
+
+void PreferencesWidget::setName(QString n)
+{
+dbpw->filenameLB->setText(i18n("Scanning file: %1").arg(n));
+}
+
+void PreferencesWidget::setEntries(int i)
+{
+dbpw->entriesLB->setText(i18n("Entries added: %1").arg(i));
+
+}
+
+#include "preferenceswidget.moc"
diff --git a/kbabel/kbabeldict/modules/dbsearchengine/preferenceswidget.h b/kbabel/kbabeldict/modules/dbsearchengine/preferenceswidget.h
new file mode 100644
index 00000000..599408cd
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine/preferenceswidget.h
@@ -0,0 +1,28 @@
+#ifndef PREFERENCESWIDGET_H
+#define PREFERENCESWIDGET_H
+
+#include "searchengine.h"
+#include "dbseprefwidget.h"
+
+class PreferencesWidget : public PrefWidget
+{
+ Q_OBJECT
+
+public:
+ PreferencesWidget(QWidget *parent=0, const char* name=0);
+ virtual ~PreferencesWidget();
+
+ virtual void apply();
+ virtual void cancel();
+ virtual void standard();
+ DBSearchEnginePref *dbpw;
+public slots:
+ void setName(QString);
+ void setEntries(int);
+signals:
+ void applyNow();
+ void restoreNow();
+
+};
+
+#endif
diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/AUTHOR b/kbabel/kbabeldict/modules/dbsearchengine2/AUTHOR
new file mode 100644
index 00000000..2a79312d
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine2/AUTHOR
@@ -0,0 +1 @@
+Andrea Rizzi <rizzi@kde.org> \ No newline at end of file
diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/KDBSearchEngine2.cpp b/kbabel/kbabeldict/modules/dbsearchengine2/KDBSearchEngine2.cpp
new file mode 100644
index 00000000..5bf088b8
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine2/KDBSearchEngine2.cpp
@@ -0,0 +1,686 @@
+/***************************************************************************
+ KDBSearchEngine2.cpp - description
+ -------------------
+ begin : Fri Sep 8 2000
+ copyright : (C) 2000-2003 by Andrea Rizzi
+ email : rizzi@kde.org
+***************************************************************************/
+
+/*
+ Translation search engine. Version II
+
+
+ Copyright 2000-2003
+ Andrea Rizzi rizzi@kde.org
+
+ License GPL v 2.0
+
+ * *
+ * In addition, as a special exception, the copyright holders give *
+ * permission to link the code of this program with any edition of *
+ * the Qt library by Trolltech AS, Norway (or with modified versions *
+ * of Qt that use the same license as Qt), and distribute linked *
+ * combinations including the two. You must obey the GNU General *
+ * Public License in all respects for all of the code used other than *
+ * Qt. If you modify this file, you may extend this exception to *
+ * your version of the file, but you are not obligated to do so. If *
+ * you do not wish to do so, delete this exception statement from *
+ * your version. *
+
+*/
+#include "algorithms.h"
+#include "chunk.h"
+#include "database.h"
+#include "KDBSearchEngine2.h"
+#include "dbscan.h"
+#include <klineedit.h>
+#include <kapplication.h>
+#include <qpushbutton.h>
+#include <kurlrequester.h>
+#include <qcheckbox.h>
+#include <knuminput.h>
+#include <kstandarddirs.h>
+#include <kmessagebox.h>
+
+#include <qmap.h>
+
+#include <kdebug.h>
+#define i18n (const char *)
+
+KDBSearchEngine2::KDBSearchEngine2(QObject *parent,const char*name)
+ : SearchEngine(parent,name)
+ {
+ pw=0;
+ dbDirectory=".";
+
+ di=0; //Database Interface is not yet initialized
+
+ connect(this,SIGNAL(hasError(QString)),SLOT(setLastError(QString)));
+
+ searching=false; // i'm not searching
+ iAmReady=true; //there are no reason to say I'm not ready.
+
+}
+
+
+KDBSearchEngine2::~KDBSearchEngine2()
+{
+ if(di)
+ delete di; //delete database interface
+}
+
+bool KDBSearchEngine2::startSearch(QString str)
+{
+ kdDebug(0) << "Start a new search. Looking for: " << str << endl;
+
+ static QString queryString;
+
+ queryString=str; //set the latest query string (note: it is static)
+
+ if(autoupdate)
+ {
+ updateSettings();
+ }
+
+
+ if(!init()) return false; //-check initialization
+ di->stop(true); //stop all new emits from database interface
+ emit started(); //say everybody we are starting
+
+ if(searching) return true; //We already have a search loop, as soon as we come back
+ //on the search loop we will start the new search (queryString).
+
+ searching=true; //really start searching
+
+ QString searchingString;
+
+ do //Search loop, it stops only when finished and latest searched string is the actual query string.
+ {
+ searchingString=queryString; //-set new search string
+ di->stop(false); //-unlock searching
+
+ if(numberOfResult<1) numberOfResult=1;
+
+// di->singleWordMatch(searchingString,0,true);
+
+ GenericSearchAlgorithm strategy(di,&settings);
+
+ //Let's create a search sequence:
+ ExactSearchAlgorithm exact(di,&settings);
+ AlphaSearchAlgorithm alpha(di,&settings);
+ SentenceArchiveSearchAlgorithm sent(di,&settings);
+ ChunkByChunkSearchAlgorithm sbys(di,&settings);
+ ChunkByChunkSearchAlgorithm wbyw(di,&settings);
+ CorrelationSearchAlgorithm corr(di,&settings);
+ FuzzyChunkSearchAlgorithm fs(di,&settings);
+ FuzzyChunkSearchAlgorithm fw(di,&settings);
+
+ SentenceChunkFactory sf(di);
+ sbys.setChunkFactory(&sf);
+ fs.setChunkFactory(&sf);
+
+
+ WordChunkFactory wf(di);
+ wbyw.setChunkFactory(&wf);
+ fw.setChunkFactory(&wf);
+
+ strategy.addAlgorithm(&exact);
+ strategy.addAlgorithm(&alpha);
+ strategy.addAlgorithm(&sent);
+ strategy.addAlgorithm(&sbys);
+ //strategy.addAlgorithm(&fs);
+ strategy.addAlgorithm(&fw);
+ strategy.addAlgorithm(&corr);
+ strategy.addAlgorithm(&wbyw);
+
+
+ connect(&strategy,SIGNAL(newResult(QueryResult)),this,SLOT(receiveResult(QueryResult)));
+ strategy.exec(searchingString); disconnect(&strategy,SIGNAL(newResult(QueryResult)),this,SLOT(receiveResult(QueryResult)));
+
+
+ kdDebug(0) << "End of search for " << searchingString << endl;
+ }
+ while(searchingString!=queryString);
+ kdDebug(0) << "Exiting the search loop" << endl;
+ //if != someone asked a different string when we was searching
+ //so we restart our search (maybe a cleanresult is needed?).
+
+
+ di->stop(false); //-clean searching locks
+ searching=false; //-clean searching locks
+ emit finished(); //Finished
+
+ return true;
+
+}
+
+
+
+
+
+bool KDBSearchEngine2::startSearchInTranslation(QString str)
+{
+ if(autoupdate)
+ {
+ updateSettings();
+ }
+
+ //TODO!!!!
+ return true;
+
+}
+
+
+
+bool KDBSearchEngine2::messagesForPackage(const QString& package
+ , QValueList<Message>& resultList, QString& error)
+{
+ //FIXME implement this (needs filters)
+ return true;
+}
+
+
+void KDBSearchEngine2::setLastError(QString er)
+{
+ lasterror=er;
+}
+
+QString KDBSearchEngine2::translate(const QString text)
+{
+ ExactSearchAlgorithm exact(di,&settings);
+
+ return exact.exec(text)[0].result();
+
+}
+
+
+void KDBSearchEngine2::receiveResult(QueryResult r)
+{
+
+ SearchResult se; // Create a new SearchResult for our QueryResult
+
+ se.translation=r.richResult();
+ se.found=r.richOriginal();
+
+ se.plainTranslation=r.result();
+ se.plainFound=r.original();
+ se.score=r.score();
+
+ emit resultFound(&se); // dispatch the new SearchResult
+
+}
+
+
+/* A SEARCH RESULT CONTAINS (see searchengine.h)
+ QString requested;
+ QString found;
+ QString translation;
+ QString plainTranslation;
+ QString plainFound;
+ QString plainRequested;
+ int score;
+ QPtrList<TranslationInfo> descriptions;
+*/
+
+
+
+bool KDBSearchEngine2::init()
+{
+ if(di!=0) return true; //if there already is a DBinterface we are ok
+ else
+ {
+ di = new DataBaseInterface(dbDirectory,&settings);
+ connect(di,SIGNAL(newResult(QueryResult)),this,SLOT(receiveResult(QueryResult)));
+ //FIXME: what wbout ready()
+ if(!di->mainOk()) return false; //check if the main DB is OK.
+
+ return true;
+ }
+
+}
+const KAboutData *KDBSearchEngine2::about() const
+{
+ return DbSe2Factory::instance()->aboutData();
+}
+
+void KDBSearchEngine2::stringChanged( QString orig, QString translated
+ , QString description)
+{
+
+ if(!init()) return;
+ //if(translated.isEmpty()) return;
+ InputInfo ii;
+ if(description.find("fuzzy",false)==-1)
+ di->addEntry(orig,translated,&ii);
+
+}
+
+PrefWidget * KDBSearchEngine2::preferencesWidget(QWidget *parent)
+{
+
+ pw = new KDB2PreferencesWidget(parent);
+ kdDebug(0) << "new KDB2 preferences widget" << endl;
+ setSettings();
+ connect(pw,SIGNAL(restoreNow()),this,SLOT(setSettings()));
+ connect(pw,SIGNAL(applyNow()),this,SLOT(updateSettings()));
+ connect(pw,SIGNAL(destroyed()),this,SLOT(prefDestr()));
+
+
+ connect(pw->dbpw->scanAll,SIGNAL(clicked()),this,SLOT(scanAllPressed()));
+ connect(pw->dbpw->scanSource,SIGNAL(clicked()),this,SLOT(scanNowPressed()));
+ connect(pw->dbpw->addSource,SIGNAL(clicked()),this,SLOT(addSource()));
+ connect(pw->dbpw->editSource,SIGNAL(clicked()),this,SLOT(editSource()));
+ connect(pw->dbpw->removeSource,SIGNAL(clicked()),this,SLOT(removeSource()));
+
+
+ return pw;
+}
+
+void KDBSearchEngine2::saveSettings(KConfigBase *config)
+{
+ KConfigGroupSaver cgs(config,"KDBSearchEngine2");
+
+
+
+ config->writeEntry("DBDirectory",dbDirectory);
+ config->writeEntry("AutoAdd",autoAdd);
+ config->writeEntry("UseSentence",useSentence);
+ config->writeEntry("UseGlossary",useGlossary);
+ config->writeEntry("UseExact",useExact);
+ config->writeEntry("UseDivide",useDivide);
+ config->writeEntry("UseAlpha",useAlpha);
+ config->writeEntry("UseWordByWord",useWordByWord);
+ config->writeEntry("UseDynamic",useDynamic);
+ config->writeEntry("NumberOfResults",numberOfResult);
+
+ config->writeEntry("ScoreDivide",settings.scoreDivide);
+ config->writeEntry("ScoreExact",settings.scoreExact);
+ config->writeEntry("ScoreSentence",settings.scoreSentence);
+ config->writeEntry("ScoreWordByWord",settings.scoreWordByWord);
+ config->writeEntry("ScoreGlossary",settings.scoreGlossary);
+ config->writeEntry("ScoreAlpha",settings.scoreAlpha);
+ config->writeEntry("ScoreDynamic",settings.scoreDynamic);
+ config->writeEntry("MinimumScore",settings.minScore);
+ config->writeEntry("FirstCapital",settings.firstCapital);
+ config->writeEntry("AllCapital",settings.allCapital);
+ config->writeEntry("Accelerator",settings.accelerator);
+ config->writeEntry("SameLetter",settings.sameLetter);
+
+ uint sourceNumber=0;
+ config->writeEntry("NumberOfDBImportSources",sources.count());
+
+ for(QMap<QString,MessagesSource>::iterator sourceIt=sources.begin() ; sourceIt!=sources.end(); ++sourceIt)
+ {
+ sourceNumber++;
+ config->setGroup("DBImportSource-"+QString::number(sourceNumber));
+ config->writeEntry("Name",sourceIt.key());
+ sourceIt.data().writeConfig(config);
+ }
+}
+
+void KDBSearchEngine2::readSettings(KConfigBase *config)
+{
+
+ /*QString defaultDir;
+ KStandardDirs * dirs = KGlobal::dirs();
+ if(dirs)
+ {
+ defaultDir = dirs->saveLocation("data");
+ if(defaultDir.right(1)!="/")
+ defaultDir+="/";
+ defaultDir += "kbabeldict/dbsearchengine2";
+ }
+*/
+ KConfigGroupSaver cgs(config,"KDBSearchEngine2");
+
+ // dbDirectory=config->readEntry("DBDirectory",defaultDir);
+ autoAdd=config->readBoolEntry("AutoAdd",true);
+ useSentence=config->readBoolEntry("UseSentence",true);
+ useGlossary=config->readBoolEntry("UseGlossary",true);
+ useExact=config->readBoolEntry("UseExact",true);
+ useDivide=config->readBoolEntry("UseDivide",true);
+ useAlpha=config->readBoolEntry("UseAlpha",true);
+ useWordByWord=config->readBoolEntry("UseWordByWord",true);
+ useDynamic=config->readBoolEntry("UseDynamic",true);
+ numberOfResult=config->readNumEntry("NumberOfResults",5);
+
+ settings.scoreDivide=config->readNumEntry("ScoreDivide",90);
+ settings.scoreExact=config->readNumEntry("ScoreExact",100);
+ settings.scoreSentence=config->readNumEntry("ScoreSentence",90);
+ settings.scoreWordByWord=config->readNumEntry("ScoreWordByWord",70);
+ settings.scoreGlossary=config->readNumEntry("ScoreGlossary",98);
+ settings.scoreAlpha=config->readNumEntry("ScoreAlpha",98);
+ settings.scoreDynamic=config->readNumEntry("ScoreDynamic",80);
+ settings.minScore=config->readNumEntry("MinimumScore",60);
+ settings.firstCapital=config->readBoolEntry("FirstCapital",true);
+ settings.allCapital=config->readBoolEntry("AllCapital",false);
+ settings.accelerator=config->readBoolEntry("Accelerator",true);
+ settings.sameLetter=config->readBoolEntry("SameLetter",true);
+
+ uint numberOfSources=config->readNumEntry("NumberOfDBImportSources",0);
+ kdDebug(0) << "Found "<< numberOfSources << " sources" << endl;
+ for(uint sourceNumber=1;sourceNumber<=numberOfSources;sourceNumber++)
+ {
+ config->setGroup("DBImportSource-"+QString::number(sourceNumber));
+ QString name=config->readEntry("Name");
+ sources[name].readConfig(config);
+ }
+ if(pw)
+ setSettings();
+
+}
+
+void KDBSearchEngine2::setSettings()
+{
+ if(pw) {
+ pw->dbpw->dbDirectory->setURL(dbDirectory);
+ pw->dbpw->autoUpdate->setChecked(autoAdd);
+
+ pw->dbpw->useSentence->setChecked(useSentence);
+ pw->dbpw->useGlossary->setChecked(useGlossary);
+ pw->dbpw->useExact->setChecked(useExact);
+ pw->dbpw->useDivide->setChecked(useDivide);
+ pw->dbpw->useAlpha->setChecked(useAlpha);
+ pw->dbpw->useWordByWord->setChecked(useWordByWord);
+ pw->dbpw->useDynamic->setChecked(useDynamic);
+ pw->dbpw->numberOfResult->setValue(numberOfResult);
+ pw->dbpw->scoreDivide->setValue(settings.scoreDivide);
+ pw->dbpw->scoreExact->setValue(settings.scoreExact);
+ pw->dbpw->scoreSentence->setValue(settings.scoreSentence);
+ pw->dbpw->scoreWordByWord->setValue(settings.scoreWordByWord);
+ pw->dbpw->scoreGlossary->setValue(settings.scoreGlossary);
+ pw->dbpw->scoreAlpha->setValue(settings.scoreAlpha);
+ pw->dbpw->scoreDynamic->setValue(settings.scoreDynamic);
+ pw->dbpw->minScore->setValue(settings.minScore);
+ pw->dbpw->firstCapital->setChecked(settings.firstCapital);
+ pw->dbpw->allCapital->setChecked(settings.allCapital);
+ pw->dbpw->accelerator->setChecked(settings.accelerator);
+ pw->dbpw->sameLetter->setChecked(settings.sameLetter);
+
+ //pw->dbpw->checkLang->setChecked(true);
+ //pw->dbpw->useFilters->setChecked(false);
+ //pw->dbpw->dateToday->setChecked(false);
+ pw->dbpw->sourceList->clear();
+ for(QMap<QString,MessagesSource>::iterator sourceIt=sources.begin() ; sourceIt!=sources.end(); ++sourceIt)
+ {
+ pw->dbpw->sourceList->insertItem(sourceIt.key());
+ }
+ }
+
+}
+
+void KDBSearchEngine2::updateSettings()
+{
+ if(!pw) return;
+
+ QString newdb = pw->dbpw->dbDirectory->url();
+ if(newdb !=dbDirectory)
+ {
+ kdDebug(0) << "Recreate DB-Interface cause dbdir is changed" << endl;
+ dbDirectory=newdb;
+ if (di!=0) delete di;
+ di= new DataBaseInterface(dbDirectory,&settings);
+ }
+
+ autoAdd=pw->dbpw->autoUpdate->isChecked();
+
+ useSentence=pw->dbpw->useSentence->isChecked();
+ useGlossary=pw->dbpw->useGlossary->isChecked();
+ useExact=pw->dbpw->useExact->isChecked();
+ useDivide=pw->dbpw->useDivide->isChecked();
+ useAlpha=pw->dbpw->useAlpha->isChecked();
+ useWordByWord=pw->dbpw->useWordByWord->isChecked();
+ useDynamic=pw->dbpw->useDynamic->isChecked();
+
+ numberOfResult=pw->dbpw->numberOfResult->value();
+
+ settings.scoreWordByWord=pw->dbpw->scoreWordByWord->value();
+ settings.scoreGlossary=pw->dbpw->scoreGlossary->value();
+ settings.scoreDivide=pw->dbpw->scoreDivide->value();
+ settings.scoreExact=pw->dbpw->scoreExact->value();
+ settings.scoreSentence=pw->dbpw->scoreSentence->value();
+ settings.scoreAlpha=pw->dbpw->scoreAlpha->value();
+ settings.scoreDynamic=pw->dbpw->scoreDynamic->value();
+
+ settings.minScore=pw->dbpw->minScore->value();
+
+ settings.firstCapital=pw->dbpw->firstCapital->isChecked();
+ settings.allCapital=pw->dbpw->allCapital->isChecked();
+ settings.accelerator=pw->dbpw->accelerator->isChecked();
+ settings.sameLetter=pw->dbpw->sameLetter->isChecked();
+
+ //pw->dbpw->editRule->
+ //pw->dbpw->deleteRule->
+ //pw->dbpw->customRules->
+
+ /*
+pw->dbpw->checkLang->
+pw->dbpw->useFilters->
+pw->dbpw->dateToday->
+
+pw->dbpw->removeSource->
+pw->dbpw->scanSource->
+pw->dbpw->addSource->
+pw->dbpw->sourceDir->
+pw->dbpw->scanAll->
+pw->dbpw->sourceList->
+*/
+
+}
+
+
+/*void KDBSearchEngine2::scanSource(QString sourceName)
+{
+ //FIXME: an error here would be nice
+ if(!init()) return;
+
+
+ for(QValueList<MessagesSource>::iterator sourceIt=sources.begin() ; sourceIt!=sources.end(); sourceIt++)
+ {
+ if((*sourceIt).getName()==sourceName)
+ {
+ QValueList<KURL> urls=(*sourceIt).urls();
+ PoScanner ps(di);
+ for(QValueList<KURL>::iterator urlIt=urls.begin();urlIt!=urls.end();urlIt++)
+ ps.scanFile(*urlIt);
+
+ //We suppose name are unique so no need for further scrolling
+ return ;
+ }
+ }
+}*/
+void KDBSearchEngine2::scanNowPressed()
+{
+ if(!pw)
+ {
+ kdDebug(0) << "We should not be here, scanNow called without a pw!" << endl;
+ return;
+ }
+ QString sourceName;
+ sourceName=pw->dbpw->sourceList->currentText();
+ if(!init()) return;
+ if(sources.contains(sourceName))
+ {
+ QValueList<KURL> urls=sources[sourceName].urls();
+ PoScanner ps(di);
+ for(QValueList<KURL>::iterator urlIt=urls.begin();urlIt!=urls.end();++urlIt)
+ ps.scanURL(*urlIt);
+
+ }
+ else
+ {
+ kdDebug(0) << "source name not found in our MAP. This is a bug." << endl;
+ }
+}
+
+void KDBSearchEngine2::scanAllPressed()
+{
+ //FIXME: an error here would be nice too
+ if(!init()) return;
+ PoScanner ps(di);
+
+
+ for(QMap<QString,MessagesSource>::iterator sourceIt=sources.begin() ; sourceIt!=sources.end(); ++sourceIt)
+ {
+ QValueList<KURL> urls=(*sourceIt).urls();
+ for(QValueList<KURL>::iterator urlIt=urls.begin();urlIt!=urls.end();++urlIt)
+ ps.scanURL(*urlIt);
+ }
+}
+
+void KDBSearchEngine2::editSource()
+{
+ if(!pw)
+ {
+ kdDebug(0) << "We should not be here, editSource called without a pw!" << endl;
+ return;
+ }
+ QString sourceName;
+ sourceName=pw->dbpw->sourceList->currentText();
+
+ if(sources.contains(sourceName))
+ {
+ bool nameIsNew;
+ QString newName;
+ SourceDialog sd;
+ do{
+ sources[sourceName].setDialogValues(&sd);
+ sd.sourceName->setText(sourceName);
+ if(sd.exec()==QDialog::Accepted)
+ {
+ sources[sourceName].getDialogValues(&sd);
+ newName= sd.sourceName->text();
+ } else
+ {
+ return;
+ }
+ nameIsNew=sources.contains(newName);
+ if(newName!=sourceName && !nameIsNew)
+ {
+
+ KMessageBox::error(0,
+ i18n("The name you chose is already used.\nPlease change the source name."),
+ i18n("Name is Not Unique"));
+ kdDebug(0) << "Name is not uniqe" << endl;
+ }
+ }while(newName!=sourceName && !nameIsNew);
+
+ if(newName!=sourceName){
+ sources[newName]=sources[sourceName];
+ sources.remove(sourceName);
+ }
+ pw->dbpw->sourceList->changeItem(newName,pw->dbpw->sourceList->currentItem());
+
+ }
+ else
+ {
+ kdDebug(0) << "source name not found in our MAP. This is a bug." << endl;
+ }
+
+}
+void KDBSearchEngine2::removeSource()
+{
+
+ if(!pw)
+ {
+ kdDebug(0) << "We should not be here, delteSource called without a pw!" << endl;
+ return;
+ }
+ QString sourceName;
+ sourceName=pw->dbpw->sourceList->currentText();
+ sources.remove(sourceName);
+ pw->dbpw->sourceList->removeItem(pw->dbpw->sourceList->currentItem());
+
+}
+
+void KDBSearchEngine2::addSource()
+{
+ QString newName;
+ SourceDialog sd;
+ bool nameIsNew;
+ do{
+ if(sd.exec()==QDialog::Accepted)
+ {
+ newName= sd.sourceName->text();
+ nameIsNew=!sources.contains(newName);
+ }
+ else
+ {
+ return;
+ }
+ // nameIsNew=sources.contains(newName);
+ if(!nameIsNew)
+ {
+ KMessageBox::error(0,i18n("The name you chose is already used.\nPlease change the source name."),
+ i18n("Name is Not Unique"));
+ kdDebug(0) << "Name is not uniqe" << endl;
+ }
+ else
+ {
+ sources[newName].getDialogValues(&sd);
+ }
+ }while(!nameIsNew);
+
+ pw->dbpw->sourceList->insertItem(newName);
+
+
+}
+QString KDBSearchEngine2::searchTranslation( const QString text, int & score )
+{
+ GenericSearchAlgorithm strategy(di,&settings);
+ strategy.setMaxResultNumber(1);
+
+ ExactSearchAlgorithm exact(di,&settings);
+ AlphaSearchAlgorithm alpha(di,&settings);
+ SentenceArchiveSearchAlgorithm sent(di,&settings);
+
+ strategy.addAlgorithm(&exact);
+ strategy.addAlgorithm(&alpha);
+ strategy.addAlgorithm(&sent);
+
+ QueryResult firstRes=strategy.exec(text)[0];
+ score=firstRes.score();
+ return firstRes.result();
+
+}
+
+QString KDBSearchEngine2::fuzzyTranslation( const QString text, int & score )
+{
+ GenericSearchAlgorithm strategy(di,&settings);
+ strategy.setMaxResultNumber(1);
+ ExactSearchAlgorithm exact(di,&settings);
+ AlphaSearchAlgorithm alpha(di,&settings);
+ SentenceArchiveSearchAlgorithm sent(di,&settings);
+ ChunkByChunkSearchAlgorithm sbys(di,&settings);
+ ChunkByChunkSearchAlgorithm wbyw(di,&settings);
+ FuzzyChunkSearchAlgorithm fs(di,&settings);
+ FuzzyChunkSearchAlgorithm fw(di,&settings);
+
+ SentenceChunkFactory sf(di);
+ sbys.setChunkFactory(&sf);
+ fs.setChunkFactory(&sf);
+
+
+ WordChunkFactory wf(di);
+ wbyw.setChunkFactory(&wf);
+ fw.setChunkFactory(&wf);
+
+ strategy.addAlgorithm(&exact);
+ strategy.addAlgorithm(&alpha);
+ strategy.addAlgorithm(&sent);
+ strategy.addAlgorithm(&sbys);
+ //strategy.addAlgorithm(&fs);
+ strategy.addAlgorithm(&fw);
+ strategy.addAlgorithm(&wbyw);
+
+
+ QueryResult firstRes=strategy.exec(text)[0];
+ score=firstRes.score();
+ return firstRes.result();
+
+
+}
+
+//FIXME: ProgressBasr, progressbar,progressbasr
+#include "KDBSearchEngine2.moc"
+
diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/KDBSearchEngine2.h b/kbabel/kbabeldict/modules/dbsearchengine2/KDBSearchEngine2.h
new file mode 100644
index 00000000..0db19c6c
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine2/KDBSearchEngine2.h
@@ -0,0 +1,202 @@
+/* ****************************************************************************
+
+DBSE2
+Andrea Rizzi
+
+**************************************************************************** */
+
+#ifndef DBSEARCH_ENGINE2_H
+#define DBSEARCH_ENGINE2_H
+
+#include <searchengine.h>
+#include <qdialog.h>
+
+#include "database.h"
+#include "dbse2_factory.h"
+#include "preferenceswidget.h"
+#include "dbscan.h"
+#include "sourcedialog.h"
+
+//#include "DBSESettings.h"
+
+class KDBSearchEngine2 : public SearchEngine
+{
+ Q_OBJECT
+
+ public:
+
+ KDBSearchEngine2(QObject *parent=0, const char *name=0);
+ virtual ~KDBSearchEngine2();
+
+ //init if needed.
+ bool init();
+
+ /** @return true, if a search is currently active */
+ bool isSearching() const {return searching;}
+
+ void stopSearch() { if(di) di->stop();}
+
+
+
+ /** @returns true, if it was initialized correctly */
+ bool isReady() const {return iAmReady; }
+
+
+ void saveSettings(KConfigBase *config);
+ void readSettings(KConfigBase *config);
+
+
+ QString translate(const QString text);
+
+ QString fuzzyTranslation(const QString text, int &score);
+ QString searchTranslation(const QString, int &score );
+
+ /**
+ * Finds all messages belonging to package package. If nothing is found,
+ * the list is empty.
+ * @param package The name of the file, something like "kbabel.po"
+ * @param resultList Will contain the found messages afterwards
+ * @param error If an error occured, this should contain a description
+ *
+ * @return true, if successfull
+ */
+ bool messagesForPackage(const QString& package
+ , QValueList<Message>& resultList, QString& error);
+
+ /**
+ * @returns true, if the searchresults are given as rich text
+ * the default implementation returns false
+ */
+ bool usesRichTextResults(){return true;}
+
+ /** @returns true, if the the entries in the database can be edited */
+ bool isEditable(){return false;}
+
+ /**
+ * @returns a widget which lets the user setup all preferences of this
+ * search engine. The returned widget should not be bigger than
+ * 400x400. If you need more space, you maybe want to use
+ * a tabbed widget.
+ * @param parent the parent of the returned widget
+ */
+ virtual PrefWidget* preferencesWidget(QWidget *parent);
+
+ /** @returns information about this SearchEngine */
+ virtual const KAboutData *about() const;
+
+ /** @returns the i18n name of this search engine */
+ QString name() const {return i18n("DB SearchEngine II");}
+
+ /** @returns a untranslated name of this engine */
+ QString id() const {return "dbse2";}
+
+ /** @returns the last error message */
+ QString lastError() {return lasterror;}
+
+
+ /**
+ * sets the engine to always ask the preferences dialog for settings
+ * if is existing before starting the search.
+ */
+ virtual void setAutoUpdateOptions(bool activate)
+ {
+ autoupdate=activate;
+ }
+
+
+
+ public slots:
+
+ void receiveResult(QueryResult r);
+
+ /**
+ * starts a search for string s in the original text
+ * @returns false, if an error occured. Use @ref lastError
+ * to get the last error message
+ */
+ bool startSearch(QString s);
+
+ /**
+ * starts a search for string s in the translated text
+ * @returns false, if an error occured. Use @ref lastError
+ * to get the last error message
+ */
+ bool startSearchInTranslation(QString s);
+
+
+ /** stops a search */
+ // virtual void stopSearch() ;
+
+
+ /**
+ * This method allows a search engine to use different settings depending
+ * on the edited file. The default implementation does nothing.
+ * @param file The edited file with path
+ */
+ // virtual void setEditedFile(QString file);
+
+ /**
+ * This method allows a search engine to use different settings depending
+ * on the edited package. The default implementation does nothing.
+ * @param package The name of the package, that is currently translated.
+ */
+ // virtual void setEditedPackage(QString package);
+
+ /**
+ * This method allows a search engine to use different settings depending
+ * on the language code. The default implementation does nothing.
+ * @param lang The current language code (e.g. de).
+ */
+ // virtual void setLanguageCode(QString lang);
+ // virtual void setLanguage(QString languageCode, QString languageName);
+
+
+
+ /**
+ * This method is called, if something has been changed in the
+ * current file. See @ref setEditedFile if you want to know the file
+ * name
+ * @param orig the original string
+ * @param translation the translated string
+ */
+
+ void stringChanged( QString orig, QString translated
+ , QString description);
+
+ //void scan();
+
+ void setLastError(QString er);
+
+ //Slots for preference dialog
+ // void scanSource(QString sourceName);
+ void scanNowPressed();
+ void scanAllPressed();
+ void editSource();
+ void removeSource();
+ void addSource();
+
+
+ private:
+ DataBaseInterface *di;
+ bool searching;
+ bool iAmReady;
+ bool autoupdate;
+ QString lasterror;
+ KDB2PreferencesWidget *pw;
+
+ //PrefWidg -> DBSE
+ void updateSettings();
+ //DBSE -> PrefWidg
+ void setSettings();
+
+ DBSESettings settings;
+ QString dbDirectory;
+ bool autoAdd,useSentence,useGlossary,useExact;
+ bool useDivide,useAlpha,useWordByWord,useDynamic;
+ uint numberOfResult;
+ QMap<QString,MessagesSource> sources;
+
+};
+
+
+#endif // SEARCH_ENGINE2_H
diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/Makefile.am b/kbabel/kbabeldict/modules/dbsearchengine2/Makefile.am
new file mode 100644
index 00000000..cdcd3083
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine2/Makefile.am
@@ -0,0 +1,34 @@
+## Makefile.am for DBSE2
+
+# this has all of the subdirectories that make will recurse into. if
+# there are none, comment this out
+#SUBDIRS =
+
+
+# this is the program that gets installed. it's name is used for all
+# of the other Makefile.am variables
+kde_module_LTLIBRARIES = kbabeldict_dbsearchengine2.la
+
+# set the include path for X, qt and KDE
+INCLUDES = -I$(srcdir)/../.. -I$(srcdir)/../../../common $(all_includes) -I$(DBIV_INCLUDES)
+
+# which sources should be compiled for kbabel
+kbabeldict_dbsearchengine2_la_SOURCES = dbscan.cpp preferenceswidget.cpp dbse2.ui KDBSearchEngine2.cpp database.cpp dbentries.cpp dbse2_factory.cpp sourcedialog.ui algorithms.cpp chunk.cpp
+
+#kbabeldict_dbsearchengine2_la_SOURCES = KDBSearchEngine2.cpp database.cpp dbentries.cpp dbse2_factory.cpp
+kbabeldict_dbsearchengine2_la_LIBADD = ../../libkbabeldictplugin.la ../../../common/libkbabelcommon.la $(LIB_KDEUI) $(LIB_KIO) $(LIB_DBIV)_cxx
+kbabeldict_dbsearchengine2_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined -L$(DBIV_LDFLAGS)
+
+
+# these are the headers for your project
+noinst_HEADERS = KDBSearchEngine2.h database.h dbentries.h dbse2_factory.h
+#chunk.h algorithms.h
+
+
+# let automoc handle all of the meta source files (moc)
+METASOURCES = AUTO
+
+kde_services_DATA = dbsearchengine2.desktop
+EXTRA_DIST = $(kde_services_DATA)
+
+
diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/README b/kbabel/kbabeldict/modules/dbsearchengine2/README
new file mode 100644
index 00000000..907ab84e
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine2/README
@@ -0,0 +1,21 @@
+If you want to test this new plugin:
+launch
+# make ; make install in this directory
+then (to create the database)
+# source compile
+# cp scan ~/mytestdir
+# cd ~/mytestdir
+# ./scan file.po (I suggest to download and scan $LANG.messages)
+
+ok now you can launch kbabel, you should be in the same
+directory you launched "scan" from.
+
+# kbabel
+
+
+change kbabel settings to use "DB Search Engine II" or use
+CTRL+2 to search.
+
+
+Bye
+Andrea
diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/algorithms.cpp b/kbabel/kbabeldict/modules/dbsearchengine2/algorithms.cpp
new file mode 100644
index 00000000..0ca040e8
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine2/algorithms.cpp
@@ -0,0 +1,425 @@
+//
+// C++ Implementation: algorithms
+//
+// Description:
+//
+//
+// Author: Andrea Rizzi <rizzi@kde.org>, (C) 2003
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#include "algorithms.h"
+#include <qstringlist.h>
+#include <kdebug.h>
+
+//FIXME: remove
+#define i18n (const char*)
+
+DataBaseInterface::ResultList ExactSearchAlgorithm::exec(const QString& query )
+{
+ DataBaseInterface::ResultList res;
+ DataBaseInterface::MainEntry e=di->get(query,0);
+
+ QStringList trs=e.second.getTranslations();
+
+ for(QStringList::iterator it=trs.begin();it!=trs.end();++it)
+ {
+
+ emit newResult(QueryResult(*it,e.first.getString(),settings->scoreExact));
+
+ res.push_back(QueryResult(*it));
+ }
+ kdDebug(0) <<"Exact algo found " << res.count() << "entries" << endl;
+ return res;
+}
+
+
+DataBaseInterface::ResultList GenericSearchAlgorithm::exec(const QString& query )
+{
+ DataBaseInterface::ResultList res;
+ // ExactSearchAlgorithm exact(query,settings);
+ uint countResults=0;
+ for(QValueList<AbstractSearchAlgorithm *>::iterator algoit = algoChain.begin(); algoit!=algoChain.end() && countResults < maxResults; algoit++)
+ {
+ connect(*algoit,SIGNAL(newResult(QueryResult)),this,SIGNAL(newResult(QueryResult)));
+ kdDebug(0) << "Algo pointer" << (*algoit) << endl;
+ res+=(*algoit)->exec(query);
+ countResults=res.count();
+ kdDebug(0) << "Count = " << countResults << endl;
+ disconnect(*algoit,SIGNAL(newResult(QueryResult)),this,SIGNAL(newResult(QueryResult)));
+ }
+ return res;
+}
+
+void GenericSearchAlgorithm::addAlgorithm( AbstractSearchAlgorithm * algo )
+{
+ algoChain.append(algo);
+}
+
+DataBaseInterface::ResultList AlphaSearchAlgorithm::exec( const QString & query )
+{
+ DataBaseInterface::ResultList res;
+ DBItemMultiIndex::IndexList il=di->getAlpha(query);
+
+ for(DBItemMultiIndex::IndexList::iterator it=il.begin();it!=il.end()&&!di->stopNow();++it)
+ {
+ DataBaseInterface::MainEntry e=di->getFromIndex(*it);
+ QStringList trs=e.second.getTranslations();
+ for(QStringList::iterator it=trs.begin();it!=trs.end() && !di->stopNow();++it)
+ {
+ QueryResult r(di->format(di->simple(*it,true),query),e.first.getString(),settings->scoreAlpha);
+ emit newResult(r);
+ res.push_back(r);
+ }
+ }
+ kdDebug(0) <<"Alpha algo found " << res.count() << "entries" << endl;
+
+ return res;
+}
+
+DataBaseInterface::ResultList SentenceArchiveSearchAlgorithm::exec( const QString & query )
+{
+ DataBaseInterface::ResultList res;
+
+ DataBaseInterface::MainEntry e = di->getSentence(query);
+
+ QStringList trs=e.second.getTranslations();
+
+ kdDebug(0) << "Count in sentence archive " << trs.count()<< endl;
+
+ for(QStringList::iterator it=trs.begin();it!=trs.end();++it)
+ {
+ QueryResult r(di->format(di->simple(*it,true),query),e.first.getString(),settings->scoreSentence);
+ emit newResult(r);
+
+ res.push_back(r);
+ }
+ kdDebug(0) <<"Sentence algo found " << res.count() << "entries" << endl;
+
+ return res;
+}
+
+DataBaseInterface::ResultList ChunkByChunkSearchAlgorithm::exec( const QString & query )
+{
+ ResultList res;
+ factory->setQuery(query);
+ QPtrList<AbstractChunk> chunks=factory->chunks();
+ kdDebug(0) << "Number of chunks " << chunks.count() << endl;
+ chunks.setAutoDelete(true); //I should delete the chunks myself
+ QStringList querySeparators=factory->separators();
+
+ //This prevents recursive loop.
+ if (chunks.count()<=1) return res;
+
+ QStringList translations,tmpTranslations;
+
+ translations.push_back(""); //FIXME this is needed to start , but is not good
+ int finalscore=0;
+ int i=0;
+ QMap<QString,bool> translationUsed;
+
+ //Loop on all chunk
+ for(AbstractChunk *it=chunks.first();it && !di->stopNow(); it=chunks.next())
+ {
+ kdDebug(0) << "Process next chunk" << endl;
+ int chunkscore=0;
+ QValueList<QueryResult> r=it->translations();
+ kdDebug(0) << "Number of results for this chunk " << r.count() << endl;
+
+ if(r.count()<1) {
+ // kdDebug(0) << "Nothing found for:" << it->translations() << endl;
+ chunkscore=-10;
+
+ }
+ else
+ {
+ //FIXME: check this, why 0? it is the best one?
+ chunkscore=r[0].score();
+ kdDebug(0) << "ChunkScore " << chunkscore << endl;
+ tmpTranslations.clear();
+
+
+ //Loop on results
+ translationUsed.clear();
+ for(ResultList::iterator it1=r.begin();it1!=r.end() &&!di->stopNow(); ++it1)
+ {
+ QString chunkTranslation= (*it1).result();
+ if(!translationUsed.contains(chunkTranslation))
+ {
+ translationUsed[chunkTranslation]=true;
+ kdDebug(0) << "a translation is: " << chunkTranslation << endl;
+ for(QStringList::iterator it2=translations.begin();it2!=translations.end() && !di->stopNow() ; it2++)
+ {
+ QString prevTranslation=*it2;
+ tmpTranslations.push_back(prevTranslation+chunkTranslation+querySeparators[i]);
+ kdDebug(0) << "..appending it to " << prevTranslation << endl;
+ }
+ }
+ }
+
+ translations=tmpTranslations;
+
+ }
+
+ //kdDebug(0) << it-> << r[0].result() << "#" << querySeparators[i] << endl;
+ i++;
+ finalscore+=chunkscore;
+
+ kdDebug(0) << "partial score " << finalscore;
+ }
+ kdDebug(0) << "this is finishd" << endl;
+ if(settings->scoreChunkByChunk==0)
+ settings->scoreChunkByChunk=1;
+// FIXME:fix the score system
+// finalscore/=(i*100*100/settings->scoreChunkByChunk); //change 100 to 120(?) to lower this result (done)
+
+ if (finalscore<50) return res;
+
+ for(QStringList::iterator it2=translations.begin();it2!=translations.end() && !di->stopNow() ; it2++)
+ {
+ QString theTranslation=*it2;
+ QueryResult qr(di->format(theTranslation,query),i18n("CHUNK BY CHUNK"),finalscore);
+ qr.setRichOriginal(i18n("<h3>Chunk by chunk</h3>CHANGE THIS TEXT!!!!This translation is"
+ "obtained translating the sentences and using a"
+ "fuzzy sentence translation database.<br>"
+ " <b>Do not rely on it</b>. Translations may be fuzzy.<br>"));
+ qr.setRichResult("<font color=#800000>"+theTranslation+"</font>") ;
+ emit newResult(qr);
+ res.push_back(qr);
+ }
+
+
+ return res;
+
+
+}
+
+ChunkByChunkSearchAlgorithm::ChunkByChunkSearchAlgorithm( DataBaseInterface * dbi, DBSESettings * sets ): AbstractSearchAlgorithm(dbi,sets) , factory(0)
+{
+
+}
+
+
+SentenceArchiveSearchAlgorithm::SentenceArchiveSearchAlgorithm( DataBaseInterface * dbi, DBSESettings * sets ): AbstractSearchAlgorithm(dbi,sets)
+{
+}
+
+FuzzyChunkSearchAlgorithm::FuzzyChunkSearchAlgorithm( DataBaseInterface * dbi, DBSESettings * sets ) : AbstractSearchAlgorithm(dbi,sets)
+{
+
+}
+
+
+DataBaseInterface::ResultList FuzzyChunkSearchAlgorithm::exec( const QString & query )
+{
+ //FIXME: this code is shit too
+ ResultList res;
+ factory->setQuery(query);
+ QPtrList<AbstractChunk> querychunks = factory->chunks();
+ querychunks.setAutoDelete(true);
+
+ typedef QMap<QString,QValueList<unsigned int> > ResultMap;
+ ResultMap rmap; //result of words index query
+ unsigned int notfound=0,frequent=0,nchunks = querychunks.count();
+
+ //Get index list for each word
+ for(AbstractChunk *it=querychunks.first(); it &&!di->stopNow() ; it=querychunks.next() )
+ {
+ QValueList<uint> locations = (*it).locationReferences();
+
+ if(locations.count()>0)
+ {
+ rmap[(*it).chunkString()] = locations;
+
+ if(locations.count()>1000) //FIXME NORMALIZE THIS!!!
+ {
+ frequent++;
+ kdDebug(0) << "\""<<(*it).chunkString() << "\" is frequent" <<endl;
+ }
+ }
+ else
+ notfound++;
+
+ }
+
+
+ //Now we have a map (rmap) "word in query->list of occurency"
+
+ QValueList<unsigned int>::iterator countpos[nchunks+1];
+
+
+ QValueList<unsigned int> il;
+ for(int i = 0;i<=nchunks&&!di->stopNow();i++)
+ countpos[i]=il.end();
+
+ unsigned int bestcount=0;
+ while(!rmap.isEmpty())
+ {
+ unsigned int ref,count;
+ ref=(unsigned int)-1;
+ count=0;
+
+
+ //This will find the min head and count how many times it occurs
+ for(ResultMap::iterator it = rmap.begin();it!=rmap.end()&&!di->stopNow();++it)
+ {
+ unsigned int thisref=it.data().first();
+ if(thisref<ref)
+ {
+ ref=thisref;
+ count=0;
+ }
+ if(thisref==ref)
+ {
+ count++;
+ }
+
+ }
+
+
+ for(ResultMap::iterator it = rmap.begin();it!=rmap.end()&&!di->stopNow();)
+ {
+ it.data().remove(ref);
+
+ //kdDebug(0)<< ((frequent<(nwords-notfound)) && (it.data().count()>350)) <<endl;
+ //FIXME: I think the frequent word check is not in the right place
+ if(it.data().isEmpty() || (((frequent+notfound)<nchunks) && (it.data().count()>1000)))
+ //very dirty hack...
+ {
+
+ ResultMap::iterator it2=it;
+ it++;
+ rmap.remove(it2);
+ }
+ else it++;
+
+ }
+
+ //This should be configurable or optimized:
+ if(count>=(nchunks-notfound)*0.50 && count!=0)
+ {
+ il.insert(countpos[count],ref);
+ for(unsigned int i = nchunks;i>=count;i--)
+ if(countpos[i]==countpos[count])
+ countpos[i]--;
+ }
+ }
+
+ //loop on number of words found
+ int bestscore=0;
+
+ for(unsigned int wf=nchunks;wf>0;wf-- ){
+ for(QValueList<unsigned int>::iterator it=countpos[wf];it!=countpos[wf-1] ;++it)
+ { //loop on entries with same number of word found
+ DataBaseInterface::MainEntry e;
+ e=di->getFromIndex(*it);
+ QStringList trs=e.second.getTranslations();
+ for(QStringList::iterator it=trs.begin();it!=trs.end()&&!di->stopNow();++it)
+ {
+ unsigned int cinr=factory->chunks(*it).count(); //chunk in result
+ //compute a score, lets kbabel sort now, it should be fast...
+ int score=90*wf/nchunks-(signed int)90*(((nchunks-cinr)>0)?(nchunks-cinr):(cinr-nchunks))/(nchunks*10);
+ if(score>bestscore) bestscore=score;
+ if(score>bestscore*0.40)
+ {
+ // kdDebug(0) << "s: "<<score << " wf: "<<wf<<" nwords: "<<nwords<<" winr: "<<winr
+ // <<" 90*wf/nwords: "<<90*wf/nwords << " -:" << 90*(((nwords-winr)>0)?(nwords-winr):(winr-nwords))/(nwords*10)<< endl;
+ // FIXME: format better the richtext
+ QString ori=e.first.getString();
+ QString re=di->format(di->simple(*it,true),query);
+ QueryResult r(re,ori,score);
+ for(QPtrListIterator<AbstractChunk> it(querychunks); it.current() && di->stopNow() ; ++it){
+ ori=ori.replace(QRegExp((*it)->chunkString(),false),"<font color=#000080><u><b>"+(*it)->chunkString()+"</b></u></font>");
+ }
+ r.setRichOriginal(ori);
+ if(!di->stopNow())
+ emit newResult(r);
+ res.push_back(r);
+ }
+ }
+ }
+ }
+ return res;
+
+}
+
+DataBaseInterface::ResultList CorrelationSearchAlgorithm::exec( const QString & query )
+{
+ //FIXME, this code is shit.
+ DataBaseInterface::ResultList res;
+ if(di->words(query).count()>1) return res;
+ QMap<QString,float> corRes = di->correlation(query,0,false);
+ float max=0,max1=0,max2=0;
+ QString best,best1,best2;
+
+ for(QMap<QString,float>::iterator it = corRes.begin(); it !=corRes.end(); ++it)
+ {
+ if(it.data()>max)
+ {
+ max2=max1;
+ best2=best1;
+ max1=max;
+ best1=best;
+ best = it.key();
+ max=it.data();
+
+ }
+
+
+ }
+ if(!best.isEmpty())
+ {
+ double myscore=0.01*max*settings->scoreDynamic;
+ QueryResult r(di->format(best,query),i18n("DYNAMIC DICT:"),myscore);
+ r.setRichOriginal(i18n("<h3>Dynamic Dictionary</h3>This is a dynamic dictionary created"
+ " looking for correlation of original and translated words.<br>"
+ " <b>Do not rely on it</b>. Translations may be fuzzy.<br>"));
+ r.setRichResult("<font size=+2 color=#A00000>"+di->format(best,query)+"</font>") ;
+ res.push_back(r);
+ if(!di->stopNow())
+ emit newResult(r);
+ }
+ if(!best1.isEmpty())
+ {
+ double myscore=0.01*max1*settings->scoreDynamic;
+ QueryResult r(di->format(best1,query),i18n("DYNAMIC DICT:"),myscore);
+ r.setRichOriginal(i18n("<h3>Dynamic Dictionary</h3>This is a dynamic dictionary created"
+ " looking for correlation of original and translated words.<br>"
+ " <b>Do not rely on it</b>. Translations may be fuzzy.<br>"));
+ r.setRichResult("<font size=+2 color=#800000>"+di->format(best1,query)+"</font>") ;
+ res.push_back(r);
+ if(!di->stopNow())
+ emit newResult(r);
+ }
+
+ kdDebug(0) << "Correlation algorithm found" << res.count() << "results";
+ return res;
+
+}
+
+GenericSearchAlgorithm::GenericSearchAlgorithm( DataBaseInterface * dbi, DBSESettings * sets ): AbstractSearchAlgorithm(dbi,sets)
+{
+ maxResults = 5; //FIXME use as default somthing from DBSESettings
+}
+
+SingleWordSearchAlgorithm::SingleWordSearchAlgorithm( DataBaseInterface * dbi, DBSESettings * sets ) : GenericSearchAlgorithm(dbi,sets),
+ exact(dbi,sets), alpha(dbi,sets), sentence(dbi,sets), corr(dbi,sets), chunk(dbi,sets),casefactory(dbi)
+ {
+ addAlgorithm(&exact);
+ addAlgorithm(&alpha);
+ addAlgorithm(&sentence);
+ chunk.setChunkFactory(&casefactory);
+ addAlgorithm(&chunk);
+ addAlgorithm(&corr);
+}
+
+DataBaseInterface::ResultList SingleWordSearchAlgorithm::exec( const QString & query )
+{
+ if(di->words(query).count()>1)
+ return ResultList();
+ return GenericSearchAlgorithm::exec(query);
+}
+
+
+//#include "algorithms.moc"
diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/algorithms.h b/kbabel/kbabeldict/modules/dbsearchengine2/algorithms.h
new file mode 100644
index 00000000..5f9ee682
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine2/algorithms.h
@@ -0,0 +1,157 @@
+//
+// C++ Interface: strategies
+//
+// Description:
+//
+//
+// Author: Andrea Rizzi <rizzi@kde.org>, (C) 2003
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef DBSE2_STRATEGIES_H
+#define DBSE2_STRATEGIES_H
+
+#include "database.h"
+#include "chunk.h"
+#include <qobject.h>
+
+class AbstractSearchAlgorithm : public QObject
+{
+ Q_OBJECT
+ public:
+
+ typedef QValueList<QueryResult> ResultList;
+
+ AbstractSearchAlgorithm(DataBaseInterface *dbi,DBSESettings *sets)
+ {
+ di=dbi;
+ settings=sets;
+ }
+ /**
+ * this contains the algo and return some results.
+ */
+ virtual DataBaseInterface::ResultList exec(const QString& query)=0;
+
+ signals:
+ void newResult(QueryResult);
+
+ protected:
+ DataBaseInterface *di;
+ DBSESettings *settings;
+
+};
+
+
+
+class ExactSearchAlgorithm : public AbstractSearchAlgorithm
+{
+ Q_OBJECT
+ public:
+ ExactSearchAlgorithm(DataBaseInterface *dbi,DBSESettings *sets) : AbstractSearchAlgorithm(dbi,sets) {}
+
+ virtual DataBaseInterface::ResultList exec(const QString& query);
+};
+
+class AlphaSearchAlgorithm : public AbstractSearchAlgorithm
+{
+ Q_OBJECT
+ public:
+ AlphaSearchAlgorithm(DataBaseInterface *dbi,DBSESettings *sets) : AbstractSearchAlgorithm(dbi,sets) {}
+
+ virtual DataBaseInterface::ResultList exec(const QString& query);
+};
+
+class SentenceArchiveSearchAlgorithm : public AbstractSearchAlgorithm
+{
+ Q_OBJECT
+ public:
+ SentenceArchiveSearchAlgorithm(DataBaseInterface *dbi,DBSESettings *sets) ;
+
+ virtual DataBaseInterface::ResultList exec(const QString& query);
+};
+
+class ChunkByChunkSearchAlgorithm : public AbstractSearchAlgorithm
+{
+ Q_OBJECT
+ public:
+ ChunkByChunkSearchAlgorithm(DataBaseInterface *dbi,DBSESettings *sets);
+
+ virtual DataBaseInterface::ResultList exec(const QString& query);
+
+ void setChunkFactory(AbstractChunkFactory *_factory)
+ {
+ factory=_factory;
+ }
+ protected:
+ AbstractChunkFactory *factory;
+};
+
+class FuzzyChunkSearchAlgorithm : public AbstractSearchAlgorithm
+{
+ Q_OBJECT
+ public:
+ FuzzyChunkSearchAlgorithm(DataBaseInterface *dbi,DBSESettings *sets);
+
+ virtual DataBaseInterface::ResultList exec(const QString& query);
+ void setChunkFactory(AbstractChunkFactory *_factory)
+ {
+ factory=_factory;
+ }
+ protected:
+ AbstractChunkFactory *factory;
+};
+
+class GenericSearchAlgorithm : public AbstractSearchAlgorithm
+{
+ Q_OBJECT
+ public:
+ GenericSearchAlgorithm(DataBaseInterface *dbi,DBSESettings *sets) ;
+
+ virtual ResultList exec(const QString& query);
+
+ void addAlgorithm(AbstractSearchAlgorithm *algo);
+ void setMaxResultNumber(uint num){maxResults=num;}
+
+
+ protected:
+ QValueList<AbstractSearchAlgorithm *> algoChain;
+ uint maxResults;
+ };
+
+
+class CorrelationSearchAlgorithm : public AbstractSearchAlgorithm
+{
+ Q_OBJECT
+ public:
+ CorrelationSearchAlgorithm(DataBaseInterface *dbi,DBSESettings *sets) : AbstractSearchAlgorithm(dbi,sets) {}
+ virtual ResultList exec(const QString& query);
+};
+
+
+
+class SingleWordSearchAlgorithm : public GenericSearchAlgorithm
+{
+ Q_OBJECT
+ public:
+ SingleWordSearchAlgorithm(DataBaseInterface *dbi,DBSESettings *sets);
+ virtual DataBaseInterface::ResultList exec(const QString& query);
+
+ private:
+ ExactSearchAlgorithm exact;
+ AlphaSearchAlgorithm alpha;
+ SentenceArchiveSearchAlgorithm sentence;
+ CorrelationSearchAlgorithm corr;
+ ChunkByChunkSearchAlgorithm chunk;
+ CaseBasedWordChunkFactory casefactory;
+};
+
+
+class UpdateChunkIndexAlgorithm
+{
+
+};
+
+
+
+#endif //DBSE2_STRATEGIES_H
diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/chunk.cpp b/kbabel/kbabeldict/modules/dbsearchengine2/chunk.cpp
new file mode 100644
index 00000000..7c62748a
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine2/chunk.cpp
@@ -0,0 +1,203 @@
+//
+// C++ Implementation: chunk
+//
+// Description:
+//
+//
+// Author: Andrea Rizzi <rizzi@kde.org>, (C) 2003
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#include "chunk.h"
+#include "algorithms.h"
+#include <kdebug.h>
+
+
+
+AbstractChunk::~AbstractChunk( )
+{
+}
+
+WordChunk::WordChunk( DataBaseInterface * di, QString _word ) : AbstractChunk(di)
+{
+ word=_word;
+}
+
+QValueList<QueryResult> WordChunk::translations( )
+{
+ DataBaseInterface::ResultList r;
+ SingleWordSearchAlgorithm sa(di,di->getSettings());
+ r=sa.exec(word);
+ return r;
+}
+
+//QValueList<QueryResult> WordChunk::translationsFromReference( uint reference )
+//{
+//}
+
+QValueList< uint > WordChunk::locationReferences( )
+{
+ QValueList<uint> res=di->getWordIndex(word);
+ kdDebug(0) << "Number of locations " << res.count() <<endl ;
+ return res;
+/* DBItemMainKey *k = new DBItemMainKey(word);
+ DBItemMultiIndex *d = new DBItemMultiIndex();
+ if(wordsindex->get(k,d)!=DB_NOTFOUND)
+ return d->getList();
+ else
+ return QValueList<uint> tmpList;
+*/
+}
+
+void WordChunk::setLocationReferences( QValueList< uint > )
+{
+}
+
+SentenceChunk::SentenceChunk( DataBaseInterface * di, QString _sentence ): AbstractChunk(di)
+{
+ sentence=_sentence;
+}
+
+QValueList<QueryResult> SentenceChunk::translations( )
+{
+ GenericSearchAlgorithm g(di,di->getSettings());
+
+ ExactSearchAlgorithm e(di,di->getSettings());
+ AlphaSearchAlgorithm a(di,di->getSettings());
+ SentenceArchiveSearchAlgorithm s(di,di->getSettings());
+
+ g.addAlgorithm(&e);
+ g.addAlgorithm(&a);
+ g.addAlgorithm(&s);
+
+ return g.exec(sentence);
+
+}
+
+//QValueList<QueryResult> SentenceChunk::translationsFromReference( uint reference )
+//{
+//
+//}
+
+QValueList< uint > SentenceChunk::locationReferences( )
+{
+}
+
+void SentenceChunk::setLocationReferences( QValueList< uint > )
+{
+}
+
+QPtrList< AbstractChunk> WordChunkFactory::chunks()
+{
+ QString str=di->simple(string);
+ QPtrList<AbstractChunk> list;
+ if(str.isEmpty()) return list;
+ _separators.clear();
+ kdDebug(0) << "Word chunks of:" <<str << endl;
+ int pos;
+ QString sep;
+ QRegExp r("(\\s)");
+ do {
+ pos=r.search(str);
+
+ sep=r.cap(1);
+ if(!str.left(pos).isEmpty()){
+ //WordChunk *c=new WordChunk(di,di->simple(str.left(pos)))
+ list.append(new WordChunk(di,str.left(pos)));
+ _separators.append(sep);
+ }
+ else
+ {
+ uint current=_separators.count()-1;
+ _separators[current]=_separators[current]+sep;
+ }
+ str=str.remove(0,pos+1);
+ } while(!str.isEmpty() && pos != -1);
+
+ return list;
+}
+
+
+
+QPtrList<AbstractChunk> SentenceChunkFactory::chunks()
+{
+ QString str=string;
+ QPtrList<AbstractChunk> list;
+ if(str.isEmpty()) return list;
+
+ // kdDebug(0) << s << endl;
+
+ int pos;
+
+
+ do {
+ QRegExp re("((\\.|;|\\?|\\!|:)( |$|\\\\n\\n))");
+ pos=re.search(str);
+ QString sep=re.cap(1);
+
+ if(!str.left(pos).isEmpty())
+ {
+ list.append(new SentenceChunk(di,str.left(pos).stripWhiteSpace()));
+ _separators.append(sep);
+ }
+ else
+ {
+ uint current=_separators.count()-1;
+ _separators[current]=_separators[current]+sep;
+ }
+
+ str=str.remove(0,pos+re.cap(1).length());
+ } while(!str.isEmpty() && pos != -1);
+
+
+ return list;
+
+}
+QPtrList< AbstractChunk > CaseBasedWordChunkFactory::chunks( )
+{
+ QString str=string;
+ QPtrList<AbstractChunk> list;
+ if(str.isEmpty()) return list;
+ uint slen=str.length();
+ kdDebug(0) << "CaseWordChunk string:" << str << endl;
+ QString tmpWord;
+ bool upcase;
+ for(uint i=0;i<=slen;i++)
+ {
+ bool tmpCase=(str[i]==str[i].upper());
+ if(upcase!=tmpCase)
+ {
+ if(!tmpWord.isEmpty() && !tmpWord.isNull()){
+ list.append(new WordChunk(di,tmpWord));
+ _separators.append("");
+ }
+ kdDebug(0) << "CaseWordChunk:" << tmpWord << endl;
+ tmpWord="";
+
+ }
+ tmpWord+=str[i];
+ upcase=tmpCase;
+ }
+
+ return list;
+}
+
+WordChunkFactory::WordChunkFactory( DataBaseInterface * _di ) : AbstractChunkFactory(_di)
+{
+}
+
+SentenceChunkFactory::SentenceChunkFactory( DataBaseInterface * _di ): AbstractChunkFactory(_di)
+{
+}
+
+CaseBasedWordChunkFactory::CaseBasedWordChunkFactory( DataBaseInterface * _di ): AbstractChunkFactory(_di)
+{
+}
+
+
+
+
+
+
+
diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/chunk.h b/kbabel/kbabeldict/modules/dbsearchengine2/chunk.h
new file mode 100644
index 00000000..5c5fcb93
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine2/chunk.h
@@ -0,0 +1,151 @@
+//
+// C++ Interface: chunk
+//
+// Description:
+//
+//
+// Author: Andrea Rizzi <rizzi@kde.org>, (C) 2003
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef DBSE2_CHUNK_H
+#define DBSE2_CHUNK_H
+#include <qstring.h>
+#include <qvaluelist.h>
+#include "database.h"
+
+/**
+ * Abstract class for text chunks.
+ * Examples of chunks are "Words" or "Sentences"
+ * This abstraction allow to use generic algorithm on chunks,
+ * like chunkByChunk translation or chunk indexing.
+ */
+class AbstractChunk
+{
+ public:
+ AbstractChunk(DataBaseInterface *_di) {di=_di;}
+ virtual ~AbstractChunk();
+ /**
+ * This function should return a list of translation for the current chunk.
+ */
+ virtual QValueList<QueryResult> translations()=0;
+
+ //FIXME: is this in the right place, better in factory? check that stuff
+ //virtual QValueList<QueryResult> translationsFromReference(uint reference)=0;
+ virtual QValueList<uint> locationReferences()=0;
+ virtual void setLocationReferences(QValueList<uint>)=0;
+ virtual QString chunkString()=0;
+
+ protected:
+ DataBaseInterface *di;
+};
+
+/**
+ * Concrete impl of Chunk, in this case chunks are words.
+ */
+class WordChunk : public AbstractChunk
+{
+ public:
+ WordChunk(DataBaseInterface *di,QString _word);
+ virtual QValueList<QueryResult> translations();
+ //virtual QValueList<QueryResult> translationsFromReference(uint reference);
+ virtual QValueList<uint> locationReferences();
+ virtual void setLocationReferences(QValueList<uint>);
+ virtual QString chunkString(){return word;}
+
+ //static QValueList<WordChunk> divide(QString);
+ private:
+ QString word;
+};
+
+/**
+ * Concrete impl of Chunk, in this case chunks are sentences.
+ */
+class SentenceChunk : public AbstractChunk
+{
+ public:
+ SentenceChunk(DataBaseInterface *di,QString _sentence);
+ virtual QValueList<QueryResult> translations();
+ //virtual QValueList<QueryResult> translationsFromReference(uint reference);
+ virtual QValueList<uint> locationReferences();
+ virtual void setLocationReferences(QValueList<uint>);
+ virtual QString chunkString(){return sentence;}
+
+ // static QValueList<SentenceChunk> divide(QString);
+
+ private:
+ QString sentence;
+};
+
+
+/**********************************
+ CHUNK FACTORIES
+**********************************/
+
+
+class AbstractChunkFactory
+{
+ public:
+ AbstractChunkFactory(DataBaseInterface *_di)
+ {
+ di=_di;
+ }
+ virtual ~AbstractChunkFactory(){}
+ virtual QPtrList<AbstractChunk> chunks()=0;
+ /**
+ Change th string and return the chunks
+ */
+ virtual QPtrList<AbstractChunk> chunks(const QString& s)
+ {
+ string=s;
+ return chunks();
+ }
+ /**
+ * Returns the list of separators of last @ref chunks() call
+ */
+
+ virtual QStringList separators(){ return _separators;}
+ void setQuery(const QString& s)
+ {
+ string=s;
+ }
+ protected:
+ QString string;
+ QStringList _separators;
+ DataBaseInterface *di;
+};
+
+class WordChunkFactory : public AbstractChunkFactory
+{
+ public:
+ WordChunkFactory(DataBaseInterface *_di);
+ /**
+ YOU SHOULD DELETE THE CHUNKS!!
+ */
+ virtual QPtrList<AbstractChunk> chunks();
+};
+
+class CaseBasedWordChunkFactory : public AbstractChunkFactory
+{
+ public:
+ CaseBasedWordChunkFactory(DataBaseInterface *_di);
+ /**
+ YOU SHOULD DELETE THE CHUNKS!!
+ */
+ virtual QPtrList<AbstractChunk> chunks();
+};
+
+class SentenceChunkFactory : public AbstractChunkFactory
+{
+ public:
+ SentenceChunkFactory(DataBaseInterface *_di);
+
+ /**
+ YOU SHOULD DELETE THE CHUNKS!!
+ */
+ virtual QPtrList<AbstractChunk> chunks();
+};
+
+
+#endif //_CHUNK_H_
diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/database.cpp b/kbabel/kbabeldict/modules/dbsearchengine2/database.cpp
new file mode 100644
index 00000000..ea0e8379
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine2/database.cpp
@@ -0,0 +1,752 @@
+/*
+
+DBSE 3
+(c) 2000-2003 Andrea Rizzi
+License: GPLv2
+
+*/
+#include <math.h>
+#include "database.h"
+
+#include <qregexp.h>
+#include <qdict.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+
+#define i18n (const char*)
+
+
+
+
+
+
+DataBase::DataBase(QString dbpath,QString dbname, QString dblang) : Db(0,DB_CXX_NO_EXCEPTIONS)
+{
+
+ filename=dbpath+"."+dblang+".db";
+ database=dbname;
+
+}
+
+int DataBase::open(DBTYPE type,unsigned int flags)
+{
+ int ret;
+ ret = Db::open(
+#if DB_VERSION_MINOR > 0
+ NULL,
+#endif
+ (const char*)filename.local8Bit(),(const char *)database.local8Bit(),type,flags,0644);
+ mytype=type;
+ return ret;
+}
+
+unsigned int DataBase::getLast()
+{
+ if(mytype!=DB_RECNO)
+ return 0;
+
+ Dbc *cur;
+ cursor(0,&cur,0);
+ DBItemNum index;
+ DBItemMainKey key;
+ cur->get(&index,&key,DB_LAST);
+ return index.getNum();
+
+}
+
+
+
+
+
+QueryResult::QueryResult(QString r)
+{
+ res=r;
+}
+QueryResult::QueryResult(QString r,QString o,int s)
+{
+ res=r;
+ richr=r;
+ orig=o;
+ richo=o;
+ sco=s;
+}
+
+QueryResult::QueryResult()
+{
+ res="";
+}
+
+
+
+
+DataBaseInterface::DataBaseInterface(QString dir, DBSESettings *sets)
+{
+
+ //FIXME Better db names!!
+ main = openMyDataBase(dir+"/testm","main","it",DB_BTREE);
+ alpha = openMyDataBase(dir+"/testa","alpha","it",DB_BTREE);
+ numindex = openMyDataBase(dir+"/testn","numindex","it",DB_RECNO);
+ wordsindex = openMyDataBase(dir+"/testw","wordsindex","it",DB_BTREE);
+ sentence = openMyDataBase(dir+"/tests","sentence","it",DB_BTREE);
+ corr = openMyDataBase(dir+"/testc","corr","it",DB_BTREE);
+ transword = openMyDataBase(dir+"/testt","transword","it",DB_RECNO);
+
+ // kdDebug(0) << main << endl;
+ // kdDebug(0) << alpha << endl;
+ settings=sets;
+ _stopNow=false;
+}
+
+DataBaseInterface::~DataBaseInterface()
+{
+
+ if(main){
+ main->close(0);
+ delete main;
+ }
+ if(numindex){
+ numindex->close(0);
+ delete numindex;
+ }
+
+ if(alpha){
+ alpha->close(0);
+ delete alpha;
+ }
+ if(wordsindex){
+ wordsindex->close(0);
+ delete wordsindex;
+ }
+ if(sentence){
+ sentence->close(0);
+ delete sentence;
+ }
+
+}
+
+DataBase *DataBaseInterface::openMyDataBase(const QString& prefix,const QString& name,const QString& l,DBTYPE tt)
+{
+
+ DataBase *aDb = new DataBase(prefix,name,l);
+ if(aDb==0){
+ return 0;
+ }
+ else
+ {
+ if(aDb->open(tt)!=0)
+ {
+ kdDebug(0) << "Database '"<< name <<"'do not exist, I try to create it.." << endl;
+ //ask only the first time.
+ static bool create=( KMessageBox::questionYesNo(0,"Database do not exist. Do you want to create it now?",
+ i18n("Create Database"), i18n("Create"), i18n("Do Not Create"))==KMessageBox::Yes);
+ if(create)
+ if(aDb->open(tt,DB_CREATE)!=0)
+ {
+ kdDebug(0) << "...cannot create!!"<< endl;
+ return 0;
+ }
+ else
+ {
+ kdDebug(0) << "...done!" << endl;
+ return aDb;
+ }
+ }
+
+ }
+ return aDb;
+}
+
+/*
+ * query functions.
+ *
+ */
+
+
+DataBaseInterface::MainEntry DataBaseInterface::get(const QString& query,SearchFilter *filter)
+{
+ static int counter=1;
+ counter++;
+ DBItemMainKey k(query);
+ DBItemMainData d;
+ //int r=
+ main->get(&k,&d);
+ // kdDebug(0) << "MAINDB->GET returned: " << r << endl;
+ if(counter%5==0) kapp->processEvents(100);
+ // kdDebug(0) << "events processed" << endl;
+ return qMakePair(k,d);
+
+}
+
+/*
+ * put functions
+ * *
+ */
+
+
+bool DataBaseInterface::addEntry(QString original,QString translated,InputInfo *info)
+{
+ DBItemMainKey mk(original);
+ DBItemMainData md;
+ QMap<QString, int> correlationDiff;
+ bool newentry=false;
+ //try to get
+ kdDebug(0) << "Inserting the pair:" << endl;
+ kdDebug(0) << "ORIGINAL:" << original << endl;
+ kdDebug(0) << "TRANSLATED:" << translated << endl;
+
+ if(main->get(&mk,&md)==DB_NOTFOUND)
+ {
+ kdDebug(0) << "new entry" << endl;
+ newentry=true;
+ //This is a new entry, create index entry
+ DBItemNum *nind;
+ int newid=numindex->getLast()+1;
+ nind=new DBItemNum(newid);
+ numindex->put(nind,&mk);
+
+ delete nind;
+
+ md.clear();
+ md.setIndexnumber(newid);
+
+
+ //Update secondary index alpha
+ DBItemMainKey ka(simple(original));
+ DBItemMultiIndex in;
+ if(alpha->get(&ka,&in)==DB_NOTFOUND) in.clear() ;
+ //alpha->get(&ka,&in);
+ in.addEntry(newid);
+ alpha->put(&ka,&in);
+ kdDebug(0) << "Updating the word index " << endl;
+ //Update words index
+ QStringList ws=words(original);
+ for(QStringList::iterator it = ws.begin(); it!=ws.end(); ++it)
+ {
+ DBItemMainKey word(*it);
+ DBItemMultiIndex win;
+ if(wordsindex->get(&word,&win)==DB_NOTFOUND) win.clear();
+ win.addEntry(newid);
+ wordsindex->put(&word,&win);
+ }
+
+ kdDebug(0) << "new entry preparation DONE" << endl;
+ }
+ else
+ {
+
+ kdDebug(0) << "It exists!" <<endl;
+ }
+
+
+ //Update sentence index
+ QStringList so=sentences(original);
+ QStringList st=sentences(translated);
+ if(so.count()==st.count() && st.count() >1 ) //we already hav a database for single string.
+ {
+ kdDebug(0) << "inside sentence loop" << endl;
+ for(int i=0; i< so.count() ; i++)
+ {
+ DBItemMainKey sk(so[i]);
+ DBItemMainData sd;
+ if(sentence->get(&sk,&sd)==DB_NOTFOUND&&!newentry)
+ kdDebug(0) << "Warning: new sentence for old entry, do we changed sentence definition? " << endl;
+
+ kdDebug(0) << "here alive" << endl;
+
+ // if(clean)
+ sd.removeRef(info->ref());
+ kdDebug(0) << "now alive" << endl;
+ sd.addTranslation(st[i],info->ref());
+ kdDebug(0) << "still alive" << endl;
+
+ sentence->put(&sk,&sd);
+
+ }
+
+
+
+ }
+ kdDebug(0) << "Fuzzy sentence archive updated" << endl;
+
+
+
+ //Add that translation, link to ref for information on that translation
+
+ if(!translated.isEmpty())
+ {
+ //loop on all translations to update correlation
+ QStringList tmpTranslations=md.getTranslations();
+ for(QStringList::iterator otIt=tmpTranslations.begin(); otIt!=tmpTranslations.end();++otIt)
+ {
+ QStringList wt=words(*otIt);
+ for(QStringList::iterator it = wt.begin(); it!=wt.end(); ++it)
+ {
+ if(correlationDiff.contains(*it))
+ correlationDiff[*it]--;
+ else
+ correlationDiff[*it]=-1;
+ }
+ }
+
+ //clean so that we have only one translation per catalog.
+ md.removeRef(info->ref());
+ md.addTranslation(translated,info->ref());
+
+ tmpTranslations=md.getTranslations();
+ for(QStringList::iterator otIt=tmpTranslations.begin(); otIt!=tmpTranslations.end();++otIt)
+ {
+ QStringList wt=words(*otIt);
+ for(QStringList::iterator it = wt.begin(); it!=wt.end(); ++it)
+ {
+ if(correlationDiff.contains(*it))
+ correlationDiff[*it]++;
+ else
+ correlationDiff[*it]=1;
+ }
+ }
+
+ //FIXME: use the correlationDIff map somehow
+
+ }
+
+ //finally put!
+ return (main->put(&mk,&md)==0);
+
+}
+
+
+bool DataBaseInterface::removeEntry(QString original)
+{
+ DBItemMainKey mk(original);
+ DBItemMainData md;
+
+ //FIXME implement remove
+ //try to get
+ if(main->get(&mk,&md)==DB_NOTFOUND)
+ {
+ /* //This is a new entry, create index entry
+ DBItemNum *nind;
+ int newid=numindex->getLast()+1;
+ nind=new DBItemNum(newid);
+ numindex->put(nind,&mk);
+
+ delete nind;
+
+ md.clear();
+ md.setIndexnumber(newid);
+
+
+ //Update secondary index alpha
+ DBItemMainKey ka(simple(original));
+ DBItemMultiIndex in;
+ if(alpha->get(&ka,&in)==DB_NOTFOUND) in.clear() ;
+ //alpha->get(&ka,&in);
+ in.addEntry(newid);
+ alpha->put(&ka,&in);
+
+ //Update words index
+ QStringList ws=words(original);
+ for(QStringList::iterator it = ws.begin(); it!=ws.end(); it++)
+ {
+ DBItemMainKey word(*it);
+ DBItemMultiIndex win;
+ if(wordsindex->get(&word,&win)==DB_NOTFOUND) win.clear();
+ win.addEntry(newid);
+ wordsindex->put(&word,&win);
+ }
+
+ //Update sentence index
+ QStringList so=sentences(original);
+ QStringList st=sentences(translated);
+ if(so.count()==st.count() && st.count() >1 ) //we already hav a database for single string.
+ {
+ for(int i=0; i< so.count() ; i++)
+ {
+ DBItemMainKey sk(so[i]);
+ DBItemMainKey sd(st[i]); //should be a list i.e. main data?
+ sentence->put(&sk,&sd);
+
+ }
+ }
+
+*/
+ }
+
+
+ return false;
+
+}
+
+
+
+QMap<QString,float> DataBaseInterface::correlation(QString word,SearchFilter *filter,bool notify, float minSign)
+{
+ QDict<unsigned int> res;
+ // res.setAutoDelete(true);
+ QMap<QString, float>final;
+ DBItemMultiIndex::IndexList il;
+ unsigned int tot=0;
+ unsigned int background=0;
+ unsigned int nocck;
+ QString sword=simple(word);
+ DBItemMainKey *k = new DBItemMainKey(sword);
+ DBItemMultiIndex *d = new DBItemMultiIndex();
+ if(wordsindex->get(k,d)!=DB_NOTFOUND)
+ {
+
+ il=d->getList();
+ kdDebug(0) << il.count()<<endl;
+ tot=0;
+ for(QValueList<unsigned int>::iterator it=il.begin();it!=il.end();++it)
+ {
+ numindex->get(*it,k);
+
+
+ // QValueList<QueryResult> trad=exactMatch(k->getString(),filter);
+
+ MainEntry e=get(k->getString(),filter);
+ QStringList trad=e.second.getTranslations();
+
+ nocck=words(k->getString()).contains(sword);
+ for( QStringList::iterator it2=trad.begin();it2!=trad.end();++it2)
+ {
+
+ QStringList w=words(*it2);
+ unsigned int numWords = w.count()*10+1;
+ unsigned int wei=100000/sqrt(numWords); //weight (is the best one?)
+
+ background+=(numWords-nocck)*wei;
+ QDict<uint> count;
+ //count.setAutoDelete(true);
+ //FIXME:SET AUTODELETE FOR ALL DICTS
+ for(QStringList::iterator it1=w.begin();it1!=w.end();it1++)
+ {
+ uint *ip;
+ if(!(ip=count[*it1])) count.insert(*it1,new uint(1));
+ else
+ (*ip)++;
+ }
+
+ for(QStringList::iterator it1=w.begin();it1!=w.end();it1++)
+ {
+ uint *ip;
+ if(*(count[*it1])==nocck) //add only if same number of entry (it cuts articles)
+ if(!(ip=res[*it1])) res.insert(*it1,new uint(wei));
+ else
+ (*ip)+=wei;
+ }
+
+ }
+ }
+
+ unsigned int sqrBG=sqrt((1.0*background+1)/10000);
+
+ for(QDictIterator<uint> it(res) ; it.current(); ++it)
+ {
+ float sign=1.0*(*(it.current()))/(10000.0*sqrBG);
+ if(sign >minSign){
+ final[it.currentKey()]=sign;
+ kdDebug(0) << it.currentKey() <<" Score:" << 1.0*(*(it.current()))/10000 << "/" <<sqrBG << " = " <<sign << endl;
+ }
+ }
+
+ kdDebug(0) << "final count " <<final.count()<< endl;
+ }
+
+ return final;
+}
+
+QStringList DataBaseInterface::words(QString s)
+{
+ QString str=simple(s);
+ QStringList list;
+
+ int pos;
+
+ do {
+ pos=str.find(QRegExp("\\s"));
+ // if(!simple(str.left(pos)).isEmpty())
+ // list.append(simple(str.left(pos)));
+ if(!str.left(pos).isEmpty())
+ list.append(str.left(pos));
+ str=str.remove(0,pos+1);
+ } while(!str.isEmpty() && pos != -1);
+
+ return list;
+}
+
+QString DataBaseInterface::simple(QString str,bool ck)
+{
+ QString res;
+ if(ck)
+ res=str; //case keep
+ else
+ res=str.lower(); //lowercase
+ //FIXME: uncoment the foll. line (check speed)
+ res=res.replace(QRegExp("(<(.*)>)(.*)(</\\2>)"),"\\3"); //remove enclosing tags
+
+
+ //Try to get rid of regexps.
+ // res=res.replace(QRegExp("(('|-|_|\\s|[^\\w%])+)")," "); //strip non-word char
+ // res=res.replace(QRegExp("(('|-|_)+)")," "); //strip non-word char
+ // res=res.replace(QRegExp("[^\\w\\s%]"),""); //strip non-word char
+
+ QString r;
+ QChar c;
+ bool wasSpace=true;
+ uint len=res.length();
+ for(uint i=0; i<len;i++)
+ {
+ c=res[i];
+ if(c.isLetterOrNumber())
+ {
+ r+=c;
+ wasSpace=false;
+ }
+ else
+ {
+ if(!wasSpace && c.isSpace())
+ {
+ r+=' ';
+ wasSpace=true;
+ }
+ else
+ {
+ if(!wasSpace && (c=='-' || c=='\'' || c=='_'))
+ {
+ r+=' ';
+ wasSpace=true;
+ }
+ else
+ {
+ if(c=='%'){
+ r+=c;
+ wasSpace=false;
+ }
+ }
+ }
+ }
+ // wasSpace=c.isSpace();
+ }
+ if(r[len-1].isSpace())
+ r.truncate(len-1);
+ res=r;
+ //kdDebug(0) << "Simple: "<<res<< endl;
+ //res=res.simplifyWhiteSpace(); //remove double spaces
+ //res=res.stripWhiteSpace(); //" as " -> "as"
+
+ // kdDebug(0) << res << endl;
+ return res;
+}
+
+QStringList DataBaseInterface::sentences(QString s)
+{
+ QString str=s;
+ QStringList list;
+
+ // kdDebug(0) << s << endl;
+
+ int pos;
+
+
+ do {
+ QRegExp re("((\\.|;|\\?|\\!|:)( |$|\\\\n\\n))");
+ pos=re.search(str);
+ if(!str.left(pos).isEmpty())
+ list.append(str.left(pos).stripWhiteSpace());
+
+ kdDebug(0) << str.left(pos) << endl;
+
+ str=str.remove(0,pos+re.cap(1).length());
+ } while(!str.isEmpty() && pos != -1);
+
+
+ return list;
+}
+
+QStringList DataBaseInterface::sentencesSeparator(QString s)
+{
+ QString str=s;
+ QStringList list;
+
+ // kdDebug(0) << s << endl;
+
+ int pos;
+
+ do {
+ QRegExp re;
+ re.setPattern("([.:?!;]( |$|\\\\n\\n))");
+ pos = re.search(str);
+ QString separator=re.cap(1);
+ if(pos!=-1){
+ list.append(separator);
+ }
+
+ str=str.remove(0,pos+1);
+ } while(!str.isEmpty() && pos != -1);
+
+ return list;
+}
+
+bool DataBaseInterface::isUpper(QChar s)
+{
+ return s==s.upper();
+}
+
+bool DataBaseInterface::isLower(QChar s)
+{
+ return s==s.lower();
+}
+
+
+
+QString DataBaseInterface::format(QString _s,QString t)
+{
+ //FIXME use settings
+ //FIXME use regexp
+
+ QString s=_s;
+ QString noTagT=t.replace(QRegExp("(<(.*)>)(.*)(</\\2>)"),"\\3");
+ QChar first=noTagT[noTagT.find(QRegExp("\\w"))];
+ bool firstCapital=isUpper(first);
+
+ /*
+bool dotsAtEnd=(t.find("...")+3==t.length());
+bool gtgtAtEnd=(t.find(">>")+2==t.length());
+bool ltltAtEnd=(t.find("<<")==t.length()-2);
+
+bool columnAtEnd=(t.find(":")+1==t.length());
+*/
+
+ bool allupper=(t.upper()==t);
+
+
+ if(firstCapital)
+ s[0]=s[0].upper();
+ else
+ s[0]=s[0].lower();
+
+ //if(dotsAtEnd)
+ // s+="...";
+
+ /*if(gtgtAtEnd)
+ s+=">>";
+
+if(ltltAtEnd)
+ s+="<<";
+
+if(columnAtEnd)
+ s+=":";
+*/
+
+ if(allupper)
+ s=s.upper();
+
+ int pos=t.find(QRegExp("&"));
+ if(pos>=0) {
+ QChar accel=t[t.find(QRegExp("&"))+1];
+ if(accel!='&')
+ {
+
+ pos=s.find(accel,false);
+ if(pos<0)
+ pos=0;
+ s.insert(pos,"&");
+ }
+ }
+ s=formatRegExp(s,t,".*(\\.\\.\\.|:|>>|<<|\\.|\\?)$",
+ "^(.*)$",
+ "\\1@CAP1@");
+ s=formatRegExp(s,t,"(<(.*)>).*(\\.\\.\\.|:|>>|<<|\\.|\\?)*(</\\2>)$",
+ "^(.*)$",
+ "@CAP1@\\1@CAP3@@CAP4@");
+
+ return s;
+
+}
+
+
+QString DataBaseInterface::formatRegExp(QString _s, QString t, QString tre,QString stringSearch,QString stringReplace)
+{
+ QString s=_s;
+ QRegExp templateRegExp(tre);
+ //QString stringSearch = "(.*)!@CAP1@$"; // use @CAP1.. fot caps in templates
+ //QString stringReplace = "\\1@CAP1@"; // use \1, \2 for caps in str and @CAP1 fot caps in template
+
+
+ if(templateRegExp.exactMatch(t))
+ {
+ QStringList caps=templateRegExp.capturedTexts();
+ int i=0;
+ for(QStringList::iterator capit=caps.begin();capit!=caps.end();++capit)
+ {
+ QString phRegExp="(?!\\\\)@CAP"+QString::number(i)+"@";
+ //kdDebug(0) << "phRegExp: " << phRegExp << endl;
+ //kdDebug(0) << "cap[" << i << "]: "<< *capit<< endl;
+
+ stringReplace = stringReplace.replace(QRegExp(phRegExp),*capit);
+ stringSearch = stringSearch.replace(QRegExp(phRegExp),*capit);
+ i++;
+
+ }
+ // kdDebug(0) << "stringSearch " << stringSearch << endl;
+ // kdDebug(0) << "stringReplace " << stringReplace << endl;
+ QRegExp stringSearchRegExp = QRegExp(stringSearch);
+ // kdDebug(0) << "before: "<<s<<endl;
+ s = s.replace(stringSearchRegExp,stringReplace);
+ // kdDebug(0) << "after: "<<s<<endl;
+
+ }
+
+ return s;
+}
+
+DBItemMultiIndex::IndexList DataBaseInterface::getAlpha( const QString & query )
+{
+ DBItemMainKey *k = new DBItemMainKey(simple(query));
+ DBItemMultiIndex *d = new DBItemMultiIndex();
+ alpha->get(k,d);
+
+ return d->getList();
+}
+
+DataBaseInterface::MainEntry DataBaseInterface::getFromIndex( uint i )
+{
+ DBItemMainKey k;
+ numindex->get(i,&k);
+ return get(k.getString(),0); //FIXME: this is a BUG right now but the filter should be removed
+}
+
+DataBaseInterface::MainEntry DataBaseInterface::getSentence( const QString & query )
+{
+
+ static int counter=1;
+ counter++;
+ DBItemMainKey k(query);
+ DBItemMainData d;
+ sentence->get(&k,&d);
+ if(counter%5==0) kapp->processEvents(100);
+ return qMakePair(k,d);
+
+}
+
+DBItemMultiIndex::IndexList DataBaseInterface::getWordIndex( const QString & query )
+{
+ DBItemMainKey k = DBItemMainKey(query);
+ DBItemMultiIndex d = DBItemMultiIndex();
+ if(wordsindex->get(&k,&d)!=DB_NOTFOUND){
+ return d.getList();
+ }
+ else
+ {
+ QValueList<unsigned int> tmpList;
+ return tmpList;
+ }
+
+}
+
+
+
+//#include "database.moc.cpp"
+
diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/database.h b/kbabel/kbabeldict/modules/dbsearchengine2/database.h
new file mode 100644
index 00000000..c447fa59
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine2/database.h
@@ -0,0 +1,237 @@
+/*
+
+ DBSE 3
+ (c) 2000-2003 Andrea Rizzi
+ License: GPLv2
+
+*/
+#ifndef DATABASE_2_H
+#define DATABASE_2_H
+
+#include <qstring.h>
+#include <qvaluelist.h>
+#include <db4/db_cxx.h>
+#include <qobject.h>
+#include <qregexp.h>
+
+#include "dbentries.h"
+
+
+class DBSESettings
+{
+public:
+ //DatabaseInterface Settings
+ uint scoreWordByWord;
+ uint scoreGlossary;
+ uint scoreDivide;
+ uint scoreExact;
+ uint scoreSentence;
+ uint scoreAlpha;
+ uint scoreDynamic;
+ uint scoreChunkByChunk;
+ uint minScore;
+ bool firstCapital;
+ bool allCapital;
+ bool accelerator;
+ bool sameLetter;
+
+
+
+};
+
+
+class DataBase : Db
+{
+ public:
+ DataBase(QString dbpath, QString dbname, QString dblang);
+
+ int open(DBTYPE type,unsigned int flags=0);
+
+//Standard access (overload std functions)
+
+
+
+int del(DBItem * key){
+ key->set();
+ int r = Db::del(0,key,0);
+ key->get();
+ return r;
+ }
+
+
+
+int get(DBItem * key,DBItem *data){
+ key->set();
+ data->set();
+ int r = Db::get(0,key,data,0);
+ key->get();
+ data->get();
+ return r;
+ }
+ int put(DBItem * key,DBItem *data,int fl=0){
+ key->set();
+ data->set();
+ int r= Db::put(0,key,data,0);
+ key->get();
+ data->get();
+ return r;
+ }
+
+ int del(DBItemNum * key){
+ int r = Db::del(0,key,0);
+ return r;
+ }
+
+ int get(DBItemNum * key,DBItem *data){
+ data->set();
+ int r = Db::get(0,key,data,0);
+ data->get();
+ return r;
+ }
+ int put(DBItemNum * key,DBItem *data)
+ {
+ data->set();
+ int r= Db::put(0,key,data,0);
+ data->get();
+ return r;
+ }
+
+//Overload, using this you loose the Key!!
+ int del(int i){DBItemNum n(i); return del(&n);}
+ int get(int i,DBItem *data){DBItemNum n(i); return get(&n,data);}
+ int put(int i,DBItem *data){DBItemNum n(i); return put(&n,data);}
+
+ unsigned int getLast();
+ int close(unsigned int i) {return Db::close( i); }
+
+//For scrolling
+ // int getFirst(DBItem *key,DBItem *data,QString table);
+ // int getNext(DBItem *key,DBItem *data,QString table);
+ // bool isEnd(QString table);
+private:
+ QString filename;
+ QString database;
+ DBTYPE mytype;
+};
+
+
+
+
+
+class QueryResult //from DBInterface to KDBSearchEngine
+{
+public:
+ QueryResult();
+ QueryResult(QString r);
+ QueryResult(QString r,QString o,int s);
+ void setRichResult(QString r) { richr=r; }
+ void setRichOriginal(QString r) { richo=r; }
+
+ QString richResult() {return richr;}
+ QString richOriginal() {return richo;}
+
+ QString result(){ return res; }
+ QString original() {return orig; }
+ int score() {return sco;}
+//info contains originalkey,catalog,date,author etc...
+ ResultInfo info(){ResultInfo i; i.info="no info"; return i;}
+
+
+private:
+ QString res;
+ QString orig;
+ QString richr;
+ QString richo;
+ int sco;
+
+};
+
+class SearchFilter
+{
+ int filter; //placeholder
+};
+
+
+
+class DataBaseInterface : public QObject
+{
+
+ public:
+ //move result list typedef to AbstractAlgorthm or somewhere else
+ typedef QValueList<QueryResult> ResultList;
+ typedef QPair<DBItemMainKey,DBItemMainData> MainEntry;
+
+ DataBaseInterface( QString dir, DBSESettings *sets);
+ ~DataBaseInterface();
+
+ //Ask the Database to stop now.
+ void stop(bool b=true) {_stopNow=b;}
+
+ //Search words
+ ResultList wordsMatch(QString query,SearchFilter *filter=0,bool notify=true);
+
+ //Edit database functions.
+ //addEntry and sync all the tables
+ bool addEntry(QString original,QString translated,InputInfo *info);
+ //FIXME:implement me!
+ bool removeEntry(QString original);
+
+ //FIXME: go persistent!
+ QMap<QString,float> correlation(QString word,SearchFilter *filter=0,bool notify=true,float minSign=0.2);
+
+
+ // Read the database
+ MainEntry get(const QString& query,SearchFilter *filter=0);
+ MainEntry getFromIndex(uint i);
+ DBItemMultiIndex::IndexList getAlpha(const QString& query);
+ DBItemMultiIndex::IndexList getWordIndex(const QString& query);
+ MainEntry getSentence(const QString& query);
+
+ //Database status check functions
+ bool mainOk() {return main!=0;}
+ bool catalogOk() {return catalog!=0;}
+ bool alphaOk() {return alpha!=0;}
+ bool sentenceOk() {return sentence!=0;}
+ bool numindexOk() {return numindex!=0;}
+ bool wordsindexOk() {return wordsindex!=0;}
+ bool externalOk() {return external!=0;}
+ bool wordOk() {return word!=0;}
+ bool transwordOk() {return transword!=0;}
+ bool correlationOk() {return corr!=0;}
+ bool stopNow() {return _stopNow;}
+
+ // signals:
+ // void newResult(QueryResult);
+
+ DBSESettings *getSettings() {return settings;}
+
+ private:
+ DataBase * openMyDataBase(const QString& prefix,const QString& name,const QString& l,DBTYPE tt);
+ DataBase *main;
+ DataBase *numindex;
+ DataBase *wordsindex;
+ DataBase *catalog;
+ DataBase *alpha;
+ DataBase *sentence;
+ DataBase *word;
+ DataBase *external;
+ DataBase *transword;
+ DataBase *corr;
+ bool _stopNow;
+ DBSESettings *settings;
+
+ //FIXME:Move to KBabel common library.
+ public:
+ QString format( QString _s,QString t);
+ QString formatRegExp(QString _s, QString t, QString tre,QString stringSearch,QString stringReplace);
+ static QStringList words(QString s);
+ static QStringList sentences(QString s);
+ static QStringList sentencesSeparator(QString s);
+ static QString simple(QString str,bool ck=false);
+ static bool isUpper(QChar s);
+ static bool isLower(QChar s);
+
+ };
+
+#endif
+
diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/dbentries.cpp b/kbabel/kbabeldict/modules/dbsearchengine2/dbentries.cpp
new file mode 100644
index 00000000..4f048f9c
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine2/dbentries.cpp
@@ -0,0 +1,171 @@
+#include "dbentries.h"
+#include <qdatastream.h>
+
+
+void DBItem::set()
+{
+ QBuffer b(mydata);
+ b.open( IO_WriteOnly );
+ QDataStream s(&b);
+ write(&s);
+ b.close();
+ set_data(mydata.data());
+ set_size(mydata.size());
+
+}
+ void DBItem::get()
+ {
+ mydata.resize(get_size());
+ mydata.duplicate((const char *)get_data(),(unsigned int)get_size());
+
+ QDataStream *s = new QDataStream(mydata,IO_ReadOnly);
+ read(s);
+ delete s;
+ }
+
+
+
+DBItemMainKey::DBItemMainKey()
+{
+ sstr="";
+ //set();
+}
+
+DBItemMainKey::DBItemMainKey(QString searchstring)
+{
+ sstr=searchstring;
+ //set();
+}
+
+void DBItemMainKey::read(QDataStream *s)
+{
+*s >> sstr;
+}
+
+void DBItemMainKey::write(QDataStream *s)
+{
+ *s << sstr;
+ }
+
+
+
+
+
+DBItemMainData::DBItemMainData()
+{
+ clear();
+ //set();
+}
+
+void DBItemMainData::clear()
+{
+ indexnumber=0;
+ translations.clear();
+ //set();
+}
+
+void DBItemMainData::read(QDataStream *s)
+{
+*s >> indexnumber >> translations;
+}
+
+void DBItemMainData::write(QDataStream *s)
+{
+ *s << (Q_UINT32)indexnumber << translations;
+}
+
+void DBItemMainData::addTranslation(QString str, unsigned int ref)
+{
+//get();
+ if(translations[str].find(ref)==translations[str].end()) // If it do not exists
+ translations[str].append(ref); //add a new reference.
+ else
+ {
+
+ }
+//set();
+
+}
+
+void DBItemMainData::removeTranslation(QString str, unsigned int ref)
+{
+//get();
+ translations[str].remove(ref);
+ if(translations[str].isEmpty())
+ translations.remove(str);
+//set();
+
+}
+
+void DBItemMainData::removeRef( unsigned int ref)
+{
+//get();
+QMapIterator<QString,QValueList<unsigned int> > it2;
+ for(QMapIterator<QString,QValueList<unsigned int> > it = translations.begin();
+ it!= translations.end(); /* it++*/)
+ { //Dirty hack
+ it2=it;
+ it++;
+ if(it2.data().find(ref)!=it2.data().end())
+ removeTranslation(it2.key(),ref);
+ }
+
+//set();
+}
+
+QStringList DBItemMainData::getTranslations()
+{
+//get();
+QStringList result;
+ for(QMapIterator<QString,QValueList<unsigned int> > it = translations.begin();
+ it!= translations.end(); it++)
+ result.append(it.key());
+
+return result;
+
+}
+
+QValueList<unsigned int> DBItemMainData::getReferences(QString str)
+{
+//get();
+return translations[str]; //this also add a "str" entry but we do not call set()!
+}
+
+
+
+DBItemMultiIndex::DBItemMultiIndex()
+{
+list.clear();
+//set();
+}
+
+void DBItemMultiIndex::addEntry(unsigned int index)
+{
+// get();
+ if(list.find(index)==list.end())
+ {
+ list.append(index);
+ qHeapSort(list);
+ // set();
+
+ }
+
+}
+
+void DBItemMultiIndex::removeEntry(unsigned int index)
+{
+// get();
+ list.remove(index);
+// set();
+}
+
+
+void DBItemMultiIndex::read(QDataStream *s)
+{
+*s >> list;
+}
+
+void DBItemMultiIndex::write(QDataStream *s)
+{
+ *s << list;
+ }
diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/dbentries.h b/kbabel/kbabeldict/modules/dbsearchengine2/dbentries.h
new file mode 100644
index 00000000..0a40878c
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine2/dbentries.h
@@ -0,0 +1,170 @@
+#ifndef DBENTRIES_H
+#define DBENTRIES_H
+
+#include <db4/db_cxx.h>
+#include <qstring.h>
+#include <qbuffer.h>
+#include <qmap.h>
+#include <qstringlist.h>
+#include <qdatetime.h>
+
+class CatalogInfo
+{
+
+ QString author;
+ QDateTime datetime;
+ QString filename;
+ QString filepath;
+
+
+};
+
+class ResultInfo
+{
+public:
+//Common info
+ QString original; //placeholder
+
+//
+//Multi reference info
+ QValueList<CatalogInfo> catalogs;
+
+ QString info;
+
+};
+
+class InputInfo
+{
+public:
+ unsigned int ref() {return 1;}
+
+};
+
+class DBItem : public Dbt
+{
+public:
+
+ virtual ~DBItem(){}
+
+ virtual bool isEmpty(){return empty;}
+//void fromDbt(Dbt *dbt);
+
+ void set();
+ void get();
+
+
+protected:
+ virtual void read(QDataStream *s) = 0;
+ virtual void write(QDataStream *s) = 0;
+ QByteArray mydata;
+ bool empty;
+
+};
+
+class DBItemMainKey : public DBItem
+{
+ public:
+ DBItemMainKey();
+ DBItemMainKey(QString searchstring);
+
+
+ QString getString(){ return sstr;}
+
+private:
+
+ virtual void read(QDataStream *s);
+ virtual void write(QDataStream *s);
+
+ QString sstr;
+
+};
+
+
+class DBItemMainData : public DBItem
+{
+ public:
+
+ typedef QMapIterator<QString,QValueList<unsigned int> > TranslationIterator;
+ typedef QMap<QString,QValueList<unsigned int> > TranslationMap;
+
+ DBItemMainData();
+
+ QStringList getTranslations();
+ QValueList<unsigned int> getReferences(QString str);
+
+ void clear();
+
+
+//Add a translation with reference ref, if translation exists append
+// ref to the list of references
+ void addTranslation(QString str,unsigned int ref);
+ void removeTranslation(QString str,unsigned int ref);
+
+//remove any reference to ref, if ref is the only reference of a translation
+// the translation is removed
+ void removeRef(unsigned int ref);
+
+ unsigned int getIndexnumber(){ return indexnumber; }
+ void setIndexnumber(int i){ indexnumber=i; }
+
+private:
+
+ virtual void read(QDataStream *s);
+ virtual void write(QDataStream *s);
+
+ unsigned int indexnumber;
+ TranslationMap translations;
+
+};
+
+
+class DBItemMultiIndex : public DBItem
+{
+ public:
+ typedef QValueList<unsigned int> IndexList;
+
+ DBItemMultiIndex();
+ // DBItemMultiIndex(IndexList l);
+
+ void addEntry(unsigned int index);
+ void removeEntry(unsigned int index);
+
+ IndexList getList(){ return list;}
+ void clear() {list.clear();}
+
+private:
+
+ virtual void read(QDataStream *s);
+ virtual void write(QDataStream *s);
+
+ IndexList list;
+
+};
+
+
+class DBItemNum : public Dbt
+{
+ public:
+ DBItemNum(){
+ set_data(&num);
+ set_size(4);
+ num=0;
+ }
+ DBItemNum(unsigned int i){
+ set_data(&num);
+ set_size(4);
+ num=i;
+ }
+
+ unsigned int getNum(){ num=*(unsigned int *)get_data(); return num;}
+
+private:
+
+ unsigned int num;
+
+};
+
+
+
+
+#endif
diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/dbscan.cpp b/kbabel/kbabeldict/modules/dbsearchengine2/dbscan.cpp
new file mode 100644
index 00000000..b19b2db2
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine2/dbscan.cpp
@@ -0,0 +1,280 @@
+/***************************************************************************
+ dbscan.cpp - Scan for po files to add in the DB
+ -------------------
+ begin : Fri Sep 8 2000
+ copyright : (C) 2000 by Andrea Rizzi
+ email : rizzi@kde.org
+ ***************************************************************************/
+
+/*
+ Translation search engine
+
+
+ Copyright 2000
+ Andrea Rizzi rizzi@kde.org
+
+ License GPL v 2.0
+
+*/
+#include "dbscan.h"
+#include <kconfig.h>
+#include <qdir.h>
+#include <qfile.h>
+#include <kapplication.h>
+#include <kurl.h>
+#include <kdebug.h>
+#include <klineedit.h>
+#include <kurlrequester.h>
+#include <kcombobox.h>
+
+using namespace KBabel;
+
+MessagesSource::MessagesSource()
+{
+ //FIXMR: check if we should put something in that constructor
+}
+void MessagesSource::writeConfig(KConfigBase *config)
+{
+ config->writeEntry("Location",location.url());
+ config->writeEntry("LocationType",type);
+ config->writeEntry("ProjectName",projectName);
+ config->writeEntry("ProjectKeywords",projectKeywords);
+ config->writeEntry("Status",status);
+}
+
+void MessagesSource::readConfig(KConfigBase *config)
+{
+ location=config->readEntry("Location");
+ type=config->readNumEntry("LocationType",0);
+ projectName=config->readEntry("ProjectName");
+ projectKeywords=config->readEntry("ProjectKeywords");
+ status=config->readEntry("Status");
+
+}
+
+void MessagesSource::setDialogValues(SourceDialog *sd)
+{
+ sd->projectName->setText(projectName);
+ sd->projectKeywords->setText(projectKeywords);
+ sd->sourceLocation->setURL(location.url());
+ sd->status->setCurrentText(status);
+ sd->type->setCurrentItem(type);
+}
+void MessagesSource::getDialogValues(SourceDialog *sd)
+{
+ projectName=sd->projectName->text();
+ projectKeywords=sd->projectKeywords->text();
+ location=sd->sourceLocation->url();
+ status=sd->status->currentText();
+ type=sd->type->currentItem();
+}
+
+QValueList<KURL> MessagesSource::urls()
+{
+ QValueList<KURL> urlList;
+ if(type==0)
+ urlList.append(location);
+ if(type==1|| type==2)
+ urlList=filesInDir(location,(type==2));
+
+ return urlList;
+
+}
+
+QValueList<KURL> MessagesSource::filesInDir(KURL url,bool recursive)
+{
+ QValueList<KURL> result;
+ QDir d(url.path());
+ d.setMatchAllDirs(true);
+ kdDebug(0) << d.count() << " files in dir "<< url.path()<<endl;
+ const QFileInfoList* files = d.entryInfoList();
+ kdDebug(0) << files << endl;
+
+ // QPtrListIterator<QFileInfo> it(*files);
+ if(files){
+ for (QPtrListIterator<QFileInfo> fileit(*files); !fileit.atLast(); ++fileit )
+ {
+ if ((*fileit)->isDir())
+ {
+ if(recursive)
+ {
+ if((*fileit)->fileName()!="." && (*fileit)->fileName() !="..")
+ {
+ result+=filesInDir(KURL((*fileit)->absFilePath()),recursive);
+ kdDebug(0) << "Recursion done for " << (*fileit)->fileName() << endl;
+ }
+ }
+
+ }
+ else
+ {
+ kdDebug(0) << (*fileit)->fileName() << endl;
+ result.append(KURL((*fileit)->absFilePath()));
+ }
+ }
+ }
+ kdDebug(0) << result.count() << endl;
+
+ return result;
+}
+
+//FIXME: clean this class
+PoScanner::PoScanner(DataBaseInterface *dbi,
+ QObject *parent,const char *name):QObject(parent,name)
+{
+ di=dbi;
+ removeOldCatalogTranslation=true;
+ count=0;
+}
+
+bool PoScanner::scanPattern(QString pathName,QString pattern,bool rec)
+{
+int tot;
+//Only one progress bar!!
+
+bool pb=false;
+static bool called=false;
+if (!called)
+{ pb=true; count=0;}
+called=true;
+
+kdDebug(0) << QString("Scanning: %1, %2").arg(pathName).arg(pattern) << endl;
+
+if(pb)
+{
+emit patternStarted();
+emit patternProgress(0);
+}
+ QDir d(pathName,pattern);
+ d.setMatchAllDirs(true);
+ const QFileInfoList* files = d.entryInfoList();
+ tot=files->count();
+ QPtrListIterator<QFileInfo> it(*files);
+kdDebug(0) << tot << endl;
+ for ( int i=0; i<tot; i++ )
+ {
+ if ((*it)->isDir())
+ {
+ if(rec)
+ {
+ kdDebug(0) << d[i] << endl;
+ if(d[i]!="." && d[i]!="..")
+ scanPattern(pathName+"/"+d[i],pattern,true);
+ }
+ } else
+ {
+ kdDebug(0) << d[i] << endl;
+ scanFile(pathName+"/"+d[i]);
+ }
+
+ if(pb)
+
+ emit patternProgress(100*i/tot);
+
+
+ ++it;
+ }
+
+
+
+if(pb)
+emit patternProgress(100);
+
+
+if(pb)
+emit patternFinished();
+if(pb){called=false;count=0;}
+
+return true;
+}
+
+bool PoScanner::scanFile(QString fileName)
+{
+ KURL u(fileName);
+ return scanURL(u);
+}
+
+bool PoScanner::scanURL(KURL u)
+{
+
+
+emit fileStarted();
+
+Catalog * catalog=new Catalog(this,"ScanPoCatalog");
+
+QString pretty=u.prettyURL();
+QString location=pretty.right(pretty.length()-pretty.findRev("/")-1);
+
+connect(catalog,SIGNAL(signalProgress(int)),this,SIGNAL(fileLoading(int)));
+emit filename(location);
+emit fileProgress(0);
+emit fileLoading(0);
+
+bool error;
+
+ConversionStatus rr=catalog->openURL(u);
+if(rr != OK && rr !=RECOVERED_PARSE_ERROR )
+{
+ delete catalog;
+ return false;
+}
+emit fileLoading(100);
+
+QString author;
+if(rr != HEADER_ERROR)
+ author=catalog->lastTranslator();
+else author=QString("");
+
+//int catnum=dm->catalogRef(location,author,fileName);
+InputInfo ii;
+
+
+uint i,tot;
+tot=catalog->numberOfEntries();
+
+bool fuzzy;
+bool untra;
+
+
+for (i=0;i<tot;i++) //Skip header = ????
+{
+
+ if(i % 10==0)
+ {
+ emit fileProgress(100*i/tot);
+ emit added(count);
+ kapp->processEvents(100);
+ }
+
+ fuzzy=catalog->isFuzzy(i);
+ untra=catalog->isUntranslated(i);
+
+
+ if(!fuzzy && !untra)
+ {
+ int res;
+ QString msgid,msgstr;
+ msgid=catalog->msgid(i,true).first();
+ msgstr=catalog->msgstr(i).first();
+ res=di->addEntry(msgid,msgstr,&ii);
+ count+=res;
+ }
+
+
+}
+
+
+// kdDebug(0) << QString("File finished") << endl;
+
+emit fileProgress(0);
+emit fileLoading(0);
+emit fileFinished();
+// dm->loadInfo(); // Sync the list of catalogs NOT NEEDED (?)
+
+delete catalog;
+
+//clear();
+return true;
+
+}
+#include "dbscan.moc"
diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/dbscan.h b/kbabel/kbabeldict/modules/dbsearchengine2/dbscan.h
new file mode 100644
index 00000000..990d556c
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine2/dbscan.h
@@ -0,0 +1,120 @@
+/***************************************************************************
+ dbscan.h -
+ -------------------
+ begin : Fri Sep 8 2000
+ copyright : (C) 2000 by Andrea Rizzi
+ email : rizzi@kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+/*
+ Translation search engine
+ Copyright 2000
+ Andrea Rizzi rizzi@kde.org
+
+*/
+
+
+#ifndef _DBSCAN_H_
+#define _DBSCAN_H_
+
+#include <catalog.h>
+#include <kurl.h>
+#include "database.h"
+
+#include "sourcedialog.h"
+
+class KConfigBase;
+
+class MessagesSource
+{
+ //FIXME Use KURL and add network support
+
+ public:
+ MessagesSource();
+ void writeConfig(KConfigBase *config);
+ void readConfig(KConfigBase *config);
+ void setDialogValues(SourceDialog *sd);
+ void getDialogValues(SourceDialog *sd);
+
+ /**
+ * It returns a list of urls to scan, the list contains single file if type is "SingleFile"
+ * or a list of files if type is "SingleDir" or "RecDir"
+ */
+ QValueList<KURL> urls();
+
+ private:
+ QValueList<KURL> filesInDir(KURL url,bool recursive);
+
+ KURL location;
+ // The source type "SingleFile" =0, "SingleDirectory"=1, "RecursiveDirectory"=2
+ uint type;
+
+ /**
+ * A filter to apply on source files
+*/
+
+ SearchFilter filter;
+
+ QString projectName;
+ QString projectKeywords;
+ QString status;
+};
+
+
+class PoScanner : public QObject
+{
+ Q_OBJECT;
+
+ public:
+
+ PoScanner(DataBaseInterface *dbi,QObject *parent=0,const char *name=0);
+
+ /*
+ Scan a single PO file.
+ */
+ bool scanFile(QString fileName);
+
+ /*
+ Scan a single URL file.
+ */
+ bool scanURL(KURL u);
+
+
+ /*
+ Scan a list of space separated files with possible MetaCharacters
+ */
+ bool scanPattern(QString pathName,QString pattern="*.po",bool rec=false);
+
+
+
+
+ signals:
+ void fileStarted();
+ void fileProgress(int);
+ void fileFinished();
+ void fileLoading(int);
+ void patternStarted();
+ void patternProgress(int);
+ void patternFinished();
+ void added(int);
+ void filename(QString);
+ private:
+
+ // If true when a translation is found in a CATALOG the old translation for this CATALOG
+ // will be removed
+ bool removeOldCatalogTranslation;
+ int count;
+ DataBaseInterface *di;
+ // InfoItem cinfo;
+};
+
+
+#endif
diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/dbse2.ui b/kbabel/kbabeldict/modules/dbsearchengine2/dbse2.ui
new file mode 100644
index 00000000..327a9d9d
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine2/dbse2.ui
@@ -0,0 +1,732 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>DBSearchEnginePrefWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>Form1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>447</width>
+ <height>483</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>tabWidget2</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>General</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox" row="0" column="0">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="title">
+ <string>Database</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>DB folder:</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="0" column="1">
+ <property name="name">
+ <cstring>dbDirectory</cstring>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>autoUpdate</cstring>
+ </property>
+ <property name="text">
+ <string>Automatic update in kbabel</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QGroupBox" row="1" column="0">
+ <property name="name">
+ <cstring>groupBox2</cstring>
+ </property>
+ <property name="title">
+ <string>New Entries</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Author:</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="0" column="2">
+ <property name="name">
+ <cstring>checkBox2</cstring>
+ </property>
+ <property name="text">
+ <string>From kbabel</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>kLineEdit1</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer7</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Algorithm</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="3" column="0">
+ <property name="name">
+ <cstring>textLabel5</cstring>
+ </property>
+ <property name="text">
+ <string>Minimum score:</string>
+ </property>
+ </widget>
+ <spacer row="4" column="1">
+ <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>40</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="Line" row="1" column="0" rowspan="1" colspan="3">
+ <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="QGroupBox" row="0" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>groupBox3</cstring>
+ </property>
+ <property name="title">
+ <string>Algorithms to Use</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="1" column="1">
+ <property name="name">
+ <cstring>textLabel3_2</cstring>
+ </property>
+ <property name="text">
+ <string>Score:</string>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="6" column="2">
+ <property name="name">
+ <cstring>scoreWordByWord</cstring>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="1" column="2">
+ <property name="name">
+ <cstring>scoreGlossary</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="1">
+ <property name="name">
+ <cstring>textLabel3_2_2</cstring>
+ </property>
+ <property name="text">
+ <string>Score:</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="3" column="0">
+ <property name="name">
+ <cstring>useSentence</cstring>
+ </property>
+ <property name="text">
+ <string>Fuzzy sentence archive</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="0">
+ <property name="name">
+ <cstring>useGlossary</cstring>
+ </property>
+ <property name="text">
+ <string>Glossary</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="0" column="0">
+ <property name="name">
+ <cstring>useExact</cstring>
+ </property>
+ <property name="text">
+ <string>Exact </string>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="4" column="2">
+ <property name="name">
+ <cstring>scoreDivide</cstring>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="0" column="2">
+ <property name="name">
+ <cstring>scoreExact</cstring>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="3" column="2">
+ <property name="name">
+ <cstring>scoreSentence</cstring>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="4" column="0">
+ <property name="name">
+ <cstring>useDivide</cstring>
+ </property>
+ <property name="text">
+ <string>Sentence by sentence</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="0">
+ <property name="name">
+ <cstring>useAlpha</cstring>
+ </property>
+ <property name="text">
+ <string>Alphanumeric</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="3" column="1">
+ <property name="name">
+ <cstring>textLabel3_2_3</cstring>
+ </property>
+ <property name="text">
+ <string>Score:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="4" column="1">
+ <property name="name">
+ <cstring>textLabel3_2_4</cstring>
+ </property>
+ <property name="text">
+ <string>Score:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="1">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Score:</string>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="2" column="2">
+ <property name="name">
+ <cstring>scoreAlpha</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="6" column="1">
+ <property name="name">
+ <cstring>textLabel3_2_6</cstring>
+ </property>
+ <property name="text">
+ <string>Score:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="5" column="1">
+ <property name="name">
+ <cstring>textLabel3_2_5</cstring>
+ </property>
+ <property name="text">
+ <string>Score:</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="6" column="0">
+ <property name="name">
+ <cstring>useWordByWord</cstring>
+ </property>
+ <property name="text">
+ <string>Word by word</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="5" column="0">
+ <property name="name">
+ <cstring>useDynamic</cstring>
+ </property>
+ <property name="text">
+ <string>Dynamic dictionary</string>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="5" column="2">
+ <property name="name">
+ <cstring>scoreDynamic</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>Preferred number of results:</string>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="2" column="2">
+ <property name="name">
+ <cstring>numberOfResult</cstring>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="3" column="2">
+ <property name="name">
+ <cstring>minScore</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Output</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox" row="0" column="0">
+ <property name="name">
+ <cstring>groupBox4</cstring>
+ </property>
+ <property name="title">
+ <string>Output Processing</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="3" column="0">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QCheckBox" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>firstCapital</cstring>
+ </property>
+ <property name="text">
+ <string>First capital letter match</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>allCapital</cstring>
+ </property>
+ <property name="text">
+ <string>All capital letter match</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>accelerator</cstring>
+ </property>
+ <property name="text">
+ <string>Accelerator symbol (&amp;&amp;)</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="3" column="1">
+ <property name="name">
+ <cstring>sameLetter</cstring>
+ </property>
+ <property name="text">
+ <string>Try to use same letter</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QGroupBox" row="1" column="0">
+ <property name="name">
+ <cstring>groupBox5</cstring>
+ </property>
+ <property name="title">
+ <string>Custom Rules</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Original string regexp:</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="0" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>kLineEdit1_2</cstring>
+ </property>
+ </widget>
+ <widget class="QListView" row="3" column="0" rowspan="3" colspan="2">
+ <column>
+ <property name="text">
+ <string>Enabled</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Description</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <item>
+ <property name="text">
+ <string>New Item</string>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="pixmap">
+ <pixmap></pixmap>
+ </property>
+ <property name="pixmap">
+ <pixmap></pixmap>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>customRules</cstring>
+ </property>
+ </widget>
+ <spacer row="5" column="2">
+ <property name="name">
+ <cstring>spacer7_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>
+ <widget class="KPushButton" row="4" column="2">
+ <property name="name">
+ <cstring>deleteRule</cstring>
+ </property>
+ <property name="text">
+ <string>Delete</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="3" column="2">
+ <property name="name">
+ <cstring>addRule</cstring>
+ </property>
+ <property name="text">
+ <string>Add</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel3_3</cstring>
+ </property>
+ <property name="text">
+ <string>Replace string:</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="2" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>kLineEdit3</cstring>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="1" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>kLineEdit2</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel2_2</cstring>
+ </property>
+ <property name="text">
+ <string>Translated regexp(search):</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Import</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox" row="0" column="0">
+ <property name="name">
+ <cstring>groupBox6</cstring>
+ </property>
+ <property name="title">
+ <string>Options</string>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>checkLang</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>20</x>
+ <y>30</y>
+ <width>150</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Check language</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>useFilters</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>20</x>
+ <y>60</y>
+ <width>140</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Use current filters</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>dateToday</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>20</x>
+ <y>90</y>
+ <width>180</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Set date to today</string>
+ </property>
+ </widget>
+ </widget>
+ <widget class="QGroupBox" row="1" column="0">
+ <property name="name">
+ <cstring>groupBox7</cstring>
+ </property>
+ <property name="title">
+ <string>Sources</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton" row="1" column="1">
+ <property name="name">
+ <cstring>editSource</cstring>
+ </property>
+ <property name="text">
+ <string>Edit</string>
+ </property>
+ </widget>
+ <widget class="KPushButton" row="2" column="1">
+ <property name="name">
+ <cstring>removeSource</cstring>
+ </property>
+ <property name="text">
+ <string>Remove</string>
+ </property>
+ </widget>
+ <widget class="KPushButton" row="3" column="1">
+ <property name="name">
+ <cstring>scanSource</cstring>
+ </property>
+ <property name="text">
+ <string>Scan Now</string>
+ </property>
+ </widget>
+ <widget class="KPushButton" row="0" column="1">
+ <property name="name">
+ <cstring>addSource</cstring>
+ </property>
+ <property name="text">
+ <string>Add</string>
+ </property>
+ </widget>
+ <spacer row="4" column="1">
+ <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>40</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KPushButton" row="5" column="1">
+ <property name="name">
+ <cstring>scanAll</cstring>
+ </property>
+ <property name="text">
+ <string>Scan All</string>
+ </property>
+ </widget>
+ <widget class="QListBox" row="0" column="0" rowspan="6" colspan="1">
+ <property name="name">
+ <cstring>sourceList</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Filters</string>
+ </attribute>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/dbse2_factory.cpp b/kbabel/kbabeldict/modules/dbsearchengine2/dbse2_factory.cpp
new file mode 100644
index 00000000..9c286052
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine2/dbse2_factory.cpp
@@ -0,0 +1,83 @@
+
+#include <klocale.h>
+#include <kinstance.h>
+#include <kaboutdata.h>
+#include <kdebug.h>
+
+#include "dbse2_factory.h"
+#include "KDBSearchEngine2.h"
+
+
+extern "C"
+{
+ KDE_EXPORT void *init_kbabeldict_dbsearchengine2()
+// void *init_libdbsearchengine2()
+ {
+ return new DbSe2Factory;
+ }
+};
+
+
+KInstance *DbSe2Factory::s_instance = 0;
+KAboutData *DbSe2Factory::s_about = 0;
+
+
+DbSe2Factory::DbSe2Factory( QObject *parent, const char *name)
+ : KLibFactory(parent,name)
+{
+}
+
+DbSe2Factory::~DbSe2Factory()
+{
+ if(s_instance)
+ {
+ delete s_instance;
+ s_instance=0;
+ }
+
+ if(s_about)
+ {
+ delete s_about;
+ s_about=0;
+ }
+}
+
+
+QObject *DbSe2Factory::createObject( QObject *parent, const char *name,
+ const char *classname, const QStringList &)
+{
+ if(QCString(classname) != "SearchEngine")
+ {
+ kdError() << "not a SearchEngine requested" << endl;
+ return 0;
+ }
+
+ KDBSearchEngine2 *se = new KDBSearchEngine2(parent,name);
+
+ emit objectCreated(se);
+ return se;
+}
+
+
+KInstance *DbSe2Factory::instance()
+{
+ if(!s_instance)
+ {
+
+ s_about = new KAboutData( "kdbsearchengine2",
+ I18N_NOOP("Translation Database")
+ , "1.99" ,
+I18N_NOOP("A fast translation search engine based on databases")
+ , KAboutData::License_GPL
+ , I18N_NOOP("Copyright 2000-2003 by Andrea Rizzi")
+ ,0,0, "rizzi@kde.org");
+
+ s_about->addAuthor("Andrea Rizzi",0,"rizzi@kde.org");
+
+ s_instance = new KInstance(s_about);
+ }
+
+ return s_instance;
+}
+
+#include "dbse2_factory.moc"
diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/dbse2_factory.h b/kbabel/kbabeldict/modules/dbsearchengine2/dbse2_factory.h
new file mode 100644
index 00000000..4285d53c
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine2/dbse2_factory.h
@@ -0,0 +1,26 @@
+#ifndef DBSE2_FACTORY_H
+#define DBSE2_FACTORY_H
+
+#include <klibloader.h>
+class KInstance;
+class KAboutData;
+
+class DbSe2Factory : public KLibFactory
+{
+ Q_OBJECT
+public:
+ DbSe2Factory( QObject *parent=0, const char *name=0);
+ ~DbSe2Factory();
+
+ virtual QObject *createObject( QObject *parent=0, const char *name=0,
+ const char *classname="QObject",
+ const QStringList &args = QStringList());
+
+ static KInstance *instance();
+
+private:
+ static KInstance *s_instance;
+ static KAboutData *s_about;
+};
+
+#endif
diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/dbsearchengine2.desktop b/kbabel/kbabeldict/modules/dbsearchengine2/dbsearchengine2.desktop
new file mode 100644
index 00000000..a46bfff1
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine2/dbsearchengine2.desktop
@@ -0,0 +1,52 @@
+[Desktop Entry]
+Type=Service
+Name=Translation Database v2 for KBabelDict
+Name[bg]=БД Ñ Ð¿Ñ€ÐµÐ²Ð¾Ð´Ð¸ v2 за KBabelDict
+Name[br]=Stlennvon geriaoueg v2 evit KBabelDict
+Name[bs]=Baza prijevoda v2 za KBabelDict
+Name[ca]=Base de dades de traducció v2 per a KBabelDict
+Name[cs]=Databáze překladů v2 pro KBabelDict
+Name[cy]=Cronfa ddata Cyfieithiadau v2 i KBabelDict
+Name[da]=Oversættelsesdatabase v2 for KBabelDict
+Name[de]=Übersetzungsdatenbank Version 2 für KBabelDict
+Name[el]=Βάση δεδομένων μετάφÏασης έκδοση 2 για το KBabelDict
+Name[es]=Base de datos de traducciones v2 para KBabelDict
+Name[et]=KBabelDicti tõlgete andmebaas (versioon 2)
+Name[eu]=v2 itzulpen datu-basea KBabelDict-entzat
+Name[fa]=دادگان ترجمۀ نسخه ۲ برای KBabelDict
+Name[fi]=KBabelDict-ohjelman käännöstietokanta v2
+Name[fr]=Base de données des traductions v2 pour KBabelDict
+Name[ga]=Cuimhne Aistriúcháin (v2) le haghaidh KBabelDict
+Name[gl]=Base de datos de traducións v2 de KBabelDict
+Name[hi]=के-बेबल-डिकà¥à¤¶ के लिठअनà¥à¤µà¤¾à¤¦ डाटाबेस वी2
+Name[hu]=Fordítási adatbázis (v2) a KBabelDicthez
+Name[is]=Þýðingagagnagrunnur v2 fyrir KBabel orðabókina
+Name[it]=Banca dati delle traduzioni v2 per KBabelDict
+Name[ja]=KBabelDict トランザクションデータベース v2
+Name[ka]=თáƒáƒ áƒ’მნის მáƒáƒœáƒáƒªáƒ”მთრბáƒáƒ–რვ2 KBabelDict-სთვის
+Name[kk]=KBabelDict-Ñ‚Ñ‹Ò£ аударма деректер қорының 2-нұÑқаÑÑ‹
+Name[lt]=KBabelDict vertimų duomenų bazės 2 versija
+Name[ms]=Pangkalan Data Penterjemahan v2 KBabelDict
+Name[nb]=Oversettelsesdatabase versjon 2 for KBabelDict
+Name[nds]=Översettendatenbank V2 för KBabelDict
+Name[ne]=KBabelDict का लागि अनà¥à¤¬à¤¾à¤¦ डाटाबेस v2
+Name[nl]=Vertalingendatabase versie2 voor KBabelDict
+Name[nn]=Omsetjingsdatabase versjon 2 for KBabelDict
+Name[pa]=ਕੇਬਬੇਲ-ਸ਼ਬਦ-ਕੋਸ਼ ਲਈ ਅਨà©à¨µà¨¾à¨¦ ਡਾਟਾਬੇਸ ਵਰਜਨ2
+Name[pl]=Baza tłumaczeń v2 dla KBabelDict
+Name[pt]=Base de Dados de Traduções v2 do KBabelDict
+Name[pt_BR]=Banco de Dados de Traduções v2 para o KBabelDict
+Name[ru]=ВерÑÐ¸Ñ 2 базы данных перевода Ð´Ð»Ñ KBabelDict
+Name[sk]=Databáza prekladov v2 pre KBabelDict
+Name[sl]=Zbirka prevodov razliÄice 2 za KBabelDict
+Name[sr]=Преводилачка база података v2 за KBabelDict
+Name[sr@Latn]=PrevodilaÄka baza podataka v2 za KBabelDict
+Name[sv]=Översättningsdatabas version 2 för Kbabeldict
+Name[ta]= Kபாபேலà¯à®•à¯à®•à®¾à®© மொழிபெயரà¯à®ªà¯à®ªà¯ தரவà¯à®¤à¯à®¤à®³à®®à¯ v2
+Name[tg]=ТафÑири 2 базаи маълумоти тарҷумаҳо барои KBabelDict
+Name[tr]=KBabelDict için Çeviri Veritabanı v2
+Name[uk]=ВерÑÑ–Ñ 2 бази даних перекладів Ð´Ð»Ñ KBabelDict
+Name[zh_CN]=KBabelDict 的翻译数æ®åº“ v2
+Name[zh_TW]=KBabelDict 翻譯資料庫 v2
+X-KDE-Library=kbabeldict_dbsearchengine2
+ServiceTypes=KBabelDictModule
diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/dbseprefwidget.ui b/kbabel/kbabeldict/modules/dbsearchengine2/dbseprefwidget.ui
new file mode 100644
index 00000000..c233265f
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine2/dbseprefwidget.ui
@@ -0,0 +1,1039 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>DBSearchEnginePref</class>
+<author>Andrea Rizzi &lt;rizzi@kde.org&gt;</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>DBSEPrefWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>414</width>
+ <height>426</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>DBSEPrefWidget</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="QTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>TabWidget6</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string></string>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>Widget4</cstring>
+ </property>
+ <attribute name="title">
+ <string>Generic</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>ButtonGroup2</cstring>
+ </property>
+ <property name="title">
+ <string>Search Mode</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="QRadioButton" row="0" column="0">
+ <property name="name">
+ <cstring>allRB</cstring>
+ </property>
+ <property name="text">
+ <string>Search in whole database (slow)</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qml&gt;Scroll the whole database and return everything that matches
+according to the rules defined in tabs &lt;strong&gt; Generic &lt;/strong&gt;
+and &lt;strong&gt;Match&lt;/strong&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="1" column="0">
+ <property name="name">
+ <cstring>slistRB</cstring>
+ </property>
+ <property name="text">
+ <string>Search in list of "good keys" (best)</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qml&gt;Search in a list of &lt;em&gt;good keys&lt;/em&gt; (see &lt;strong&gt;Good keys&lt;/strong&gt; tab) with rules defined in &lt;strong&gt;Search&lt;/strong&gt; tab.
+This is the best way to search because the &lt;em&gt;good keys&lt;/em&gt; list probably contains all the keys that match with your query. However, it is smaller than the whole database.</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="2" column="0">
+ <property name="name">
+ <cstring>rlistRB</cstring>
+ </property>
+ <property name="text">
+ <string>Return the list of "good keys" (fast)</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qml&gt;Returns the whole &lt;em&gt;good keys&lt;/em&gt; list. Rules defined in &lt;strong&gt;Search&lt;/strong&gt; tab are ignored.</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>caseSensitiveCB</cstring>
+ </property>
+ <property name="text">
+ <string>Case sensitive</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qml&gt;If it is checked the search will be case sensitive. It is ignored if you use &lt;em&gt;Return the list of "good keys"&lt;/em&gt; search mode.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>normalizeCB</cstring>
+ </property>
+ <property name="text">
+ <string>Normalize white space</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Remove white spaces at the beginning and at the end of the phrase.
+It also substitutes groups of more than one space character with only one space character.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>removeContextCB</cstring>
+ </property>
+ <property name="text">
+ <string>Remove context comment</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Remove, if exists, the _:comment</string>
+ </property>
+ </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>TextLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Character to be ignored:</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>ignoreLE</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>Widget5</cstring>
+ </property>
+ <attribute name="title">
+ <string>Search</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>ButtonGroup1</cstring>
+ </property>
+ <property name="title">
+ <string>Matching Method</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>Spacer4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>Spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QCheckBox" row="2" column="1">
+ <property name="name">
+ <cstring>containedCB</cstring>
+ </property>
+ <property name="text">
+ <string>Query is contained</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Match if query is contained in database string</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="3" column="1">
+ <property name="name">
+ <cstring>containsCB</cstring>
+ </property>
+ <property name="text">
+ <string>Query contains</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Match if query contains the database string</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>normalTextRB</cstring>
+ </property>
+ <property name="text">
+ <string>Normal text</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Consider the search string as normal text.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="1">
+ <property name="name">
+ <cstring>equalCB</cstring>
+ </property>
+ <property name="text">
+ <string>Equal</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="tristate">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Match if query and database string are equal</string>
+ </property>
+ </widget>
+ <spacer row="3" column="0">
+ <property name="name">
+ <cstring>Spacer7</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QRadioButton" row="4" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>RegExpRB</cstring>
+ </property>
+ <property name="text">
+ <string>Regular expression</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Consider the search string as a regular expression</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>GroupBox3</cstring>
+ </property>
+ <property name="title">
+ <string>Word Substitution</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qml&gt;If you use one or two &lt;em&gt;word substitution&lt;/em&gt; each time you search a phrase with less than the specified number of words, the search engine will also search for all phrases that differ from the original one in one or two words.&lt;p&gt;
+&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
+If you search for &lt;em&gt;My name is Andrea&lt;/em&gt; and you have activated &lt;em&gt;one word substitution&lt;/em&gt; you may also find phrases like &lt;em&gt;My name is Joe&lt;/em&gt; or &lt;em&gt;Your name is Andrea&lt;/em&gt;.</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <spacer row="3" column="0">
+ <property name="name">
+ <cstring>Spacer8</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QCheckBox" row="0" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>oneWordSubCB</cstring>
+ </property>
+ <property name="text">
+ <string>Use one word substitution</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="tristate">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>Spacer9</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel" row="1" column="1">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Max number of words in the query:</string>
+ </property>
+ </widget>
+ <widget class="QSpinBox" row="3" column="2">
+ <property name="name">
+ <cstring>twoWordSubSB</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="maxValue">
+ <number>14</number>
+ </property>
+ <property name="value">
+ <number>10</number>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>twoWordSubCB</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Use two word substitution</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QLabel" row="3" column="1">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Max number of words in the query:</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="5" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>Layout7</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>TextLabel5_3</cstring>
+ </property>
+ <property name="text">
+ <string>[A-Za-z0-9_%</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="hAlign" stdset="0">
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>regExpLE</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel6_2</cstring>
+ </property>
+ <property name="text">
+ <string>]</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel" row="4" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>TextLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>Local characters for regular expressions:</string>
+ </property>
+ </widget>
+ <widget class="QSpinBox" row="1" column="2">
+ <property name="name">
+ <cstring>oneWordSubSB</cstring>
+ </property>
+ <property name="maxValue">
+ <number>200</number>
+ </property>
+ <property name="minValue">
+ <number>2</number>
+ </property>
+ <property name="value">
+ <number>40</number>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer1_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>Widget6</cstring>
+ </property>
+ <attribute name="title">
+ <string>Database</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel" row="0" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>TextLabel7_2</cstring>
+ </property>
+ <property name="text">
+ <string>Database folder:</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="1" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>dirInput</cstring>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>autoAddCB_2</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Auto add entry to database</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Automatically add an entry to the database if a new translation is notified by someone (may be kbabel)</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="3" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>Layout3</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_4</cstring>
+ </property>
+ <property name="text">
+ <string>Auto added entry author:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>authorLE</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qml&gt;Put here the name and email address that you want to use as &lt;em&gt;last translator&lt;/em&gt; filed when you auto-add entry to the database (e.g. when you modify a translation with kbabel).&lt;p&gt;</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QPushButton" row="4" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>scanFilePB</cstring>
+ </property>
+ <property name="text">
+ <string>Scan Single PO File</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="5" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>scanPB_2</cstring>
+ </property>
+ <property name="text">
+ <string>Scan Folder</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="6" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>scanrecPB</cstring>
+ </property>
+ <property name="text">
+ <string>Scan Folder &amp;&amp; Subfolders</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="8" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>Layout5</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>filenameLB</cstring>
+ </property>
+ <property name="text">
+ <string>Scanning file:</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>entriesLB</cstring>
+ </property>
+ <property name="text">
+ <string>Entries added:</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget" row="9" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>Layout4</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QProgressBar" row="2" column="1">
+ <property name="name">
+ <cstring>processPB</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>Panel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="centerIndicator">
+ <bool>true</bool>
+ </property>
+ <property name="indicatorFollowsStyle">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel1_3</cstring>
+ </property>
+ <property name="text">
+ <string>Total progress:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>TextLabel3_3</cstring>
+ </property>
+ <property name="text">
+ <string>Processing file:</string>
+ </property>
+ </widget>
+ <widget class="QProgressBar" row="0" column="1">
+ <property name="name">
+ <cstring>totalPB</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>Panel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="centerIndicator">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QProgressBar" row="1" column="1">
+ <property name="name">
+ <cstring>loadingPB</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>Panel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="centerIndicator">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>TextLabel2_3</cstring>
+ </property>
+ <property name="text">
+ <string>Loading file:</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QPushButton" row="10" column="2">
+ <property name="name">
+ <cstring>exportPB</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Export...</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="10" column="0">
+ <property name="name">
+ <cstring>statPB</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Statistics</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="10" column="1">
+ <property name="name">
+ <cstring>repeatPB</cstring>
+ </property>
+ <property name="text">
+ <string>Repeated Strings</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Good Keys</string>
+ </attribute>
+ <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>GroupBox4</cstring>
+ </property>
+ <property name="title">
+ <string>Generic</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qml&gt;Here you can define how to fill the &lt;em&gt;good keys list&lt;/em&gt;.&lt;p&gt;
+You can set the minimum number of words of the query that a key must have to be inserted in the &lt;em&gt;good keys list&lt;/em&gt;.&lt;p&gt;
+You can also set the minimum number of words of the key that the query must have to insert the key in the list.&lt;p&gt;
+These two numbers are the percentage of the total number of words. If the result of this percentage is less than one, the engine will set it to one.&lt;p&gt;
+Finally you can set the maximum number of entries in the list.</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="QLabel" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>TextLabel3_2</cstring>
+ </property>
+ <property name="text">
+ <string>Minimum number of words of the key also in the query (%):</string>
+ </property>
+ <property name="textFormat">
+ <enum>RichText</enum>
+ </property>
+ </widget>
+ <widget class="QSlider" row="1" column="0">
+ <property name="name">
+ <cstring>thresholdSL</cstring>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>50</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="QSpinBox" row="1" column="1">
+ <property name="name">
+ <cstring>SpinBox5</cstring>
+ </property>
+ <property name="suffix">
+ <string>%</string>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>50</number>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>TextLabel2_2</cstring>
+ </property>
+ <property name="text">
+ <string>Minimum number of query words in the key (%):</string>
+ </property>
+ </widget>
+ <widget class="QSpinBox" row="4" column="1">
+ <property name="name">
+ <cstring>maxSB</cstring>
+ </property>
+ <property name="maxValue">
+ <number>5000</number>
+ </property>
+ <property name="value">
+ <number>30</number>
+ </property>
+ </widget>
+ <widget class="QSpinBox" row="3" column="1">
+ <property name="name">
+ <cstring>SpinBox6</cstring>
+ </property>
+ <property name="suffix">
+ <string>%</string>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>50</number>
+ </property>
+ </widget>
+ <widget class="QLabel" row="4" column="0">
+ <property name="name">
+ <cstring>TextLabel4_2</cstring>
+ </property>
+ <property name="text">
+ <string>Max list length:</string>
+ </property>
+ </widget>
+ <widget class="QSlider" row="3" column="0">
+ <property name="name">
+ <cstring>thresholdOrigSL</cstring>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>50</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>GroupBox3_2</cstring>
+ </property>
+ <property name="title">
+ <string>Frequent Words</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="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Discard words more frequent than:</string>
+ </property>
+ </widget>
+ <widget class="QSpinBox" row="0" column="1">
+ <property name="name">
+ <cstring>freqSB</cstring>
+ </property>
+ <property name="suffix">
+ <string>/10000</string>
+ </property>
+ <property name="maxValue">
+ <number>10000</number>
+ </property>
+ <property name="lineStep">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>nothingCB</cstring>
+ </property>
+ <property name="text">
+ <string>Frequent words are considered as in every key</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>thresholdSL</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>SpinBox5</receiver>
+ <slot>setValue(int)</slot>
+ </connection>
+ <connection>
+ <sender>thresholdOrigSL</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>SpinBox6</receiver>
+ <slot>setValue(int)</slot>
+ </connection>
+ <connection>
+ <sender>SpinBox5</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>thresholdSL</receiver>
+ <slot>setValue(int)</slot>
+ </connection>
+ <connection>
+ <sender>SpinBox6</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>thresholdOrigSL</receiver>
+ <slot>setValue(int)</slot>
+ </connection>
+</connections>
+<includes>
+ <include location="local" impldecl="in declaration">klocale.h</include>
+ <include location="global" impldecl="in declaration">kseparator.h</include>
+</includes>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/preferenceswidget.cpp b/kbabel/kbabeldict/modules/dbsearchengine2/preferenceswidget.cpp
new file mode 100644
index 00000000..7634a799
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine2/preferenceswidget.cpp
@@ -0,0 +1,98 @@
+#include <qradiobutton.h>
+#include <qslider.h>
+#include <qspinbox.h>
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <klocale.h>
+#include <kfiledialog.h>
+#include <kurlrequester.h>
+#include <qtoolbutton.h>
+#include <klineedit.h>
+#include <kstandarddirs.h>
+#include <knuminput.h>
+
+#include "dbse2.h"
+#include "preferenceswidget.h"
+
+KDB2PreferencesWidget::KDB2PreferencesWidget(QWidget *parent, const char* name)
+ : PrefWidget(parent,name)
+{
+ QVBoxLayout *layout = new QVBoxLayout(this);
+// QLabel *label = new QLabel(i18n("Settings for KDE Database Search Engine"),this);
+// layout->addWidget(label);
+
+ dbpw = new DBSearchEnginePrefWidget(this);
+ dbpw->dbDirectory->setMode(KFile::Directory | KFile::LocalOnly);
+ dbpw->show();
+ layout->addWidget(dbpw);
+ setMinimumSize(300,300);
+
+ standard();
+
+// connect(dbpw->browseTB_3,SIGNAL(clicked()),SLOT(browse1()));
+
+ emit restoreNow(); //Fill with actual params.
+
+}
+
+KDB2PreferencesWidget::~KDB2PreferencesWidget()
+{
+}
+
+void KDB2PreferencesWidget::apply()
+{
+emit applyNow();
+}
+
+void KDB2PreferencesWidget::cancel()
+{
+emit restoreNow();
+}
+
+void KDB2PreferencesWidget::standard()
+{
+QString defaultDir;
+ KStandardDirs * dirs = KGlobal::dirs();
+ if(dirs)
+ {
+ defaultDir = dirs->saveLocation("data");
+ if(defaultDir.right(1)!="/")
+ defaultDir+="/";
+ defaultDir += "kbabeldict/dbsearchengine2";
+ }
+dbpw->dbDirectory->setURL(defaultDir);
+
+dbpw->autoUpdate->setChecked(true);
+
+dbpw->useSentence->setChecked(true);
+dbpw->useGlossary->setChecked(true);
+dbpw->useExact->setChecked(true);
+dbpw->useDivide->setChecked(true);
+dbpw->useAlpha->setChecked(true);
+dbpw->useWordByWord->setChecked(true);
+dbpw->useDynamic->setChecked(true);
+dbpw->scoreDivide->setValue(90);
+dbpw->scoreExact->setValue(100);
+dbpw->scoreSentence->setValue(90);
+dbpw->scoreWordByWord->setValue(70);
+dbpw->scoreGlossary->setValue(98);
+dbpw->scoreAlpha->setValue(98);
+dbpw->scoreDynamic->setValue(80);
+
+dbpw->numberOfResult->setValue(5);
+dbpw->minScore->setValue(60);
+
+dbpw->firstCapital->setChecked(true);
+dbpw->allCapital->setChecked(false);
+dbpw->accelerator->setChecked(true);
+dbpw->sameLetter->setChecked(true);
+dbpw->checkLang->setChecked(true);
+dbpw->useFilters->setChecked(false);
+dbpw->dateToday->setChecked(false);
+/*
+ */
+ //dbpw->dirInput->setURL(defaultDir);
+}
+
+#include "preferenceswidget.moc"
diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/preferenceswidget.h b/kbabel/kbabeldict/modules/dbsearchengine2/preferenceswidget.h
new file mode 100644
index 00000000..4714fd13
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine2/preferenceswidget.h
@@ -0,0 +1,26 @@
+#ifndef PREFERENCESWIDGET_H
+#define PREFERENCESWIDGET_H
+
+#include "searchengine.h"
+#include "dbse2.h"
+
+class KDB2PreferencesWidget : public PrefWidget
+{
+ Q_OBJECT
+
+public:
+ KDB2PreferencesWidget(QWidget *parent=0, const char* name=0);
+ virtual ~KDB2PreferencesWidget();
+
+ virtual void apply();
+ virtual void cancel();
+ virtual void standard();
+ DBSearchEnginePrefWidget *dbpw;
+
+signals:
+ void applyNow();
+ void restoreNow();
+
+};
+
+#endif
diff --git a/kbabel/kbabeldict/modules/dbsearchengine2/sourcedialog.ui b/kbabel/kbabeldict/modules/dbsearchengine2/sourcedialog.ui
new file mode 100644
index 00000000..3f4030a0
--- /dev/null
+++ b/kbabel/kbabeldict/modules/dbsearchengine2/sourcedialog.ui
@@ -0,0 +1,266 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>SourceDialog</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>SourceDialog</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>415</width>
+ <height>385</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Edit Source</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="2" column="1">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KPushButton" row="2" column="0">
+ <property name="name">
+ <cstring>ok</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;OK</string>
+ </property>
+ </widget>
+ <widget class="KPushButton" row="2" column="2">
+ <property name="name">
+ <cstring>cancel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Cancel</string>
+ </property>
+ </widget>
+ <widget class="QGroupBox" row="1" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="title">
+ <string>Additional Informations</string>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel6</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>11</x>
+ <y>76</y>
+ <width>108</width>
+ <height>29</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Status: </string>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>projectName</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>125</x>
+ <y>22</y>
+ <width>182</width>
+ <height>21</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>projectKeywords</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>125</x>
+ <y>49</y>
+ <width>182</width>
+ <height>21</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="KComboBox">
+ <property name="name">
+ <cstring>status</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>125</x>
+ <y>76</y>
+ <width>182</width>
+ <height>29</height>
+ </rect>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>11</x>
+ <y>22</y>
+ <width>108</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Project name:</string>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel5</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>11</x>
+ <y>49</y>
+ <width>108</width>
+ <height>21</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Project keywords:</string>
+ </property>
+ </widget>
+ </widget>
+ <widget class="QGroupBox" row="0" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>groupBox2</cstring>
+ </property>
+ <property name="title">
+ <string>General Info</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>sourceName</cstring>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="1" column="1">
+ <item>
+ <property name="text">
+ <string>Single File</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Single Folder</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Recursive Folder</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>type</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Source name:</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="2" column="1">
+ <property name="name">
+ <cstring>sourceLocation</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Type:</string>
+ </property>
+ </widget>
+ <widget class="KPushButton" row="3" column="1">
+ <property name="name">
+ <cstring>filterDialog</cstring>
+ </property>
+ <property name="text">
+ <string>Setup Filter...</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Location:</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="3" column="0">
+ <property name="name">
+ <cstring>useFilter</cstring>
+ </property>
+ <property name="text">
+ <string>Use filter</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<connections>
+ <connection>
+ <sender>ok</sender>
+ <signal>clicked()</signal>
+ <receiver>SourceDialog</receiver>
+ <slot>accept()</slot>
+ </connection>
+ <connection>
+ <sender>cancel</sender>
+ <signal>clicked()</signal>
+ <receiver>SourceDialog</receiver>
+ <slot>reject()</slot>
+ </connection>
+</connections>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kbabel/kbabeldict/modules/poauxiliary/Makefile.am b/kbabel/kbabeldict/modules/poauxiliary/Makefile.am
new file mode 100644
index 00000000..75509337
--- /dev/null
+++ b/kbabel/kbabeldict/modules/poauxiliary/Makefile.am
@@ -0,0 +1,36 @@
+## Makefile.am for poauxiliary
+
+# this has all of the subdirectories that make will recurse into. if
+# there are none, comment this out
+#SUBDIRS =
+
+
+# this is the program that gets installed. it's name is used for all
+# of the other Makefile.am variables
+kde_module_LTLIBRARIES = kbabeldict_poauxiliary.la
+
+# set the include path for X, qt and KDE
+INCLUDES = -I$(srcdir)/../.. -I../../../common -I$(srcdir)/../../../common $(all_includes)
+
+
+kbabeldict_poauxiliary_la_SOURCES = poauxiliary.cpp preferenceswidget.cpp\
+ pa_factory.cpp pwidget.ui
+kbabeldict_poauxiliary_la_LIBADD = ../../libkbabeldictplugin.la ../../../common/libkbabelcommon.la $(LIB_KDEUI) $(LIB_KIO)
+kbabeldict_poauxiliary_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined
+
+
+
+# these are the headers for your project
+noinst_HEADERS = poauxiliary.h preferenceswidget.h pa_factory.h
+
+
+# let automoc handle all of the meta source files (moc)
+METASOURCES = AUTO
+
+
+# this is where the kdelnk file will go
+#datadir = $(kde_datadir)/kbabeldict/modules
+#data_DATA = poauxiliary.rc
+
+kde_services_DATA = poauxiliary.desktop
+EXTRA_DIST = $(kde_services_DATA)
diff --git a/kbabel/kbabeldict/modules/poauxiliary/pa_factory.cpp b/kbabel/kbabeldict/modules/poauxiliary/pa_factory.cpp
new file mode 100644
index 00000000..1448e2b0
--- /dev/null
+++ b/kbabel/kbabeldict/modules/poauxiliary/pa_factory.cpp
@@ -0,0 +1,110 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#include <klocale.h>
+#include <kinstance.h>
+#include <kaboutdata.h>
+#include <kdebug.h>
+
+#include "pa_factory.h"
+#include "poauxiliary.h"
+
+
+extern "C"
+{
+ KDE_EXPORT void *init_kbabeldict_poauxiliary()
+ {
+ return new PaFactory;
+ }
+}
+
+
+KInstance *PaFactory::s_instance = 0;
+KAboutData *PaFactory::s_about = 0;
+
+
+PaFactory::PaFactory( QObject *parent, const char *name)
+ : KLibFactory(parent,name)
+{
+}
+
+PaFactory::~PaFactory()
+{
+ if(s_instance)
+ {
+ delete s_instance;
+ s_instance=0;
+ }
+
+ if(s_about)
+ {
+ delete s_about;
+ s_about=0;
+ }
+}
+
+
+QObject *PaFactory::createObject( QObject *parent, const char *name
+ , const char *classname, const QStringList &)
+{
+ if(QCString(classname) != "SearchEngine")
+ {
+ kdError() << "not a SearchEngine requested" << endl;
+ return 0;
+ }
+
+ return new PoAuxiliary(parent,name);
+}
+
+
+KInstance *PaFactory::instance()
+{
+ if(!s_instance)
+ {
+ s_about = new KAboutData( "poauxiliary", I18N_NOOP("PO Auxiliary")
+ , "1.0"
+ , I18N_NOOP("A simple module for exact searching in a PO file")
+ , KAboutData::License_GPL
+ , "Copyright 2000, Matthias Kiefer"
+ ,0,0, "kiefer@kde.org");
+
+ s_about->addAuthor("Matthias Kiefer",0,"kiefer@kde.org");
+
+ s_instance = new KInstance(s_about);
+ }
+
+ return s_instance;
+}
+
+#include "pa_factory.moc"
diff --git a/kbabel/kbabeldict/modules/poauxiliary/pa_factory.h b/kbabel/kbabeldict/modules/poauxiliary/pa_factory.h
new file mode 100644
index 00000000..8871a538
--- /dev/null
+++ b/kbabel/kbabeldict/modules/poauxiliary/pa_factory.h
@@ -0,0 +1,60 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#ifndef PA_FACTORY_H
+#define PA_FACTORY_H
+
+#include <klibloader.h>
+class KInstance;
+class KAboutData;
+
+class PaFactory : public KLibFactory
+{
+ Q_OBJECT
+public:
+ PaFactory( QObject *parent=0, const char *name=0);
+ ~PaFactory();
+
+ virtual QObject *createObject( QObject *parent=0, const char *name=0
+ , const char *classname="QObject"
+ , const QStringList &args = QStringList());
+
+ static KInstance *instance();
+
+private:
+ static KInstance *s_instance;
+ static KAboutData *s_about;
+};
+
+#endif
diff --git a/kbabel/kbabeldict/modules/poauxiliary/poauxiliary.cpp b/kbabel/kbabeldict/modules/poauxiliary/poauxiliary.cpp
new file mode 100644
index 00000000..373f123d
--- /dev/null
+++ b/kbabel/kbabeldict/modules/poauxiliary/poauxiliary.cpp
@@ -0,0 +1,554 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include <klocale.h>
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kinstance.h>
+
+#include <qregexp.h>
+#include <qtimer.h>
+#include <qstylesheet.h>
+
+#include "poauxiliary.h"
+#include "preferenceswidget.h"
+#include "pa_factory.h"
+
+#include <resources.h>
+#include <catalog.h>
+
+using namespace KBabel;
+
+PoAuxiliary::PoAuxiliary(QObject *parent, const char *name)
+ : SearchEngine(parent, name)
+{
+ catalog = new Catalog(this, "PoAuxiliary::catalog");
+ prefWidget=0;
+ error=false;
+ stop=false;
+ active=false;
+ loading=false;
+ initialized=false;
+
+ ignoreFuzzy=true;
+
+ loadTimer = new QTimer(this);
+ connect(loadTimer,SIGNAL(timeout()),this,SLOT(loadAuxiliary()));
+
+ msgidDict.setAutoDelete(true);
+}
+
+PoAuxiliary::~PoAuxiliary()
+{
+ results.clear();
+}
+
+bool PoAuxiliary::isReady() const
+{
+ return !error;
+}
+
+
+bool PoAuxiliary::isSearching() const
+{
+ return active;
+}
+
+
+void PoAuxiliary::saveSettings(KConfigBase *config)
+{
+ if(autoUpdate && prefWidget && prefWidget->settingsChanged())
+ {
+ applySettings();
+ }
+
+ config->writeEntry("Auxiliary", url);
+ config->writeEntry("IgnoreFuzzy",ignoreFuzzy);
+}
+
+void PoAuxiliary::readSettings(KConfigBase *config)
+{
+ bool needLoading=false;
+
+ QString newPath = config->readEntry("Auxiliary"
+ ,"../../../de/messages/@DIR1@/@PACKAGE@.po");
+ if(!initialized)
+ {
+ url = newPath;
+ }
+ else if(newPath != url)
+ {
+ url = newPath;
+ needLoading = true;
+ }
+
+ ignoreFuzzy = config->readBoolEntry("IgnoreFuzzy",true);
+
+ if(needLoading && !loadTimer->isActive())
+ {
+ kdDebug(KBABEL_SEARCH) << "readSettings" << endl;
+ loadTimer->start(100,true);
+ }
+
+ restoreSettings();
+}
+
+PrefWidget *PoAuxiliary::preferencesWidget(QWidget *parent)
+{
+ prefWidget = new AuxiliaryPreferencesWidget(parent,"pocompendium_prefwidget");
+ connect(prefWidget, SIGNAL(applySettings()), this, SLOT(applySettings()));
+ connect(prefWidget, SIGNAL(restoreSettings())
+ , this, SLOT(restoreSettings()));
+
+ restoreSettings();
+
+ return prefWidget;
+}
+
+const KAboutData *PoAuxiliary::about() const
+{
+ return PaFactory::instance()->aboutData();
+}
+
+
+QString PoAuxiliary::name() const
+{
+ return i18n("PO Auxiliary");
+}
+
+QString PoAuxiliary::id() const
+{
+ return "poauxiliary";
+}
+
+QString PoAuxiliary::lastError()
+{
+ return errorMsg;
+}
+
+bool PoAuxiliary::startSearch(const QString& t, uint pluralForm, const SearchFilter*filter)
+{
+ QString text(t);
+ if(autoUpdate && prefWidget && prefWidget->settingsChanged())
+ {
+ applySettings();
+ }
+
+ if(!initialized)
+ {
+ loadAuxiliary();
+ }
+
+ if(error)
+ return false;
+
+ if(isSearching())
+ return false;
+
+ stop=false;
+ active = true;
+ emit started();
+
+ clearResults();
+
+ kapp->processEvents(100);
+
+ text.replace("\n","");
+
+ Entry *entry = msgidDict[text];
+ if(entry)
+ {
+ if( !(entry->fuzzy && ignoreFuzzy) )
+ {
+ SearchResult *result = new SearchResult;
+ result->requested =QStyleSheet::convertFromPlainText(text);
+ result->found = QStyleSheet::convertFromPlainText(text);
+ result->translation =
+ QStyleSheet::convertFromPlainText(entry->translation);
+
+ result->plainRequested = text;
+ result->plainFound=text;
+ result->plainTranslation=entry->translation;
+ result->score=100;
+
+ if(entry->fuzzy)
+ {
+ result->translation="<qt><font color=\"red\">"+i18n("fuzzy")
+ +"</font><hr/>" + result->translation+"</qt>";
+ }
+
+ TranslationInfo *info = new TranslationInfo;
+ info->location = auxPackage;
+ info->translator = auxTranslator;
+ info->description = entry->comment;
+ info->filePath = auxURL;
+ result->descriptions.append(info);
+
+ results.append(result);
+
+ emit numberOfResultsChanged(1);
+ emit resultFound(result);
+ }
+ }
+
+
+ active = false;
+ stop = false;
+ emit finished();
+
+ return true;
+}
+
+
+bool PoAuxiliary::startSearchInTranslation(const QString& text)
+{
+ if(autoUpdate && prefWidget && prefWidget->settingsChanged())
+ {
+ applySettings();
+ }
+
+ if(!initialized)
+ {
+ loadAuxiliary();
+ }
+
+ if(error)
+ return false;
+
+ if(isSearching())
+ return false;
+
+ stop=false;
+ active = true;
+ emit started();
+
+ clearResults();
+
+ kapp->processEvents(100);
+
+ Entry *entry = msgstrDict[text];
+ if(entry)
+ {
+ if( !(entry->fuzzy && ignoreFuzzy) )
+ {
+ SearchResult *result = new SearchResult;
+ result->requested =QStyleSheet::convertFromPlainText(entry->orig);
+ result->found = QStyleSheet::convertFromPlainText(entry->orig);
+ result->translation =
+ QStyleSheet::convertFromPlainText(text);
+
+ result->plainRequested = entry->orig;
+ result->plainFound=entry->orig;
+ result->plainTranslation=text;
+ result->score=100;
+
+ if(entry->fuzzy)
+ {
+ result->translation="<qt><font color=\"red\">"+i18n("fuzzy")
+ +"</font><hr/>" + result->translation+"</qt>";
+ }
+
+ TranslationInfo *info = new TranslationInfo;
+ info->location = auxPackage;
+ info->translator = auxTranslator;
+ info->description = entry->comment;
+ info->filePath = auxURL;
+ result->descriptions.append(info);
+
+ results.append(result);
+
+ emit numberOfResultsChanged(1);
+ emit resultFound(result);
+ }
+ }
+
+
+ active = false;
+ stop = false;
+ emit finished();
+
+ return true;
+}
+
+void PoAuxiliary::stopSearch()
+{
+ stop=true;
+}
+
+
+void PoAuxiliary::applySettings()
+{
+ if(!prefWidget)
+ return;
+
+ bool needLoading=false;
+
+ if(isSearching())
+ stopSearch();
+
+ QString newPath = prefWidget->url();
+ if(!initialized)
+ {
+ url = newPath;
+ }
+ else if(newPath != url)
+ {
+ url = newPath;
+ needLoading=true;
+ }
+
+ ignoreFuzzy = prefWidget->ignoreFuzzy();
+
+ if(needLoading && !loadTimer->isActive())
+ {
+ loadTimer->start(100,true);
+ }
+}
+
+void PoAuxiliary::restoreSettings()
+{
+ if(!prefWidget)
+ return;
+
+ prefWidget->setURL(url);
+ prefWidget->setIgnoreFuzzy(ignoreFuzzy);
+}
+
+void PoAuxiliary::loadAuxiliary()
+{
+ if(loadTimer->isActive())
+ loadTimer->stop();
+
+ if(loading)
+ return;
+
+ loading=true;
+ error=false;
+
+ QString path=url;
+
+ if(path.contains("@LANG@"))
+ {
+ path.replace("@LANG@",langCode);
+ }
+ if(path.contains("@PACKAGE@"))
+ {
+ int pos=package.findRev("/");
+ if( pos<0 ) pos=0;
+ path.replace("@PACKAGE@",package.mid(pos));
+ }
+ if(path.contains("@PACKAGEDIR@"))
+ {
+ QString packagedir;
+ int pos=package.findRev("/");
+ if( pos > 0 ) packagedir=package.left(pos);
+ else packagedir="";
+ path.replace("@PACKAGEDIR@",packagedir);
+ kdDebug(KBABEL_SEARCH) << "Packagedir found " << packagedir << endl;
+ }
+ QRegExp reg("@DIR[0-9]+@");
+ if(path.contains(reg))
+ {
+ int pos=reg.search(path);
+ int len = reg.matchedLength();
+
+ while(pos>=0)
+ {
+ QString num=path.mid(pos+4,len-5);
+
+ bool ok;
+ int number=num.toInt(&ok);
+ if(ok)
+ {
+ QString dir=directory(editedFile,number);
+ QString s("@DIR%1@");
+ path.replace(s.arg(number),dir);
+
+ pos+=dir.length();
+ }
+
+ pos=reg.search(path);
+ len = reg.matchedLength();
+ }
+ }
+
+ KURL u;
+ QRegExp rel("^[a-zA-Z]+:");
+ if(rel.search(path) >= 0)
+ {
+ u=path;
+ }
+ else if(path[0] != '/') // relative path
+ {
+ KURL temp(editedFile);
+ QString dir = temp.directory();
+ kdDebug(KBABEL_SEARCH) << dir << endl;
+ u.setPath(dir+"/"+path);
+ u.cleanPath();
+ kdDebug(KBABEL_SEARCH) << u.prettyURL() << endl;
+ }
+ else
+ {
+ u.setPath(path);
+ }
+
+ emit progressStarts(i18n("Loading PO auxiliary"));
+ connect(catalog, SIGNAL(signalProgress(int))
+ , this, SIGNAL(progress(int)));
+
+ ConversionStatus stat = catalog->openURL(u);
+ if( stat != OK && stat != RECOVERED_PARSE_ERROR)
+ {
+ kdDebug(KBABEL_SEARCH) << "error while opening file " << u.prettyURL() << endl;
+
+ if( !error )
+ {
+ error = true;
+ errorMsg = i18n("Error while trying to open file for PO Auxiliary module:\n%1")
+ .arg(u.prettyURL());
+ emit hasError(errorMsg);
+ }
+ }
+ else
+ {
+ error = false;
+ // build index for fast search
+ msgidDict.clear();
+ msgstrDict.clear();
+
+ emit progressStarts(i18n("Building index"));
+
+ int total = catalog->numberOfEntries();
+ for(int i=0; i < total; i++)
+ {
+ if( (100*(i+1))%total < 100 )
+ {
+ emit progress((100*(i+1))/total);
+ kapp->processEvents(100);
+ }
+
+ Entry *e = new Entry;
+ // FIXME: should care about plural forms
+ e->orig = catalog->msgid(i).first();
+ e->orig.replace("\n","");
+ kdWarning() << "PoAuxialiary does not support plural forms" << endl;
+ e->translation = catalog->msgstr(i).first();
+ e->comment = catalog->comment(i);
+ e->fuzzy = catalog->isFuzzy(i);
+
+ msgidDict.insert(catalog->msgid(i,true).first(),e);
+ msgstrDict.insert(e->translation,e);
+ }
+
+ auxPackage = catalog->packageName();
+ auxURL = catalog->currentURL().url();
+ auxTranslator = catalog->lastTranslator();
+ }
+
+ disconnect(catalog, SIGNAL(signalProgress(int))
+ , this, SIGNAL(progress(int)));
+
+ emit progressEnds();
+
+ initialized=true;
+
+ loading=false;
+
+ catalog->clear();
+}
+
+
+void PoAuxiliary::setEditedFile(const QString& file)
+{
+ if(initialized && (url.contains("@DIR") || KURL::isRelativeURL(url))
+ && file!=editedFile && !loadTimer->isActive() )
+ {
+ initialized=false;
+ }
+
+ editedFile=file;
+}
+
+
+void PoAuxiliary::setEditedPackage(const QString& pack)
+{
+ if(initialized && url.contains("@PACKAGE@") && pack!=package
+ && !loadTimer->isActive() )
+ {
+ initialized=false;
+ }
+
+ package=pack;
+}
+
+
+void PoAuxiliary::setLanguageCode(const QString& lang)
+{
+ if(initialized && url.contains("@LANG@") && lang!=langCode
+ && !loadTimer->isActive() )
+ {
+ initialized=false;
+ }
+
+ langCode=lang;
+}
+
+bool PoAuxiliary::usesRichTextResults()
+{
+ return true;
+}
+
+QString PoAuxiliary::translate(const QString& text, uint pluralForm)
+{
+ if(!initialized)
+ {
+ loadAuxiliary();
+ }
+
+ if(error)
+ {
+ return QString::null;
+ }
+
+ Entry *entry = msgidDict[text];
+ if(entry)
+ {
+ return entry->translation;
+ }
+
+ return QString::null;
+}
+
+
+#include "poauxiliary.moc"
diff --git a/kbabel/kbabeldict/modules/poauxiliary/poauxiliary.desktop b/kbabel/kbabeldict/modules/poauxiliary/poauxiliary.desktop
new file mode 100644
index 00000000..5629930e
--- /dev/null
+++ b/kbabel/kbabeldict/modules/poauxiliary/poauxiliary.desktop
@@ -0,0 +1,51 @@
+[Desktop Entry]
+Type=Service
+Name=Auxiliary PO Module for KBabelDict
+Name[bg]=Помощен PO модул за KBabelDict
+Name[bs]=Pomoćni PO modul za KBabelDict
+Name[ca]=Mòdul PO auxiliar per a KBabelDict
+Name[cs]=Doplňkový PO modul pro KBabelDict
+Name[cy]=Modiwl PO Ategol i KBabelDict
+Name[da]=Auxiliary PO-module for KBabelDict
+Name[de]=PO-Hilfsdatei-Modul für KBabelDict
+Name[el]=ΆÏθÏωμα Î²Î¿Î·Î¸Î·Ï„Î¹ÎºÎ¿Ï PO για το KBabelDict
+Name[es]=Módulo PO auxiliar para KBabelDict
+Name[et]=KBabelDicti PO liitlasfaili moodul
+Name[eu]=PO modulu laguntzailea KBabelDict-entzat
+Name[fa]=پیمانۀ کمکی PO برای KBabelDict
+Name[fi]=KBabelDict-ohjelman PO-apumoduuli
+Name[fr]=Module de PO auxiliaire pour KBabelDict
+Name[gl]=Módulo de PO auxiliar para KBabelDict
+Name[hi]=के-बेबल-डिकà¥à¤¶ के लिठऑकà¥à¤œà¤¿à¤²à¤°à¥€ पीओ मॉडà¥à¤¯à¥‚ल
+Name[hu]=Kiegészítő PO modul a KBabelDicthez
+Name[is]=Viðbótar PO eining fyrir KBabel orðabókina
+Name[it]=Modulo ausiliario PO per KBabelDict
+Name[ja]=KBabelDict 補助 PO モジュール
+Name[ka]=დáƒáƒ›áƒ®áƒ›áƒáƒ áƒ” PO მáƒáƒ“ული KBabelDict-სთვის
+Name[kk]=KBabelDict-Ñ‚Ñ‹Ò£ қоÑымша PO модулі
+Name[lt]=KBabelDict papildomo PO žodyno modulis
+Name[ms]=Modul Auksillari PO untuk KBabelDict
+Name[nb]=Hjelpeordlistemodul for KBabelDict
+Name[nds]=PO-Hülpdateimoduul för KBabelDict
+Name[ne]=KBabelDict का लागि सहायक पीओ मोडà¥à¤¯à¥à¤²
+Name[nl]=Alternatieve PO-module voor KBabelDict
+Name[nn]=Jamføringsmodul for KBabelDict
+Name[pa]=ਕੇਬਬੇਲ-ਸ਼ਬਦਕੋਸ਼ ਲਈ ਸਹਾਇਕ PO ਸਹਾਇਕ
+Name[pl]=Moduł pomocniczego pliku PO dla KBabelDict
+Name[pt]=Módulo de PO Auxiliar para o KBabelDict
+Name[pt_BR]=Módulo Auxiliar PO para o KBabelDict
+Name[ru]=Ð’Ñпомогательный модуль PO Ð´Ð»Ñ KBabelDict
+Name[sk]=Iný PO súbore pre KBabelDict
+Name[sl]=Dodatni modul PO za KBabelDict
+Name[sr]=Помоћни PO модул за KBabelDict
+Name[sr@Latn]=Pomoćni PO modul za KBabelDict
+Name[sv]=Hjälp-PO modul för Kbabeldict
+Name[ta]=Kபாபேலà¯à®•à¯à®•à®¾à®© இரணà¯à®Ÿà®¾à®®à¯ PO கூறà¯
+Name[tg]=Модули ёрираÑони PO барои KBabelDict
+Name[tr]=KBabelDict için Yardımcı PO Modülü
+Name[uk]=Модуль допоміжного Ñловника PO Ð´Ð»Ñ KBabelDict
+Name[zh_CN]=KBabelDict çš„ PO 辅助è¯å…¸æ¨¡å—
+Name[zh_TW]=KBabelDict 輔助 PO 模組
+X-KDE-Library=kbabeldict_poauxiliary
+ServiceTypes=KBabelDictModule
+Applications=kbabel
diff --git a/kbabel/kbabeldict/modules/poauxiliary/poauxiliary.h b/kbabel/kbabeldict/modules/poauxiliary/poauxiliary.h
new file mode 100644
index 00000000..27fecba6
--- /dev/null
+++ b/kbabel/kbabeldict/modules/poauxiliary/poauxiliary.h
@@ -0,0 +1,136 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#ifndef POAUXILIARY_H
+#define POAUXILIARY_H
+
+#include "searchengine.h"
+
+#include <qguardedptr.h>
+#include <qdict.h>
+class QTimer;
+
+namespace KBabel
+{
+ class Catalog;
+}
+
+class AuxiliaryPreferencesWidget;
+
+class PoAuxiliary : public SearchEngine
+{
+ Q_OBJECT
+
+public:
+ PoAuxiliary(QObject *parent=0, const char *name=0);
+ virtual ~PoAuxiliary();
+
+ virtual bool isReady() const;
+
+ virtual QString translate(const QString& text, uint pluralForm);
+
+ virtual bool isSearching() const;
+
+ virtual void saveSettings(KConfigBase *config);
+ virtual void readSettings(KConfigBase *config);
+
+ virtual PrefWidget *preferencesWidget(QWidget *parent);
+
+ virtual const KAboutData *about() const;
+
+ virtual QString name() const;
+
+ virtual QString id() const;
+
+ virtual QString lastError();
+
+ virtual bool usesRichTextResults();
+
+public slots:
+ virtual bool startSearch(const QString& text, unsigned int pluralForm
+ , const SearchFilter*filter);
+ virtual bool startSearchInTranslation(const QString& text);
+
+ virtual void stopSearch();
+
+ virtual void setEditedFile(const QString&);
+ virtual void setEditedPackage(const QString&);
+ virtual void setLanguageCode(const QString&);
+
+
+protected slots:
+ /** reads the current settings from the preferences dialog */
+ void applySettings();
+
+ /** sets the current settings in the preferences dialog */
+ void restoreSettings();
+
+ void loadAuxiliary();
+
+private:
+ QGuardedPtr<AuxiliaryPreferencesWidget> prefWidget;
+ KBabel::Catalog *catalog;
+ QString auxPackage;
+ QString auxTranslator;
+ QString auxURL;
+
+ QString url;
+ bool ignoreFuzzy;
+
+ QString editedFile;
+ QString package;
+ QString langCode;
+
+ bool error;
+ QString errorMsg;
+
+ bool stop;
+ bool active;
+ bool loading;
+ bool initialized;
+
+ QTimer *loadTimer;
+
+ struct Entry
+ {
+ QString orig;
+ QString translation;
+ QString comment;
+ bool fuzzy;
+ };
+
+ QDict<Entry> msgidDict;
+ QDict<Entry> msgstrDict;
+};
+
+#endif
diff --git a/kbabel/kbabeldict/modules/poauxiliary/preferenceswidget.cpp b/kbabel/kbabeldict/modules/poauxiliary/preferenceswidget.cpp
new file mode 100644
index 00000000..e8d48032
--- /dev/null
+++ b/kbabel/kbabeldict/modules/poauxiliary/preferenceswidget.cpp
@@ -0,0 +1,115 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+
+#include <kfiledialog.h>
+#include <qpushbutton.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <kurlrequester.h>
+
+#include "preferenceswidget.h"
+#include "pwidget.h"
+
+AuxiliaryPreferencesWidget::AuxiliaryPreferencesWidget(QWidget *parent, const char* name)
+ : PrefWidget(parent,name)
+ , changed(false)
+{
+ QVBoxLayout *layout = new QVBoxLayout(this);
+
+ prefWidget = new PWidget(this);
+ layout->addWidget(prefWidget);
+
+
+ connect(prefWidget->urlInput->lineEdit(),SIGNAL(textChanged(const QString&))
+ , this, SLOT(setChanged()));
+}
+
+AuxiliaryPreferencesWidget::~AuxiliaryPreferencesWidget()
+{
+}
+
+
+void AuxiliaryPreferencesWidget::apply()
+{
+ emit applySettings();
+}
+
+void AuxiliaryPreferencesWidget::cancel()
+{
+ emit restoreSettings();
+}
+
+void AuxiliaryPreferencesWidget::standard()
+{
+ prefWidget->urlInput->setURL("@PACKAGE@.po");
+ changed=true;
+}
+
+void AuxiliaryPreferencesWidget::setURL(const QString url)
+{
+ prefWidget->urlInput->setURL(url);
+ changed=false;
+}
+
+QString AuxiliaryPreferencesWidget::url()
+{
+ changed = false;
+ return prefWidget->urlInput->url();
+}
+
+bool AuxiliaryPreferencesWidget::ignoreFuzzy()
+{
+ changed=false;
+ return prefWidget->fuzzyBtn->isChecked();
+}
+
+void AuxiliaryPreferencesWidget::setIgnoreFuzzy(bool flag)
+{
+ prefWidget->fuzzyBtn->setChecked(flag);
+}
+
+bool AuxiliaryPreferencesWidget::settingsChanged() const
+{
+ return changed;
+}
+
+void AuxiliaryPreferencesWidget::setChanged()
+{
+ changed=true;
+}
+
+
+#include "preferenceswidget.moc"
diff --git a/kbabel/kbabeldict/modules/poauxiliary/preferenceswidget.h b/kbabel/kbabeldict/modules/poauxiliary/preferenceswidget.h
new file mode 100644
index 00000000..45488158
--- /dev/null
+++ b/kbabel/kbabeldict/modules/poauxiliary/preferenceswidget.h
@@ -0,0 +1,77 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#ifndef PREFERENCESWIDGET_H
+#define PREFERENCESWIDGET_H
+
+#include "searchengine.h"
+
+class PWidget;
+
+class AuxiliaryPreferencesWidget : public PrefWidget
+{
+ Q_OBJECT
+
+public:
+ AuxiliaryPreferencesWidget(QWidget *parent=0, const char* name=0);
+ virtual ~AuxiliaryPreferencesWidget();
+
+ virtual void apply();
+ virtual void cancel();
+ virtual void standard();
+
+ void setURL(const QString url);
+ QString url();
+
+ void setIgnoreFuzzy(bool);
+ bool ignoreFuzzy();
+
+ bool settingsChanged() const;
+
+signals:
+ void restoreSettings();
+ void applySettings();
+
+public:
+ PWidget *prefWidget;
+
+protected slots:
+ void setChanged();
+
+private:
+ bool changed;
+
+};
+
+#endif
diff --git a/kbabel/kbabeldict/modules/poauxiliary/pwidget.ui b/kbabel/kbabeldict/modules/poauxiliary/pwidget.ui
new file mode 100644
index 00000000..8179caed
--- /dev/null
+++ b/kbabel/kbabeldict/modules/poauxiliary/pwidget.ui
@@ -0,0 +1,133 @@
+<!DOCTYPE UI><UI>
+<class>PWidget</class>
+<widget>
+ <class>QWidget</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>PWidget</cstring>
+ </property>
+ <property stdset="1">
+ <name>geometry</name>
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>335</width>
+ <height>306</height>
+ </rect>
+ </property>
+ <property stdset="1">
+ <name>caption</name>
+ <string></string>
+ </property>
+ <vbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>11</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>6</number>
+ </property>
+ <widget>
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>&amp;Path to auxiliary file:</string>
+ </property>
+ <property>
+ <name>buddy</name>
+ <cstring>urlInput</cstring>
+ </property>
+ </widget>
+ <widget>
+ <class>KURLRequester</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>urlInput</cstring>
+ </property>
+ </widget>
+ <widget>
+ <class>QCheckBox</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>fuzzyBtn</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>&amp;Ignore fuzzy entries</string>
+ </property>
+ </widget>
+ <widget>
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>TextLabel1_2</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>&lt;qt&gt;&lt;p&gt;
+The following variables will be replaced in the path if available:
+&lt;ul&gt;
+&lt;li&gt;&lt;b&gt;@PACKAGE@&lt;/b&gt;: the name of the currently translated application or package&lt;/li&gt;
+&lt;li&gt;&lt;b&gt;@LANG@&lt;/b&gt;: the language code&lt;/li&gt;
+&lt;li&gt;&lt;b&gt;@DIR&lt;em&gt;n&lt;/em&gt;@&lt;/b&gt;: where n is a positive integer. This expands to the nth folder counted from the filename&lt;/li&gt;
+&lt;/ul&gt;&lt;/p&gt;&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <spacer>
+ <property>
+ <name>name</name>
+ <cstring>Spacer1</cstring>
+ </property>
+ <property stdset="1">
+ <name>orientation</name>
+ <enum>Vertical</enum>
+ </property>
+ <property stdset="1">
+ <name>sizeType</name>
+ <enum>Expanding</enum>
+ </property>
+ <property>
+ <name>sizeHint</name>
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property>
+ <name>sizeHint</name>
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>KURLRequester</class>
+ <header location="global">kurlrequester.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image>
+ <name>image0</name>
+ <data format="XPM.GZ" length="646">789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758</data>
+ </image>
+</images>
+</UI>
diff --git a/kbabel/kbabeldict/modules/pocompendium/Makefile.am b/kbabel/kbabeldict/modules/pocompendium/Makefile.am
new file mode 100644
index 00000000..b4fe4974
--- /dev/null
+++ b/kbabel/kbabeldict/modules/pocompendium/Makefile.am
@@ -0,0 +1,39 @@
+## Makefile.am for pocompendium
+
+# this has all of the subdirectories that make will recurse into. if
+# there are none, comment this out
+#SUBDIRS =
+
+
+# this is the program that gets installed. it's name is used for all
+# of the other Makefile.am variables
+kde_module_LTLIBRARIES = kbabeldict_pocompendium.la
+
+# set the include path for X, qt and KDE
+INCLUDES = -I$(srcdir)/../.. -I../../../common -I$(srcdir)/../../../common $(all_includes)
+
+
+# which sources should be compiled for kbabel
+kbabeldict_pocompendium_la_SOURCES = pocompendium.cpp preferenceswidget.cpp \
+ pc_factory.cpp pwidget.ui compendiumdata.cpp
+
+kbabeldict_pocompendium_la_LIBADD = ../../libkbabeldictplugin.la ../../../common/libkbabelcommon.la $(LIB_KDEUI) $(LIB_KIO)
+kbabeldict_pocompendium_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined
+
+
+
+# these are the headers for your project
+noinst_HEADERS = pocompendium.h preferenceswidget.h pc_factory.h \
+ compendiumdata.h
+
+
+# let automoc handle all of the meta source files (moc)
+METASOURCES = AUTO
+
+
+# this is where the kdelnk file will go
+#datadir = $(kde_datadir)/kbabeldict/modules
+#data_DATA = pocompendium.rc
+
+kde_services_DATA = pocompendium.desktop
+EXTRA_DIST = $(kde_services_DATA)
diff --git a/kbabel/kbabeldict/modules/pocompendium/compendiumdata.cpp b/kbabel/kbabeldict/modules/pocompendium/compendiumdata.cpp
new file mode 100644
index 00000000..d862b236
--- /dev/null
+++ b/kbabel/kbabeldict/modules/pocompendium/compendiumdata.cpp
@@ -0,0 +1,261 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2001 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include "compendiumdata.h"
+
+#include <resources.h>
+#include <catalog.h>
+#include <tagextractor.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+using namespace KBabel;
+
+CompendiumData::CompendiumData(QObject *parent)
+ : QObject(parent)
+ , _active(false)
+ , _error(false)
+ , _initialized(false)
+ , _catalog(0)
+ , _exactDict(9887)
+ , _allDict(9887)
+ , _wordDict(9887)
+ , _textonlyDict(9887)
+{
+ _catalog = new Catalog(this, "CompendiumData::catalog", QString::null);
+ _exactDict.setAutoDelete(true);
+ _allDict.setAutoDelete(true);
+ _wordDict.setAutoDelete(true);
+ _textonlyDict.setAutoDelete(true);
+}
+
+
+bool CompendiumData::load(KURL url)
+{
+ if(_active)
+ return false;
+
+
+ _error = false;
+ _active = true;
+
+ _exactDict.clear();
+ _allDict.clear();
+ _wordDict.clear();
+ _textonlyDict.clear();
+
+
+ emit progressStarts(i18n("Loading PO compendium"));
+ connect(_catalog, SIGNAL(signalProgress(int)), this, SIGNAL(progress(int)));
+
+ ConversionStatus stat=_catalog->openURL(url);
+
+ disconnect(_catalog, SIGNAL(signalProgress(int))
+ , this, SIGNAL(progress(int)));
+
+
+ if( stat!= OK && stat != RECOVERED_PARSE_ERROR)
+ {
+ kdDebug(KBABEL_SEARCH) << "error while opening file " << url.prettyURL() << endl;
+
+ _error = true;
+ _errorMsg = i18n("Error while trying to read file for PO Compendium module:\n%1")
+ .arg(url.prettyURL());
+
+ emit progressEnds();
+
+ _active = false;
+ _initialized=true;
+
+ return false;
+ }
+
+ emit progressStarts(i18n("Building indices"));
+
+ int total = _catalog->numberOfEntries();
+ for(int i=0; i < total; i++)
+ {
+ if( (100*(i+1))%total < 100 )
+ {
+ emit progress((100*(i+1))/total);
+ kapp->processEvents(100);
+ }
+
+ // FIXME: shoudl care about plural forms
+ QString temp = _catalog->msgid(i,true).first();
+
+ int *index = new int(i);
+ _exactDict.insert(temp,index);
+
+
+ temp = simplify(temp);
+ temp = temp.lower();
+
+ if(!temp.isEmpty() && temp.length() > 1)
+ {
+ // add to allDict
+ QValueList<int> *indexList=_allDict[temp];
+
+ if(!indexList)
+ {
+ indexList = new QValueList<int>;
+ _allDict.insert(temp,indexList);
+ }
+
+ indexList->append(i);
+
+ // add to textonlyDict
+ QString temp1 = temp;
+ temp1.remove( ' ' );
+
+ indexList=_textonlyDict[temp1];
+
+ if(!indexList)
+ {
+ indexList = new QValueList<int>;
+ _textonlyDict.insert(temp1,indexList);
+ kdDebug() << "Adding " << temp1 << endl;
+ }
+
+ indexList->append(i);
+
+ // add to wordDict
+ QStringList wList = wordList(temp);
+ for ( QStringList::Iterator it = wList.begin()
+ ; it != wList.end(); ++it )
+ {
+ if( (*it).length() > 1)
+ {
+ indexList=_wordDict[*it];
+
+ if(!indexList)
+ {
+ indexList = new QValueList<int>;
+ _wordDict.insert(*it,indexList);
+ }
+
+ indexList->append(i);
+ }
+ }
+ }
+ }
+
+ // remove words, that are too frequent
+ uint max=_allDict.count()/10;
+ QDictIterator< QValueList<int> > it(_wordDict);
+ while ( it.current() )
+ {
+ if(it.current()->count() > max)
+ {
+ _wordDict.remove(it.currentKey());
+ }
+ else
+ {
+ ++it;
+ }
+ }
+
+
+ _initialized=true;
+
+ emit progressEnds();
+
+
+
+ _active = false;
+
+ return true;
+}
+
+const int* CompendiumData::exactDict(const QString text) const
+{
+ return _exactDict[text];
+}
+
+const QValueList<int>* CompendiumData::allDict(const QString text) const
+{
+ return _allDict[text];
+}
+
+const QValueList<int>* CompendiumData::wordDict(const QString text) const
+{
+ return _wordDict[text];
+}
+
+const QValueList<int>* CompendiumData::textonlyDict(const QString text) const
+{
+ return _textonlyDict[text];
+}
+
+
+void CompendiumData::registerObject(QObject *obj)
+{
+ if(!_registered.containsRef(obj))
+ _registered.append(obj);
+}
+
+bool CompendiumData::unregisterObject(QObject *obj)
+{
+ _registered.removeRef(obj);
+
+ return _registered.count()==0;
+}
+
+bool CompendiumData::hasObjects() const
+{
+ return _registered.count()==0;
+}
+
+QString CompendiumData::simplify(const QString string)
+{
+ QString result;
+
+ TagExtractor te;
+ te.setString(string);
+ result=te.plainString();
+
+ result=result.simplifyWhiteSpace();
+ result=result.stripWhiteSpace();
+
+ return result;
+}
+
+QStringList CompendiumData::wordList(const QString string)
+{
+ QString result=CompendiumData::simplify(string);
+
+ return QStringList::split(' ',result);
+}
+
+#include "compendiumdata.moc"
diff --git a/kbabel/kbabeldict/modules/pocompendium/compendiumdata.h b/kbabel/kbabeldict/modules/pocompendium/compendiumdata.h
new file mode 100644
index 00000000..2fec45cb
--- /dev/null
+++ b/kbabel/kbabeldict/modules/pocompendium/compendiumdata.h
@@ -0,0 +1,105 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2001 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef COMPENDIUMDATA_H
+#define COMPENDIUMDATA_H
+
+
+#include <kurl.h>
+#include <qdict.h>
+#include <qobject.h>
+#include <qstringlist.h>
+#include <qvaluelist.h>
+#include <qptrlist.h>
+
+namespace KBabel
+{
+class Catalog;
+}
+
+class CompendiumData : public QObject
+{
+ Q_OBJECT
+
+public:
+ CompendiumData(QObject *parent=0);
+
+ bool load(KURL url);
+
+ const KBabel::Catalog *catalog() const { return _catalog; }
+ const int *exactDict(const QString text) const;
+ const QValueList<int> *allDict(const QString text) const;
+ const QValueList<int> *wordDict(const QString text) const;
+ const QValueList<int> *textonlyDict(const QString text) const;
+
+ bool active() const { return _active; }
+ bool initialized() const { return _initialized; }
+ bool hasErrors() const { return _error; }
+ QString errorMsg() const { return _errorMsg; }
+
+ /** registers an object, that uses this data */
+ void registerObject(QObject *);
+ /**
+ * unregisters an object, that uses this data
+ *
+ * @return true, if this was the last object
+ */
+ bool unregisterObject(QObject *);
+
+ bool hasObjects() const;
+
+
+ static QString simplify(const QString text);
+ static QStringList wordList(const QString text);
+
+signals:
+ void progressStarts(const QString);
+ void progressEnds();
+ void progress(int);
+
+
+private:
+ bool _active;
+ bool _error;
+ bool _initialized;
+ QString _errorMsg;
+
+ KBabel::Catalog *_catalog;
+ QDict<int> _exactDict;
+ QDict< QValueList<int> > _allDict;
+ QDict< QValueList<int> > _wordDict;
+ QDict< QValueList<int> > _textonlyDict;
+
+ QPtrList<QObject> _registered;
+};
+
+#endif
diff --git a/kbabel/kbabeldict/modules/pocompendium/pc_factory.cpp b/kbabel/kbabeldict/modules/pocompendium/pc_factory.cpp
new file mode 100644
index 00000000..882cc064
--- /dev/null
+++ b/kbabel/kbabeldict/modules/pocompendium/pc_factory.cpp
@@ -0,0 +1,110 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#include <klocale.h>
+#include <kinstance.h>
+#include <kaboutdata.h>
+#include <kdebug.h>
+
+#include "pc_factory.h"
+#include "pocompendium.h"
+
+
+extern "C"
+{
+ KDE_EXPORT void *init_kbabeldict_pocompendium()
+ {
+ return new PcFactory;
+ }
+}
+
+
+KInstance *PcFactory::s_instance = 0;
+KAboutData *PcFactory::s_about = 0;
+
+
+PcFactory::PcFactory( QObject *parent, const char *name)
+ : KLibFactory(parent,name)
+{
+}
+
+PcFactory::~PcFactory()
+{
+ if(s_instance)
+ {
+ delete s_instance;
+ s_instance=0;
+ }
+
+ if(s_about)
+ {
+ delete s_about;
+ s_about=0;
+ }
+}
+
+
+QObject *PcFactory::createObject( QObject *parent, const char *name
+ , const char *classname, const QStringList &)
+{
+ if(QCString(classname) != "SearchEngine")
+ {
+ kdError() << "not a SearchEngine requested" << endl;
+ return 0;
+ }
+
+ return new PoCompendium(parent,name);
+}
+
+
+KInstance *PcFactory::instance()
+{
+ if(!s_instance)
+ {
+ s_about = new KAboutData( "pocompendium", I18N_NOOP("PO Compendium")
+ , "1.0"
+ , I18N_NOOP("A module for searching in a PO file")
+ , KAboutData::License_GPL
+ , "Copyright 2000-2001, Matthias Kiefer"
+ ,0,0, "kiefer@kde.org");
+
+ s_about->addAuthor("Matthias Kiefer",0,"kiefer@kde.org");
+
+ s_instance = new KInstance(s_about);
+ }
+
+ return s_instance;
+}
+
+#include "pc_factory.moc"
diff --git a/kbabel/kbabeldict/modules/pocompendium/pc_factory.h b/kbabel/kbabeldict/modules/pocompendium/pc_factory.h
new file mode 100644
index 00000000..d52fadfe
--- /dev/null
+++ b/kbabel/kbabeldict/modules/pocompendium/pc_factory.h
@@ -0,0 +1,60 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#ifndef PC_FACTORY_H
+#define PC_FACTORY_H
+
+#include <klibloader.h>
+class KInstance;
+class KAboutData;
+
+class PcFactory : public KLibFactory
+{
+ Q_OBJECT
+public:
+ PcFactory( QObject *parent=0, const char *name=0);
+ ~PcFactory();
+
+ virtual QObject *createObject( QObject *parent=0, const char *name=0
+ , const char *classname="QObject"
+ , const QStringList &args = QStringList());
+
+ static KInstance *instance();
+
+private:
+ static KInstance *s_instance;
+ static KAboutData *s_about;
+};
+
+#endif
diff --git a/kbabel/kbabeldict/modules/pocompendium/pocompendium.cpp b/kbabel/kbabeldict/modules/pocompendium/pocompendium.cpp
new file mode 100644
index 00000000..0cd79fb3
--- /dev/null
+++ b/kbabel/kbabeldict/modules/pocompendium/pocompendium.cpp
@@ -0,0 +1,1246 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2003 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include <klocale.h>
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <kstaticdeleter.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kinstance.h>
+#include <kio/netaccess.h>
+
+#include <qregexp.h>
+#include <qtextstream.h>
+#include <qtimer.h>
+
+#include "resources.h"
+#include "compendiumdata.h"
+#include "pocompendium.h"
+#include "preferenceswidget.h"
+#include "pc_factory.h"
+
+#include <catalog.h>
+#include <catalogitem.h>
+
+// ngram length and minimal matching for fuzzy search
+#define NGRAM_LEN 3
+#define LIM_NGRAM 50
+
+using namespace KBabel;
+
+static KStaticDeleter< QDict<CompendiumData> > compDataDeleter;
+QDict<CompendiumData> *PoCompendium::_compDict = 0;
+
+PoCompendium::PoCompendium(QObject *parent, const char *name)
+ : SearchEngine(parent, name)
+{
+ prefWidget=0;
+ data=0;
+ error=false;
+ stop=false;
+ active=false;
+ initialized=false;
+ loading=false;
+
+ langCode = KGlobal::locale()->language();
+
+ caseSensitive = false;
+ ignoreFuzzy=true;
+ wholeWords=true;
+
+ matchEqual = true;
+ matchNGram = true;
+ matchIsContained = false;
+ matchContains = true;
+ matchWords=true;
+
+
+ loadTimer = new QTimer(this);
+ connect(loadTimer,SIGNAL(timeout()),this,SLOT(slotLoadCompendium()));
+}
+
+PoCompendium::~PoCompendium()
+{
+ if(isSearching())
+ {
+ stopSearch();
+ }
+
+ unregisterData();
+}
+
+bool PoCompendium::isReady() const
+{
+ return (isSearching() || !error);
+}
+
+
+bool PoCompendium::isSearching() const
+{
+ return (active || loading);
+}
+
+
+void PoCompendium::saveSettings(KConfigBase *config )
+{
+ if(autoUpdate && prefWidget && prefWidget->settingsChanged())
+ {
+ applySettings();
+ }
+
+ config->writeEntry("CaseSensitive",caseSensitive);
+ config->writeEntry("IgnoreFuzzy", ignoreFuzzy);
+ config->writeEntry("WholeWords", wholeWords);
+
+ config->writeEntry("MatchEqual", matchEqual);
+ config->writeEntry("MatchIsContained",matchIsContained);
+ config->writeEntry("MatchContains", matchContains);
+ config->writeEntry("MatchWords", matchWords);
+ config->writeEntry("MatchNGram", matchNGram);
+
+ config->writeEntry("Compendium", url);
+}
+
+void PoCompendium::readSettings(KConfigBase *config)
+{
+ caseSensitive = config->readBoolEntry("CaseSensitive", false);
+ ignoreFuzzy = config->readBoolEntry("IgnoreFuzzy",true);
+ wholeWords = config->readBoolEntry("WholeWords",true);
+
+ matchEqual = config->readBoolEntry("MatchEqual", true);
+ matchIsContained = config->readBoolEntry("MatchIsContained", false);
+ matchContains = config->readBoolEntry("MatchContains",true);
+ matchWords = config->readBoolEntry("MatchWords",true);
+ matchNGram = config->readBoolEntry("MatchNGram",true);
+
+ QString newPath = config->readEntry("Compendium","http://i18n.kde.org/po_overview/@LANG@.messages");
+ if(!initialized)
+ {
+ url = newPath;
+ }
+ else if(newPath != url)
+ {
+ url = newPath;
+ loadCompendium();
+ }
+
+
+ restoreSettings();
+}
+
+PrefWidget *PoCompendium::preferencesWidget(QWidget *parent)
+{
+ prefWidget = new CompendiumPreferencesWidget(parent,"pocompendium_prefwidget");
+ kdDebug(KBABEL_SEARCH) << "PreferencesWidget is " << prefWidget << endl;
+ connect(prefWidget, SIGNAL(applySettings()), this, SLOT(applySettings()));
+ connect(prefWidget, SIGNAL(restoreSettings())
+ , this, SLOT(restoreSettings()));
+
+ restoreSettings();
+
+ return prefWidget;
+}
+
+const KAboutData *PoCompendium::about() const
+{
+ return PcFactory::instance()->aboutData();
+}
+
+
+QString PoCompendium::name() const
+{
+ return i18n("PO Compendium");
+}
+
+QString PoCompendium::id() const
+{
+ return "pocompendium";
+}
+
+QString PoCompendium::lastError()
+{
+ return errorMsg;
+}
+
+bool PoCompendium::searchExact(const QString& text, uint pluralForm, QPtrList<SearchResult>& results, QValueList<int>& foundIndices, QValueList<int>& )
+{
+ const int *index = data->exactDict(text);
+ if(index)
+ {
+ foundIndices.append(*index);
+
+ SearchResult *result = new SearchResult;
+ result->requested = text;
+ result->found = data->catalog()->msgid(*index);
+#warning kdWarning() << "PoCompendium can't return plural form translation" << endl;
+ result->translation = data->catalog()->msgstr(*index).first();
+ result->score = 100;
+
+ TranslationInfo *info = new TranslationInfo;
+ info->location = directory(realURL,0);
+ info->translator = catalogInfo.lastTranslator;
+ info->description = data->catalog()->comment(*index);
+ result->descriptions.append(info);
+
+ addResult(result, results);
+ return true;
+ }
+
+ return false;
+
+}
+
+bool PoCompendium::searchCaseInsensitive(const QString& text, uint pluralForm, QPtrList<SearchResult>& results, QValueList<int>& foundIndices, QValueList<int>& )
+{
+ QString searchStr = text.lower();
+
+ const QValueList<int> *indexList = data->allDict(text.lower());
+ if(indexList)
+ {
+ QValueList<int>::ConstIterator it;
+ for( it = indexList->begin(); it != indexList->end(); ++it )
+ {
+ if(foundIndices.contains(*it))
+ {
+ continue;
+ }
+
+ if(ignoreFuzzy && data->catalog()->isFuzzy(*it))
+ {
+ continue;
+ }
+
+
+ QString origStr = data->catalog()->msgid(*it).first();
+ origStr = CompendiumData::simplify(origStr);
+
+
+ if(!caseSensitive)
+ {
+ origStr = origStr.lower();
+ }
+
+ if(origStr==searchStr)
+ {
+ foundIndices.append(*it);
+
+ SearchResult *result = new SearchResult;
+ result->requested = text;
+ result->found = data->catalog()->msgid(*it);
+ result->translation = *(data->catalog()->msgstr(*it).at(pluralForm));
+ result->score = score(result->requested,*(result->found.at(pluralForm)));
+
+ TranslationInfo *info = new TranslationInfo;
+ info->location = directory(realURL,0);
+ info->translator = catalogInfo.lastTranslator;
+ info->description = data->catalog()->comment(*it);
+ result->descriptions.append(info);
+
+ addResult(result, results);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool PoCompendium::searchTextOnly(const QString& text, uint pluralForm, QPtrList<SearchResult>& results, QValueList<int>& foundIndices, QValueList<int>& )
+{
+ QString searchStr = text.lower();
+ QString t = text;
+ t.remove( " " );
+
+ const QValueList<int> *indexList = data->textonlyDict(t.lower());
+ if(indexList)
+ {
+ QValueList<int>::ConstIterator it;
+ for( it = indexList->begin(); it != indexList->end(); ++it )
+ {
+ if(foundIndices.contains(*it))
+ {
+ continue;
+ }
+
+ if(ignoreFuzzy && data->catalog()->isFuzzy(*it))
+ {
+ continue;
+ }
+
+
+ QString origStr = data->catalog()->msgid(*it).first();
+ origStr = CompendiumData::simplify(origStr);
+
+
+ foundIndices.append(*it);
+
+ SearchResult *result = new SearchResult;
+ result->requested = text;
+ result->found = data->catalog()->msgid(*it).first();
+#warning kdWarning() << "PoCompendium can't return plural form translation" << endl;
+ result->translation = data->catalog()->msgstr(*it).first();
+ result->score = score(result->requested,*(result->found.at(pluralForm)));
+
+ TranslationInfo *info = new TranslationInfo;
+ info->location = directory(realURL,0);
+ info->translator = catalogInfo.lastTranslator;
+ info->description = data->catalog()->comment(*it);
+ result->descriptions.append(info);
+
+ addResult(result, results);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool PoCompendium::searchWords(const QString& searchStr, uint pluralForm, QPtrList<SearchResult>& results, QValueList<int>& foundIndices, QValueList<int>& checkedIndices )
+{
+ uint checkCounter = 0;
+ bool foundResults = false;
+
+ QStringList wList = CompendiumData::wordList(searchStr);
+ for ( QStringList::Iterator wit = wList.begin()
+ ; wit != wList.end(); ++wit )
+ {
+ if(stop)
+ break;
+
+ const QValueList<int> *indexList = data->wordDict((*wit).lower());
+ if(indexList)
+ {
+ QValueList<int>::ConstIterator it;
+ for( it = indexList->begin(); it != indexList->end(); ++it )
+ {
+ if(stop)
+ break;
+
+ if(foundIndices.contains(*it))
+ {
+ continue;
+ }
+
+ if(checkedIndices.contains(*it))
+ {
+ continue;
+ }
+
+ checkedIndices.append(*it);
+ checkCounter++;
+
+ if(ignoreFuzzy && data->catalog()->isFuzzy(*it))
+ {
+ continue;
+ }
+
+ if( (100*(checkCounter+1))%catalogInfo.total < 100)
+ {
+ emit progress( (50*checkCounter+1)/catalogInfo.total);
+ }
+
+ kapp->processEvents(100);
+
+ QString origStr = data->catalog()->msgid(*it).first();
+ origStr = CompendiumData::simplify(origStr);
+
+
+ if(!caseSensitive)
+ {
+ origStr = origStr.lower();
+ }
+
+ bool found = false;
+ if(matchWords)
+ {
+ if(!caseSensitive)
+ {
+ found=true;
+ }
+ else
+ {
+ QString s=*wit;
+ QString o=origStr;
+
+ if(wholeWords)
+ {
+ s=" "+*wit+" ";
+ o=" "+origStr+" ";
+ }
+ if(o.contains(s))
+ {
+ found=true;
+ }
+ }
+ }
+
+
+ if(!found && origStr==searchStr)
+ {
+ found =true;
+ }
+
+ // if there is an string which just contains ignored characters,
+ // continue
+ if(!found && origStr.isEmpty() ||
+ (origStr.length() == 1 && searchStr.length() > 1))
+ {
+ continue;
+ }
+
+
+ if(!found && matchContains && !wholeWords)
+ {
+ QString s=maskString(searchStr);
+ QRegExp searchReg(s);
+
+ if(searchReg.search(origStr) >= 0)
+ found=true;
+ }
+
+ if(!found && matchIsContained && !wholeWords)
+ {
+ QString s=maskString(origStr);
+ QRegExp reg(s);
+
+ if(reg.search(searchStr) >= 0)
+ {
+ found = true;
+ }
+ }
+ if(!found && matchWords && !wholeWords)
+ {
+ QStringList list = CompendiumData::wordList(searchStr);
+
+ for ( QStringList::Iterator wit2 = list.begin()
+ ; wit2 != list.end(); ++wit2 )
+ {
+ QString s=maskString(*wit2);
+ QRegExp reg(s);
+
+ if(reg.search(origStr) >= 0)
+ {
+ found = true;
+ }
+ }
+ }
+
+ if(found)
+ {
+ foundIndices.append(*it);
+
+ SearchResult *result = new SearchResult;
+ result->requested = searchStr; // FIXME:here should be the original text
+ result->found = data->catalog()->msgid(*it).first();
+#warning kdWarning() << "PoCompendium can't return plural form translation" << endl;
+ result->translation = data->catalog()->msgstr(*it).first();
+ result->score = score(result->requested,*(result->found.at(pluralForm)));
+
+ TranslationInfo *info = new TranslationInfo;
+ info->location = directory(realURL,0);
+ info->translator = catalogInfo.lastTranslator;
+ info->description = data->catalog()->comment(*it);
+ result->descriptions.append(info);
+
+ addResult(result, results);
+
+ foundResults = true;
+ }
+ }
+ }
+ }
+
+ return foundResults;
+}
+
+bool PoCompendium::searchNGram(const QString& searchStr, uint pluralForm, QPtrList<SearchResult>& results, QValueList<int>& foundIndices, QValueList<int>& checkedIndices )
+{
+ uint checkCounter = 0;
+ bool foundResults = false;
+
+ QRegExp searchReg;
+ if(matchContains)
+ {
+ QString s=maskString(searchStr);
+ searchReg.setPattern(s);
+ }
+
+
+ bool breakLoop=false;
+ int i=-1;
+ while(!breakLoop)
+ {
+ if(stop)
+ {
+ breakLoop=true;
+ break;
+ }
+
+ i++;
+
+ if(i >= catalogInfo.total)
+ {
+ breakLoop = true;
+ break;
+ }
+
+ if( (100*(checkCounter+1))%catalogInfo.total < 100)
+ {
+ emit progress( 50+(50*(checkCounter+1))/catalogInfo.total);
+ }
+
+ if(checkedIndices.contains(i))
+ {
+ continue;
+ }
+
+ checkedIndices.append(i);
+ checkCounter++;
+
+ if(ignoreFuzzy && data->catalog()->isFuzzy(i))
+ {
+ continue;
+ }
+
+ if(foundIndices.contains(i))
+ {
+ continue;
+ }
+
+ kapp->processEvents(100);
+
+ QString origStr = data->catalog()->msgid(i).first();
+ origStr = CompendiumData::simplify(origStr);
+
+ if(!caseSensitive)
+ {
+ origStr = origStr.lower();
+ }
+
+
+ // if there is an string which just contains ignored characters,
+ // continue
+ if(origStr.isEmpty() ||
+ (origStr.length() == 1 && searchStr.length() > 1))
+ {
+ continue;
+ }
+
+ bool found = false;
+ if(matchContains && searchReg.search(origStr) >= 0)
+ {
+ found=true;
+ }
+
+ if(!found && matchIsContained)
+ {
+ QString s=maskString(origStr);
+ QRegExp reg(s);
+
+ if(reg.search(searchStr) >= 0)
+ {
+ found = true;
+ }
+ }
+
+ if(!found && matchWords)
+ {
+ QStringList list = CompendiumData::wordList(searchStr);
+
+ for ( QStringList::Iterator wit2 = list.begin()
+ ; wit2 != list.end(); ++wit2 )
+ {
+ QString s=maskString(*wit2);
+
+ if(wholeWords)
+ {
+ origStr = " "+origStr+" ";
+ s=" "+s+" ";
+ }
+ QRegExp reg(s);
+
+ if(reg.search(origStr) >= 0)
+ {
+ found = true;
+ }
+ }
+ }
+
+ if(!found && matchNGram)
+ {
+ // to get more results one could
+ // interchange searchStr and origStr when
+ // the latter is shorter
+
+ found = ( ngramMatch(searchStr,origStr,NGRAM_LEN)
+ > LIM_NGRAM );
+ }
+
+ if(found)
+ {
+ foundIndices.append(i);
+
+ SearchResult *result = new SearchResult;
+ result->requested = searchStr;
+ result->found = data->catalog()->msgid(i).first();
+ result->translation = data->catalog()->msgstr(i).first();
+#warning kdWarning() << "PoCompendium can't return plural form translation" << endl;
+ result->score = score(result->requested,*(result->found.at(pluralForm)));
+
+ TranslationInfo *info = new TranslationInfo;
+ info->location = directory(realURL,0);
+ info->translator = catalogInfo.lastTranslator;
+ info->description = data->catalog()->comment(i);
+ result->descriptions.append(info);
+
+ addResult(result, results);
+
+ foundResults = true;
+ }
+ }
+
+ return foundResults;
+}
+
+bool PoCompendium::startSearch(const QString& text, uint pluralForm, const SearchFilter* filter)
+{
+ if(autoUpdate && prefWidget && prefWidget->settingsChanged())
+ {
+ applySettings();
+ }
+
+ if(isSearching())
+ return false;
+
+ clearResults();
+ stop = false;
+ active = true;
+
+ if(!initialized)
+ {
+ if(loadTimer->isActive())
+ loadTimer->stop();
+
+ slotLoadCompendium();
+ }
+
+ if(error || !data)
+ {
+ active = false;
+ return false;
+ }
+
+ if(data->active())
+ {
+ active = false;
+ return true;
+ }
+
+ emit started();
+
+
+ QValueList<int> foundIndices;
+ QValueList<int> checkedIndices;
+
+ // first, exact search
+ searchExact(text, pluralForm, results, foundIndices, checkedIndices);
+
+ QString searchStr=CompendiumData::simplify(text);
+
+
+ if(!caseSensitive)
+ {
+ searchStr = searchStr.lower();
+
+ // do case insensite search if necessary
+ searchCaseInsensitive(searchStr, pluralForm, results, foundIndices, checkedIndices);
+ }
+
+ // search without whitespace
+ searchTextOnly(searchStr, pluralForm, results, foundIndices, checkedIndices);
+
+ // now, search based on words (contains, is contained, etc)
+ searchWords(searchStr, pluralForm, results, foundIndices, checkedIndices);
+
+
+ if( matchNGram ||
+ (!wholeWords && (matchContains || matchIsContained || matchWords))
+ )
+ {
+ // search based on ngrams
+ searchNGram(searchStr, pluralForm, results, foundIndices, checkedIndices);
+ }
+
+ emit progress(100);
+
+ active = false;
+ stop = false;
+ emit finished();
+
+ return true;
+}
+
+void PoCompendium::stopSearch()
+{
+ stop=true;
+}
+
+
+void PoCompendium::applySettings()
+{
+ if(!prefWidget)
+ return;
+
+ if(isSearching())
+ stopSearch();
+
+ caseSensitive = prefWidget->caseSensitive();
+ ignoreFuzzy = prefWidget->ignoreFuzzy();
+ wholeWords = prefWidget->wholeWords();
+
+ matchEqual = prefWidget->matchEqual();
+ matchNGram = prefWidget->matchNGram();
+ matchIsContained = prefWidget->matchIsContained();
+ matchContains = prefWidget->matchContains();
+ matchWords = prefWidget->matchWords();
+
+
+ bool needLoading=false;
+
+
+ QString newPath = prefWidget->url();
+ if(!initialized)
+ {
+ url = newPath;
+ }
+ else if(newPath != url)
+ {
+ url = newPath;
+ needLoading = true;
+ }
+
+ if(needLoading)
+ {
+ loadCompendium();
+ initialized=false;
+ }
+}
+
+void PoCompendium::restoreSettings()
+{
+ if(!prefWidget)
+ return;
+
+ prefWidget->setCaseSensitive(caseSensitive);
+ prefWidget->setIgnoreFuzzy(ignoreFuzzy);
+ prefWidget->setWholeWords(wholeWords);
+ prefWidget->setURL(url);
+
+ prefWidget->setMatchEqual(matchEqual);
+ prefWidget->setMatchNGram(matchNGram);
+ prefWidget->setMatchIsContained(matchIsContained);
+ prefWidget->setMatchContains(matchContains);
+ prefWidget->setMatchWords(matchWords);
+}
+
+void PoCompendium::loadCompendium()
+{
+ if(!loading && !loadTimer->isActive())
+ loadTimer->start(100,true);
+}
+
+void PoCompendium::slotLoadCompendium()
+{
+ if(loading)
+ return;
+
+ if(loadTimer->isActive())
+ loadTimer->stop();
+
+ loading = true;
+
+ if(data)
+ {
+ unregisterData();
+ }
+
+
+ QString path=url;
+
+ if(path.contains("@LANG@"))
+ {
+ path.replace("@LANG@",langCode);
+ }
+ KURL u=KCmdLineArgs::makeURL(path.local8Bit());
+ realURL = u.url();
+
+ registerData();
+
+
+ if(!data)
+ {
+ kdError() << "no data object in pocompendium?" << endl;
+
+ loading=false;
+ return;
+ }
+
+ if(!data->initialized())
+ {
+ if(!data->active())
+ {
+ data->load(u);
+ recheckData();
+ if(error)
+ {
+ emit hasError(errorMsg);
+ }
+ }
+ else
+ {
+ connect(data, SIGNAL(progressEnds()), this, SLOT(recheckData()));
+ }
+ }
+ else
+ {
+ recheckData();
+ if(error)
+ {
+ emit hasError(errorMsg);
+ }
+ }
+
+ initialized=true;
+}
+
+void PoCompendium::recheckData()
+{
+ if(data)
+ {
+ disconnect(data, SIGNAL(progressEnds()), this, SLOT(recheckData()));
+
+ error = data->hasErrors();
+ errorMsg = data->errorMsg();
+
+ if(!error)
+ {
+ catalogInfo = Catalog::headerInfo(data->catalog()->header());
+ catalogInfo.total = data->catalog()->numberOfEntries();
+ catalogInfo.fuzzy = data->catalog()->numberOfFuzzies();
+ catalogInfo.untranslated = data->catalog()->numberOfUntranslated();
+ }
+ }
+
+ loading=false;
+}
+
+QString PoCompendium::maskString(QString s)
+{
+ s.replace("\\","\\\\");
+ s.replace("\?","\\?");
+ s.replace("[","\\[");
+ s.replace(".","\\.");
+ s.replace("*","\\*");
+ s.replace("+","\\+");
+ s.replace("^","\\^");
+ s.replace("$","\\$");
+ s.replace("(","\\(");
+ s.replace(")","\\)");
+ s.replace("{","\\{");
+ s.replace("}","\\}");
+ s.replace("|","\\|");
+
+ return s;
+}
+
+void PoCompendium::addResult(SearchResult *result, QPtrList<SearchResult>& res)
+{
+ if(res.last() && res.last()->score >= result->score)
+ {
+ res.append(result);
+ }
+ else
+ {
+ SearchResult *sr;
+ for(sr = res.first(); sr != 0; sr=res.next())
+ {
+ if(sr->score < result->score)
+ {
+ int pos = res.at();
+ if( pos < 0 ) pos = 0;
+ res.insert( pos,result);
+ emit resultsReordered();
+ break;
+ }
+ }
+
+ if(!sr)
+ {
+ res.append(result);
+ }
+ }
+
+ emit numberOfResultsChanged(res.count());
+ emit resultFound(result);
+}
+
+
+void PoCompendium::setLanguageCode(const QString& lang)
+{
+ if(initialized && url.contains("@LANG@") && lang!=langCode
+ && !loadTimer->isActive() )
+ {
+ initialized=false;
+ }
+
+ langCode=lang;
+}
+
+QString PoCompendium::translate(const QString& text, uint pluralForm)
+{
+ if(!initialized)
+ {
+ if(loadTimer->isActive())
+ loadTimer->stop();
+
+ slotLoadCompendium();
+ }
+
+ if(error || !data || data->active())
+ {
+ return QString::null;
+ }
+
+
+ const int *index = data->exactDict(text);
+
+ if(index)
+ {
+#warning kdWarning() << "PoCompendium can't return plural form translation" << endl;
+ return data->catalog()->msgstr(*index).first();
+ }
+
+ return QString::null;
+}
+
+QString PoCompendium::fuzzyTranslation(const QString& text, int &score, const uint pluralForm)
+{
+ if(!initialized)
+ {
+ if(loadTimer->isActive())
+ loadTimer->stop();
+
+ slotLoadCompendium();
+ }
+
+ if(error || !data || data->active())
+ {
+ return QString::null;
+ }
+
+ // try to find fuzzy string
+ bool breakLoop = false;
+ stop = false;
+ int i=-1;
+ int best_matching = -1;
+ int best_match = 0;
+ int total = data->catalog()->numberOfEntries();
+
+ QString searchStr = CompendiumData::simplify(text);
+
+ //kdDebug(750) << "find best match for " << searchStr << endl;
+
+ while(!breakLoop)
+ {
+
+ // progress and loop control
+ if(stop)
+ {
+ breakLoop=true;
+ break;
+ }
+
+ i++;
+
+ if(i >= total)
+ {
+ breakLoop = true;
+ break;
+ }
+
+ if( (100*(i+1))%total < 100)
+ {
+ emit progress( (100*(i+1))/total);
+ }
+
+ // get a message from the catalog FIXME: plurals
+ QString origStr = data->catalog()->msgid(i).first();
+ origStr = CompendiumData::simplify(origStr);
+
+ // don't match too long strings for short search string
+ if (origStr.length() > 2*searchStr.length())
+ continue;
+ // kdDebug(750) << i << ": matching " << origStr << endl;
+
+ int ngram_result = ngramMatch(searchStr,origStr);
+
+ if (ngram_result > best_match) {
+ best_match = ngram_result;
+ best_matching = i;
+
+ // kdDebug(750) << "[" << ngram_result << "] " << text << "-"
+ // << origStr << endl;
+ }
+ }
+
+ if (best_match > LIM_NGRAM) {
+ score = best_match;
+#warning kdWarning() << "PoCompendium can't return plural form translation" << endl;
+ return data->catalog()->msgstr(best_matching).first();
+ }
+
+ return QString::null;
+}
+
+
+QString PoCompendium::searchTranslation(const QString& text, int &sc, const uint pluralForm)
+{
+ if(autoUpdate && prefWidget && prefWidget->settingsChanged())
+ {
+ applySettings();
+ }
+
+ if(isSearching())
+ return QString::null;
+
+ clearResults();
+ stop = false;
+ active = true;
+
+ if(!initialized)
+ {
+ if(loadTimer->isActive())
+ loadTimer->stop();
+
+ slotLoadCompendium();
+ }
+
+ if(error || !data)
+ {
+ active = false;
+ return QString::null;
+ }
+
+ if(data->active())
+ {
+ active = false;
+ return QString::null;
+ }
+
+ emit started();
+
+ QPtrList<SearchResult> res;
+
+ QValueList<int> foundIndices;
+ QValueList<int> checkedIndices;
+
+ // first, exact search
+ if( searchExact(text, pluralForm, res, foundIndices, checkedIndices) )
+ {
+ active = false;
+ stop = false;
+ emit finished();
+
+ // found, this is the best
+ sc = res.first()->score;
+ return res.first()->translation;
+ }
+
+ QString searchStr=CompendiumData::simplify(text);
+
+
+ if(!caseSensitive)
+ {
+ searchStr = searchStr.lower();
+
+ // do case insensite search if necessary
+ if( searchCaseInsensitive(searchStr, pluralForm, res, foundIndices, checkedIndices) )
+ {
+ active = false;
+ stop = false;
+ emit finished();
+
+ // found, return this one
+ sc = res.first()->score;
+ return res.first()->translation;
+ }
+ }
+
+ // search without whitespace
+ QString s = searchStr;
+ s.remove( ' ' );
+ if( searchTextOnly(s, pluralForm, res, foundIndices, checkedIndices) )
+ {
+ active = false;
+ stop = false;
+ emit finished();
+
+ // found, return this one
+ sc = res.first()->score;
+ return res.first()->translation;
+ }
+
+ // now, search based on words (contains, is contained, etc)
+ searchWords(searchStr, pluralForm, res, foundIndices, checkedIndices);
+
+ if( matchNGram ||
+ (!wholeWords && (matchContains || matchIsContained || matchWords))
+ )
+ {
+ // search based on ngrams
+ searchNGram(searchStr, pluralForm, res, foundIndices, checkedIndices);
+ }
+
+ active = false;
+ stop = false;
+
+ // now, pick up the best one from not exact translations
+ if( res.count() > 0 ) {
+
+ emit finished();
+
+ sc = res.first()->score;
+ return res.first()->translation;
+ }
+
+ sc = 0;
+
+ return QString::null;
+}
+
+
+void PoCompendium::unregisterData()
+{
+ if(data)
+ {
+ disconnect(data, SIGNAL(progressStarts(const QString&)), this
+ , SIGNAL(progressStarts(const QString&)));
+ disconnect(data, SIGNAL(progressEnds()), this , SIGNAL(progressEnds()));
+ disconnect(data, SIGNAL(progress(int)), this , SIGNAL(progress(int)));
+
+ if(data->active())
+ {
+ disconnect(data,SIGNAL(progressEnds()),this,SLOT(recheckData()));
+ }
+
+ if(data->unregisterObject(this))
+ {
+ if(!data->active())
+ {
+ compendiumDict()->remove(realURL);
+ }
+ else
+ {
+ connect(data,SIGNAL(progressEnds()),this,SLOT(removeData()));
+ }
+ }
+
+ data=0;
+ }
+}
+
+void PoCompendium::registerData()
+{
+ data = compendiumDict()->find(realURL);
+ if(!data)
+ {
+ data = new CompendiumData;
+ compendiumDict()->insert(realURL,data);
+ }
+
+ data->registerObject(this);
+
+ if(data->active())
+ {
+ emit progressStarts(i18n("Loading PO compendium"));
+ }
+
+ connect(data, SIGNAL(
+ progressStarts(const QString&)), this
+ , SIGNAL(progressStarts(const QString&)));
+ connect(data, SIGNAL(progressEnds()), this , SIGNAL(progressEnds()));
+ connect(data, SIGNAL(progress(int)), this , SIGNAL(progress(int)));
+}
+
+void PoCompendium::removeData()
+{
+ const QObject *s=sender();
+ if(s && s->inherits("CompendiumData"))
+ {
+ const CompendiumData *d=static_cast<const CompendiumData*>(s);
+ if(d)
+ {
+ QDictIterator<CompendiumData> it(*compendiumDict());
+ while(it.current())
+ {
+ if(it.current() == d)
+ {
+ if(!d->hasObjects())
+ {
+ compendiumDict()->remove(it.currentKey());
+ }
+
+ break;
+ }
+
+ ++it;
+ }
+ }
+
+ }
+}
+
+QDict<CompendiumData> *PoCompendium::compendiumDict()
+{
+ if(!_compDict)
+ {
+ _compDict=compDataDeleter.setObject( new QDict<CompendiumData> );
+ _compDict->setAutoDelete(true);
+ }
+
+ return _compDict;
+}
+
+
+
+#include "pocompendium.moc"
diff --git a/kbabel/kbabeldict/modules/pocompendium/pocompendium.desktop b/kbabel/kbabeldict/modules/pocompendium/pocompendium.desktop
new file mode 100644
index 00000000..ac9ee368
--- /dev/null
+++ b/kbabel/kbabeldict/modules/pocompendium/pocompendium.desktop
@@ -0,0 +1,50 @@
+[Desktop Entry]
+Type=Service
+Name=PO Compendium Module for KBabelDict
+Name[bg]=PO компендиум за KBabelDict
+Name[bs]=Modul PO kompendijuma za KBabelDict
+Name[ca]=Mòdul del Compendi PO per a KBabelDict
+Name[cs]=Modul s PO kompendiem pro KBabelDict
+Name[cy]=Modiwl Compendiwm PO i KBabelDict
+Name[da]=PO-kompendium-module for KBabelDict
+Name[de]=PO-Kompendium-Modul für KBabelDict
+Name[el]=ΆÏθÏωμα επιτομής PO για το KBabelDict
+Name[es]=Módulo de compendio de PO para KBabelDict
+Name[et]=KBabelDicti PO kompendiumi moodul
+Name[eu]=PO laburpen modulua KBabelDict-entzat
+Name[fa]=پیمانۀ مختصر PO برای KBabelDict
+Name[fi]=KBabelDict-ohjelman PO-kokoelmatiedostomoduuli
+Name[fr]=Module de fichier de référence PO pour KBabelDict
+Name[gl]=Módulo de compendio PO para KBabelDict
+Name[hi]=के-बेबल-डिकà¥à¤¶ के लिठपीओ कमà¥à¤ªà¥‡à¤‚डियम मॉडà¥à¤¯à¥‚ल
+Name[hu]=PO összefoglaló modul a KBabelDicthez
+Name[is]=PO ágrips eining fyrir KBabel orðabókina
+Name[it]=Modulo PO Compendium per KBabelDict
+Name[ja]=KBabelDict PO è¦ç´„モジュール
+Name[ka]=PO კáƒáƒœáƒ¡áƒžáƒ”ქტის მáƒáƒ“ული KBabelDict-სთვის
+Name[kk]=KBabelDict-тың PO аудармалар жиынтық модулі
+Name[lt]=KBabelDict PO tekstyno modulis
+Name[ms]=Modul Kompendium PO untuk KBabelDict
+Name[nb]=PO-kompendiummodul for KBabelDict
+Name[nds]=PO-Kompendiummoduul för KBabelDict
+Name[ne]=KBabelDict का लागि संकà¥à¤·à¥‡à¤ª पीओ मोडà¥à¤¯à¥à¤²
+Name[nl]=PO-samenvattingmodule voor KBabelDict
+Name[nn]=PO-kompendiemodul for KBabelDict
+Name[pa]=ਕੇਬਬੇਲ-ਸ਼ਬਦਕੋਸ਼ ਲਈ PO ਸੰਖੇਪ ਮੈਡੀਊਲ
+Name[pl]=Moduł Kompendium PO dla KBabelDict
+Name[pt]=Módulo de Compêndio de PO para o KBabelDict
+Name[pt_BR]=Módulo de Compêndio PO para o KBabelDict
+Name[ru]=Модуль опиÑÐ°Ð½Ð¸Ñ PO Ð´Ð»Ñ KBabelDict
+Name[sk]=Kompendium pre KBabelDict
+Name[sl]=Modul zbornika PO za KBabelDict
+Name[sr]=Модул PO зборника за KBabelDict
+Name[sr@Latn]=Modul PO zbornika za KBabelDict
+Name[sv]=PO-kompendiemodul för Kbabeldict
+Name[ta]=Kபாபேலà¯à®•à¯à®•à®¾à®© காமà¯à®ªà¯†à®©à¯à®Ÿà®¿à®¯à®®à¯ PO கூறà¯
+Name[tg]=Модули таÑвири PO барои KBabelDict
+Name[tr]=KBabelDict için PO Özet Modülü
+Name[uk]=Модуль збірки перекладів PO Ð´Ð»Ñ KBabelDict
+Name[zh_CN]=KBabelDict çš„ PO 概è¦è¯å…¸æ¨¡å—
+Name[zh_TW]=KBabelDict PO 摘è¦æ¨¡çµ„
+X-KDE-Library=kbabeldict_pocompendium
+ServiceTypes=KBabelDictModule
diff --git a/kbabel/kbabeldict/modules/pocompendium/pocompendium.h b/kbabel/kbabeldict/modules/pocompendium/pocompendium.h
new file mode 100644
index 00000000..6d92fb58
--- /dev/null
+++ b/kbabel/kbabeldict/modules/pocompendium/pocompendium.h
@@ -0,0 +1,147 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#ifndef POCOMPENDIUM_H
+#define POCOMPENDIUM_H
+
+#include <poinfo.h>
+
+#include "compendiumdata.h"
+#include "searchengine.h"
+
+#include <qdict.h>
+#include <qfile.h>
+#include <qguardedptr.h>
+#include <qptrlist.h>
+
+class CompendiumPreferencesWidget;
+class KConfigBase;
+class QTimer;
+
+class PoCompendium : public SearchEngine
+{
+ Q_OBJECT
+
+public:
+ PoCompendium(QObject *parent=0, const char *name=0);
+ virtual ~PoCompendium();
+
+ virtual bool isReady() const;
+
+ virtual QString translate(const QString&text, uint pluralForm);
+ virtual QString searchTranslation(const QString&, int &score, const uint pluralForm);
+ virtual QString fuzzyTranslation(const QString&, int &score, const uint pluralForm);
+
+ virtual bool isSearching() const;
+
+ virtual void saveSettings(KConfigBase *config);
+ virtual void readSettings(KConfigBase *config);
+
+ virtual PrefWidget *preferencesWidget(QWidget *parent);
+
+ virtual const KAboutData *about() const;
+
+ virtual QString name() const;
+
+ virtual QString id() const;
+
+ virtual QString lastError();
+
+
+public slots:
+ virtual bool startSearch(const QString& s, uint pluralForm = 0, const SearchFilter* filter = 0);
+ virtual void stopSearch();
+ virtual void setLanguageCode(const QString& lang);
+
+protected slots:
+ /** reads the current settings from the preferences dialog */
+ void applySettings();
+
+ /** sets the current settings in the preferences dialog */
+ void restoreSettings();
+
+ void slotLoadCompendium();
+
+ void recheckData();
+ void removeData();
+
+protected:
+ void loadCompendium();
+ void addResult(SearchResult *, QPtrList<SearchResult>& allResults);
+ QString maskString(QString string);
+
+ void registerData();
+ void unregisterData();
+
+ bool searchExact(const QString& searchString, uint pluralForm, QPtrList<SearchResult>& results, QValueList<int>& foundIndices, QValueList<int>& checkedIndices );
+ bool searchTextOnly(const QString& searchString, uint pluralForm, QPtrList<SearchResult>& results, QValueList<int>& foundIndices, QValueList<int>& checkedIndices );
+ bool searchCaseInsensitive(const QString& searchString, uint pluralForm, QPtrList<SearchResult>& results, QValueList<int>& foundIndices, QValueList<int>& checkedIndices );
+ bool searchWords(const QString& searchString, uint pluralForm, QPtrList<SearchResult>& results, QValueList<int>& foundIndices, QValueList<int>& checkedIndices );
+ bool searchNGram(const QString& searchString, uint pluralForm, QPtrList<SearchResult>& results, QValueList<int>& foundIndices, QValueList<int>& checkedIndices );
+
+private:
+ QGuardedPtr<CompendiumPreferencesWidget> prefWidget;
+ CompendiumData *data;
+ KBabel::PoInfo catalogInfo;
+ QTimer *loadTimer;
+
+ QString url;
+ QString realURL;
+ QString langCode;
+
+ bool caseSensitive;
+ bool ignoreFuzzy;
+ bool wholeWords;
+
+ bool matchEqual;
+ bool matchIsContained;
+ bool matchContains;
+ bool matchWords;
+ bool matchNGram;
+
+ bool buildIndex;
+ uint freeMemDelay;
+
+ bool error;
+ QString errorMsg;
+
+ bool stop;
+ bool active;
+ bool initialized;
+ bool loading;
+
+ static QDict<CompendiumData> *_compDict;
+ static QDict<CompendiumData> *compendiumDict();
+};
+
+#endif
diff --git a/kbabel/kbabeldict/modules/pocompendium/preferenceswidget.cpp b/kbabel/kbabeldict/modules/pocompendium/preferenceswidget.cpp
new file mode 100644
index 00000000..c3ce730d
--- /dev/null
+++ b/kbabel/kbabeldict/modules/pocompendium/preferenceswidget.cpp
@@ -0,0 +1,352 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+
+#include <kfiledialog.h>
+#include <qpushbutton.h>
+#include <qwhatsthis.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <kurlrequester.h>
+
+#include "preferenceswidget.h"
+#include "pwidget.h"
+
+CompendiumPreferencesWidget::CompendiumPreferencesWidget(QWidget *parent, const char* name)
+ : PrefWidget(parent,name)
+ , changed(false)
+{
+ QVBoxLayout *layout = new QVBoxLayout(this);
+
+ prefWidget = new CompendiumPWidget(this);
+ layout->addWidget(prefWidget);
+
+ connect(prefWidget->caseBtn, SIGNAL(toggled(bool))
+ , this, SLOT(setChanged()));
+ connect(prefWidget->equalBtn, SIGNAL(toggled(bool))
+ , this, SLOT(setChanged()));
+ connect(prefWidget->ngramBtn, SIGNAL(toggled(bool))
+ , this, SLOT(setChanged()));
+ connect(prefWidget->isContainedBtn, SIGNAL(toggled(bool))
+ , this, SLOT(setChanged()));
+ connect(prefWidget->containsBtn, SIGNAL(toggled(bool))
+ , this, SLOT(setChanged()));
+ connect(prefWidget->fuzzyBtn, SIGNAL(toggled(bool))
+ , this, SLOT(setChanged()));
+ connect(prefWidget->hasWordBtn, SIGNAL(toggled(bool))
+ , this, SLOT(setChanged()));
+ connect(prefWidget->wholeBtn, SIGNAL(toggled(bool))
+ , this, SLOT(setChanged()));
+
+ connect(prefWidget->urlInput->lineEdit(),SIGNAL(textChanged(const QString&))
+ , this, SLOT(setChanged()));
+
+ connect(prefWidget->equalBtn, SIGNAL(toggled(bool))
+ , this, SLOT(equalBtnToggled(bool)));
+ connect(prefWidget->ngramBtn, SIGNAL(toggled(bool))
+ , this, SLOT(ngramBtnToggled(bool)));
+ connect(prefWidget->isContainedBtn, SIGNAL(toggled(bool))
+ , this, SLOT(isContainedBtnToggled(bool)));
+ connect(prefWidget->containsBtn, SIGNAL(toggled(bool))
+ , this, SLOT(containsBtnToggled(bool)));
+ connect(prefWidget->hasWordBtn, SIGNAL(toggled(bool))
+ , this, SLOT(hasWordBtnToggled(bool)));
+
+
+ QString whatsthis=i18n("<qt><p><b>Parameters</b></p>"
+ "<p>Here you can fine-tune searching within the PO file. "
+ "For example if you want to perform a case sensitive search, or if "
+ "you want fuzzy messages to be ignored.</p></qt>" );
+ QWhatsThis::add(prefWidget->caseBtn,whatsthis);
+ QWhatsThis::add(prefWidget->fuzzyBtn,whatsthis);
+ QWhatsThis::add(prefWidget->wholeBtn,whatsthis);
+
+ whatsthis = i18n("<qt><p><b>Comparison Options</b></p>"
+ "<p>Choose here which messages you want to have treated as a matching "
+ "message.</p></qt>");
+ QWhatsThis::add(prefWidget->equalBtn,whatsthis);
+ QWhatsThis::add(prefWidget->containsBtn,whatsthis);
+ QWhatsThis::add(prefWidget->isContainedBtn,whatsthis);
+ QWhatsThis::add(prefWidget->hasWordBtn,whatsthis);
+
+ whatsthis = i18n("<qt><p><b>3-Gram-matching</b></p>"
+ "<p>A message matches another if most of its 3-letter groups are "
+ "contained in the other message. e.g. 'abc123' matches 'abcx123c12'.</p></qt>");
+ QWhatsThis::add(prefWidget->ngramBtn,whatsthis);
+
+ whatsthis = i18n("<qt><p><b>Location</b></p>"
+ "<p>Configure here which file is to be used for searching."
+ "</p></qt>");
+ QWhatsThis::add(prefWidget->urlInput,whatsthis);
+}
+
+CompendiumPreferencesWidget::~CompendiumPreferencesWidget()
+{
+}
+
+
+void CompendiumPreferencesWidget::apply()
+{
+ emit applySettings();
+}
+
+void CompendiumPreferencesWidget::cancel()
+{
+ emit restoreSettings();
+}
+
+void CompendiumPreferencesWidget::standard()
+{
+ prefWidget->urlInput->setURL("http://i18n.kde.org/po_overview/@LANG@.messages");
+ prefWidget->caseBtn->setChecked(false);
+ prefWidget->equalBtn->setChecked(true);
+ prefWidget->ngramBtn->setChecked(true);
+ prefWidget->isContainedBtn->setChecked(false);
+ prefWidget->containsBtn->setChecked(false);
+ prefWidget->wholeBtn->setChecked(true);
+ prefWidget->hasWordBtn->setChecked(true);
+
+ prefWidget->fuzzyBtn->setChecked(true);
+
+ changed=true;
+}
+
+void CompendiumPreferencesWidget::setURL(const QString url)
+{
+ prefWidget->urlInput->setURL(url);
+ changed=false;
+}
+
+void CompendiumPreferencesWidget::setCaseSensitive(bool on)
+{
+ prefWidget->caseBtn->setChecked(on);
+ changed=false;
+}
+
+void CompendiumPreferencesWidget::setMatchEqual(bool on)
+{
+ prefWidget->equalBtn->setChecked(on);
+ changed=false;
+}
+
+void CompendiumPreferencesWidget::setMatchNGram(bool on)
+{
+ prefWidget->ngramBtn->setChecked(on);
+ changed=false;
+}
+
+void CompendiumPreferencesWidget::setMatchIsContained(bool on)
+{
+ prefWidget->isContainedBtn->setChecked(on);
+ changed=false;
+}
+
+void CompendiumPreferencesWidget::setMatchContains(bool on)
+{
+ prefWidget->containsBtn->setChecked(on);
+ changed=false;
+}
+
+void CompendiumPreferencesWidget::setIgnoreFuzzy(bool on)
+{
+ prefWidget->fuzzyBtn->setChecked(on);
+ changed=false;
+}
+
+void CompendiumPreferencesWidget::setWholeWords(bool on)
+{
+ prefWidget->wholeBtn->setChecked(on);
+ changed=false;
+}
+
+
+void CompendiumPreferencesWidget::setMatchWords(bool on)
+{
+ prefWidget->hasWordBtn->setChecked(on);
+ changed=false;
+}
+
+
+
+QString CompendiumPreferencesWidget::url()
+{
+ changed=false;
+ return prefWidget->urlInput->url();
+}
+
+bool CompendiumPreferencesWidget::caseSensitive()
+{
+ changed=false;
+
+ return prefWidget->caseBtn->isChecked();
+}
+
+bool CompendiumPreferencesWidget::matchEqual()
+{
+ changed=false;
+
+ return prefWidget->equalBtn->isChecked();
+}
+
+bool CompendiumPreferencesWidget::matchNGram()
+{
+ changed=false;
+
+ return prefWidget->ngramBtn->isChecked();
+}
+
+bool CompendiumPreferencesWidget::matchIsContained()
+{
+ changed=false;
+
+ return prefWidget->isContainedBtn->isChecked();
+}
+
+bool CompendiumPreferencesWidget::matchContains()
+{
+ changed=false;
+
+ return prefWidget->containsBtn->isChecked();
+}
+
+bool CompendiumPreferencesWidget::ignoreFuzzy()
+{
+ changed=false;
+
+ return prefWidget->fuzzyBtn->isChecked();
+}
+
+
+bool CompendiumPreferencesWidget::wholeWords()
+{
+ changed=false;
+
+ return prefWidget->wholeBtn->isChecked();
+}
+
+
+bool CompendiumPreferencesWidget::matchWords()
+{
+ changed=false;
+
+ return prefWidget->hasWordBtn->isChecked();
+}
+
+
+
+bool CompendiumPreferencesWidget::settingsChanged() const
+{
+ return changed;
+}
+
+void CompendiumPreferencesWidget::setChanged()
+{
+ changed=true;
+}
+
+
+void CompendiumPreferencesWidget::equalBtnToggled(bool on)
+{
+ if(!on)
+ {
+ if(!prefWidget->isContainedBtn->isChecked()
+ && !prefWidget->ngramBtn->isChecked()
+ && !prefWidget->containsBtn->isChecked()
+ && !prefWidget->hasWordBtn->isChecked())
+ {
+ prefWidget->equalBtn->setChecked(true);
+ }
+ }
+}
+
+void CompendiumPreferencesWidget::ngramBtnToggled(bool on)
+{
+ if(!on)
+ {
+ if(!prefWidget->isContainedBtn->isChecked()
+ && !prefWidget->equalBtn->isChecked()
+ && !prefWidget->containsBtn->isChecked()
+ && !prefWidget->hasWordBtn->isChecked())
+ {
+ prefWidget->equalBtn->setChecked(true);
+ }
+ }
+}
+
+void CompendiumPreferencesWidget::isContainedBtnToggled(bool on)
+{
+ if(!on)
+ {
+ if(!prefWidget->equalBtn->isChecked()
+ && !prefWidget->ngramBtn->isChecked()
+ && !prefWidget->containsBtn->isChecked()
+ && !prefWidget->hasWordBtn->isChecked())
+ {
+ prefWidget->isContainedBtn->setChecked(true);
+ }
+ }
+}
+
+void CompendiumPreferencesWidget::containsBtnToggled(bool on)
+{
+ if(!on)
+ {
+ if(!prefWidget->isContainedBtn->isChecked()
+ && !prefWidget->ngramBtn->isChecked()
+ && !prefWidget->equalBtn->isChecked()
+ && !prefWidget->hasWordBtn->isChecked())
+ {
+ prefWidget->containsBtn->setChecked(true);
+ }
+ }
+}
+
+void CompendiumPreferencesWidget::hasWordBtnToggled(bool on)
+{
+ if(!on)
+ {
+ if(!prefWidget->isContainedBtn->isChecked()
+ && !prefWidget->ngramBtn->isChecked()
+ && !prefWidget->equalBtn->isChecked()
+ && !prefWidget->containsBtn->isChecked())
+ {
+ prefWidget->hasWordBtn->setChecked(true);
+ }
+ }
+}
+
+
+
+#include "preferenceswidget.moc"
diff --git a/kbabel/kbabeldict/modules/pocompendium/preferenceswidget.h b/kbabel/kbabeldict/modules/pocompendium/preferenceswidget.h
new file mode 100644
index 00000000..db70df4d
--- /dev/null
+++ b/kbabel/kbabeldict/modules/pocompendium/preferenceswidget.h
@@ -0,0 +1,97 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#ifndef PREFERENCESWIDGET_H
+#define PREFERENCESWIDGET_H
+
+#include "searchengine.h"
+
+class CompendiumPWidget;
+
+class CompendiumPreferencesWidget : public PrefWidget
+{
+ Q_OBJECT
+
+public:
+ CompendiumPreferencesWidget(QWidget *parent=0, const char* name=0);
+ virtual ~CompendiumPreferencesWidget();
+
+ virtual void apply();
+ virtual void cancel();
+ virtual void standard();
+
+ void setURL(const QString url);
+ void setMatchEqual(bool);
+ void setMatchNGram(bool);
+ void setMatchIsContained(bool);
+ void setMatchContains(bool);
+ void setIgnoreFuzzy(bool);
+ void setMatchWords(bool);
+ void setWholeWords(bool);
+ void setCaseSensitive(bool);
+
+ QString url();
+ bool matchEqual();
+ bool matchNGram();
+ bool matchIsContained();
+ bool matchContains();
+ bool ignoreFuzzy();
+ bool matchWords();
+ bool wholeWords();
+ bool caseSensitive();
+
+
+ bool settingsChanged() const;
+
+signals:
+ void restoreSettings();
+ void applySettings();
+
+public:
+ CompendiumPWidget *prefWidget;
+
+protected slots:
+ void setChanged();
+ void equalBtnToggled(bool);
+ void ngramBtnToggled(bool);
+ void isContainedBtnToggled(bool);
+ void containsBtnToggled(bool);
+ void hasWordBtnToggled(bool);
+
+private:
+ bool changed;
+
+};
+
+#endif
diff --git a/kbabel/kbabeldict/modules/pocompendium/pwidget.ui b/kbabel/kbabeldict/modules/pocompendium/pwidget.ui
new file mode 100644
index 00000000..8f54b087
--- /dev/null
+++ b/kbabel/kbabeldict/modules/pocompendium/pwidget.ui
@@ -0,0 +1,280 @@
+<!DOCTYPE UI><UI>
+<class>CompendiumPWidget</class>
+<include location="global">kseparator.h</include>
+<widget>
+ <class>QWidget</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>PWidget</cstring>
+ </property>
+ <property stdset="1">
+ <name>geometry</name>
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>452</width>
+ <height>291</height>
+ </rect>
+ </property>
+ <property stdset="1">
+ <name>caption</name>
+ <string></string>
+ </property>
+ <vbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>11</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>6</number>
+ </property>
+ <widget>
+ <class>QGroupBox</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>GroupBox1</cstring>
+ </property>
+ <property stdset="1">
+ <name>title</name>
+ <string>&amp;Path to Compendium File</string>
+ </property>
+ <vbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>11</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>6</number>
+ </property>
+ <widget>
+ <class>KURLRequester</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>urlInput</cstring>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget>
+ <class>QButtonGroup</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>ButtonGroup1</cstring>
+ </property>
+ <property stdset="1">
+ <name>title</name>
+ <string>Options</string>
+ </property>
+ <vbox>
+ <property stdset="1">
+ <name>margin</name>
+ <number>11</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>6</number>
+ </property>
+ <widget>
+ <class>QLayoutWidget</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>Layout4</cstring>
+ </property>
+ <grid>
+ <property stdset="1">
+ <name>margin</name>
+ <number>0</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>6</number>
+ </property>
+ <widget row="1" column="0" >
+ <class>QCheckBox</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>fuzzyBtn</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Ignore &amp;fuzzy strings</string>
+ </property>
+ </widget>
+ <widget row="0" column="1" >
+ <class>QCheckBox</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>wholeBtn</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Onl&amp;y whole words</string>
+ </property>
+ </widget>
+ <widget row="0" column="0" >
+ <class>QCheckBox</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>caseBtn</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Case sensiti&amp;ve</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget>
+ <class>KSeparator</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>Line1</cstring>
+ </property>
+ <property stdset="1">
+ <name>orientation</name>
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget>
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>TextLabel3</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>A text matches if:</string>
+ </property>
+ </widget>
+ <widget>
+ <class>QLayoutWidget</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>Layout3</cstring>
+ </property>
+ <grid>
+ <property stdset="1">
+ <name>margin</name>
+ <number>0</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>6</number>
+ </property>
+ <widget row="0" column="0" >
+ <class>QCheckBox</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>equalBtn</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>E&amp;qual to searched text</string>
+ </property>
+ </widget>
+ <widget row="2" column="1" >
+ <class>QCheckBox</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>hasWordBtn</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Contains a &amp;word of searched text</string>
+ </property>
+ </widget>
+ <widget row="1" column="1" >
+ <class>QCheckBox</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>isContainedBtn</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Co&amp;ntained in searched text</string>
+ </property>
+ </widget>
+ <widget row="1" column="0" >
+ <class>QCheckBox</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>ngramBtn</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>&amp;Similar to searched text</string>
+ </property>
+ </widget>
+ <widget row="0" column="1" >
+ <class>QCheckBox</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>containsBtn</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>Contains searched te&amp;xt</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </vbox>
+ </widget>
+ <spacer>
+ <property>
+ <name>name</name>
+ <cstring>Spacer1</cstring>
+ </property>
+ <property stdset="1">
+ <name>orientation</name>
+ <enum>Vertical</enum>
+ </property>
+ <property stdset="1">
+ <name>sizeType</name>
+ <enum>Expanding</enum>
+ </property>
+ <property>
+ <name>sizeHint</name>
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property>
+ <name>sizeHint</name>
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>KURLRequester</class>
+ <header location="global">kurlrequester.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image>
+ <name>image0</name>
+ <data format="XPM.GZ" length="646">789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758</data>
+ </image>
+</images>
+<tabstops>
+ <tabstop>caseBtn</tabstop>
+</tabstops>
+</UI>
diff --git a/kbabel/kbabeldict/modules/tmx/Makefile.am b/kbabel/kbabeldict/modules/tmx/Makefile.am
new file mode 100644
index 00000000..f0f54b01
--- /dev/null
+++ b/kbabel/kbabeldict/modules/tmx/Makefile.am
@@ -0,0 +1,34 @@
+## Makefile.am for tmxcompendium
+
+# this has all of the subdirectories that make will recurse into. if
+# there are none, comment this out
+#SUBDIRS =
+
+
+# this is the program that gets installed. it's name is used for all
+# of the other Makefile.am variables
+kde_module_LTLIBRARIES = kbabeldict_tmxcompendium.la
+
+# set the include path for X, qt and KDE
+INCLUDES = -I$(srcdir)/../.. -I../../../common -I$(srcdir)/../../../common $(all_includes)
+
+
+# which sources should be compiled for kbabel
+kbabeldict_tmxcompendium_la_SOURCES = tmxcompendium.cpp preferenceswidget.cpp \
+ pc_factory.cpp pwidget.ui tmxcompendiumdata.cpp
+
+kbabeldict_tmxcompendium_la_LIBADD = ../../libkbabeldictplugin.la ../../../common/libkbabelcommon.la $(LIB_KDEUI) $(LIB_KIO)
+kbabeldict_tmxcompendium_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined
+
+
+
+# these are the headers for your project
+noinst_HEADERS = tmxcompendium.h preferenceswidget.h pc_factory.h \
+ tmxcompendiumdata.h
+
+
+# let automoc handle all of the meta source files (moc)
+METASOURCES = AUTO
+
+kde_services_DATA = tmxcompendium.desktop
+EXTRA_DIST = $(kde_services_DATA)
diff --git a/kbabel/kbabeldict/modules/tmx/pc_factory.cpp b/kbabel/kbabeldict/modules/tmx/pc_factory.cpp
new file mode 100644
index 00000000..a3dcfdf9
--- /dev/null
+++ b/kbabel/kbabeldict/modules/tmx/pc_factory.cpp
@@ -0,0 +1,111 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer <matthias.kiefer@gmx.de>
+ 2002 by Stanislav Visnovsky <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#include <klocale.h>
+#include <kinstance.h>
+#include <kaboutdata.h>
+#include <kdebug.h>
+
+#include "pc_factory.h"
+#include "tmxcompendium.h"
+
+
+extern "C"
+{
+ KDE_EXPORT void *init_kbabeldict_tmxcompendium()
+ {
+ return new PcFactory;
+ }
+}
+
+
+KInstance *PcFactory::s_instance = 0;
+KAboutData *PcFactory::s_about = 0;
+
+
+PcFactory::PcFactory( QObject *parent, const char *name)
+ : KLibFactory(parent,name)
+{
+}
+
+PcFactory::~PcFactory()
+{
+ if(s_instance)
+ {
+ delete s_instance;
+ s_instance=0;
+ }
+
+ if(s_about)
+ {
+ delete s_about;
+ s_about=0;
+ }
+}
+
+
+QObject *PcFactory::createObject( QObject *parent, const char *name
+ , const char *classname, const QStringList &)
+{
+ if(QCString(classname) != "SearchEngine")
+ {
+ kdError() << "not a SearchEngine requested" << endl;
+ return 0;
+ }
+
+ return new TmxCompendium(parent,name);
+}
+
+
+KInstance *PcFactory::instance()
+{
+ if(!s_instance)
+ {
+ s_about = new KAboutData( "tmxcompendium", I18N_NOOP("TMX Compendium")
+ , "1.0"
+ , I18N_NOOP("A module for searching in a TMX file")
+ , KAboutData::License_GPL
+ , "Copyright 2002, Stanislav Visnovsky"
+ ,0,0, "visnovsky@kde.org");
+
+ s_about->addAuthor("Matthias Kiefer",0,"kiefer@kde.org");
+ s_about->addAuthor("Stanislav Visnovsky",0,"visnovsky@kde.org");
+
+ s_instance = new KInstance(s_about);
+ }
+
+ return s_instance;
+}
+
+#include "pc_factory.moc"
diff --git a/kbabel/kbabeldict/modules/tmx/pc_factory.h b/kbabel/kbabeldict/modules/tmx/pc_factory.h
new file mode 100644
index 00000000..5ef08277
--- /dev/null
+++ b/kbabel/kbabeldict/modules/tmx/pc_factory.h
@@ -0,0 +1,62 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2002 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#ifndef PC_FACTORY_H
+#define PC_FACTORY_H
+
+#include <klibloader.h>
+class KInstance;
+class KAboutData;
+
+class PcFactory : public KLibFactory
+{
+ Q_OBJECT
+public:
+ PcFactory( QObject *parent=0, const char *name=0);
+ ~PcFactory();
+
+ virtual QObject *createObject( QObject *parent=0, const char *name=0
+ , const char *classname="QObject"
+ , const QStringList &args = QStringList());
+
+ static KInstance *instance();
+
+private:
+ static KInstance *s_instance;
+ static KAboutData *s_about;
+};
+
+#endif
diff --git a/kbabel/kbabeldict/modules/tmx/preferenceswidget.cpp b/kbabel/kbabeldict/modules/tmx/preferenceswidget.cpp
new file mode 100644
index 00000000..1202496d
--- /dev/null
+++ b/kbabel/kbabeldict/modules/tmx/preferenceswidget.cpp
@@ -0,0 +1,334 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2002 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+
+#include <kfiledialog.h>
+#include <qpushbutton.h>
+#include <qwhatsthis.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <kurlrequester.h>
+
+#include "preferenceswidget.h"
+#include "pwidget.h"
+
+TmxCompendiumPreferencesWidget::TmxCompendiumPreferencesWidget(QWidget *parent, const char* name)
+ : PrefWidget(parent,name)
+ , changed(false)
+{
+ QVBoxLayout *layout = new QVBoxLayout(this);
+
+ prefWidget = new TmxCompendiumPWidget(this);
+ layout->addWidget(prefWidget);
+
+ connect(prefWidget->caseBtn, SIGNAL(toggled(bool))
+ , this, SLOT(setChanged()));
+ connect(prefWidget->equalBtn, SIGNAL(toggled(bool))
+ , this, SLOT(setChanged()));
+ connect(prefWidget->ngramBtn, SIGNAL(toggled(bool))
+ , this, SLOT(setChanged()));
+ connect(prefWidget->isContainedBtn, SIGNAL(toggled(bool))
+ , this, SLOT(setChanged()));
+ connect(prefWidget->containsBtn, SIGNAL(toggled(bool))
+ , this, SLOT(setChanged()));
+ connect(prefWidget->hasWordBtn, SIGNAL(toggled(bool))
+ , this, SLOT(setChanged()));
+ connect(prefWidget->wholeBtn, SIGNAL(toggled(bool))
+ , this, SLOT(setChanged()));
+
+ connect(prefWidget->urlInput->lineEdit(),SIGNAL(textChanged(const QString&))
+ , this, SLOT(setChanged()));
+
+ connect(prefWidget->equalBtn, SIGNAL(toggled(bool))
+ , this, SLOT(equalBtnToggled(bool)));
+ connect(prefWidget->ngramBtn, SIGNAL(toggled(bool))
+ , this, SLOT(ngramBtnToggled(bool)));
+ connect(prefWidget->isContainedBtn, SIGNAL(toggled(bool))
+ , this, SLOT(isContainedBtnToggled(bool)));
+ connect(prefWidget->containsBtn, SIGNAL(toggled(bool))
+ , this, SLOT(containsBtnToggled(bool)));
+ connect(prefWidget->hasWordBtn, SIGNAL(toggled(bool))
+ , this, SLOT(hasWordBtnToggled(bool)));
+
+
+ QString whatsthis=i18n("<qt><p><b>Parameters</b></p>"
+ "<p>Here you can fine-tune searching within the PO file. "
+ "For example, if you want to perform a case sensitive search.</p></qt>" );
+ QWhatsThis::add(prefWidget->caseBtn,whatsthis);
+ QWhatsThis::add(prefWidget->wholeBtn,whatsthis);
+
+ whatsthis = i18n("<qt><p><b>Comparison Options</b></p>"
+ "<p>Choose here which messages you want to have treated as a matching "
+ "message.</p></qt>");
+ QWhatsThis::add(prefWidget->equalBtn,whatsthis);
+ QWhatsThis::add(prefWidget->containsBtn,whatsthis);
+ QWhatsThis::add(prefWidget->isContainedBtn,whatsthis);
+ QWhatsThis::add(prefWidget->hasWordBtn,whatsthis);
+
+ whatsthis = i18n("<qt><p><b>3-Gram-matching</b></p>"
+ "<p>A message matches another if most of its 3-letter groups are "
+ "contained in the other message. e.g. 'abc123' matches 'abcx123c12'.</p></qt>");
+ QWhatsThis::add(prefWidget->ngramBtn,whatsthis);
+
+ whatsthis = i18n("<qt><p><b>Location</b></p>"
+ "<p>Configure here which file is to be used for searching."
+ "</p></qt>");
+ QWhatsThis::add(prefWidget->urlInput,whatsthis);
+}
+
+TmxCompendiumPreferencesWidget::~TmxCompendiumPreferencesWidget()
+{
+}
+
+
+void TmxCompendiumPreferencesWidget::apply()
+{
+ emit applySettings();
+}
+
+void TmxCompendiumPreferencesWidget::cancel()
+{
+ emit restoreSettings();
+}
+
+void TmxCompendiumPreferencesWidget::standard()
+{
+ prefWidget->urlInput->setURL("http://i18n.kde.org/po_overview/@LANG@.messages");
+ prefWidget->caseBtn->setChecked(false);
+ prefWidget->equalBtn->setChecked(true);
+ prefWidget->ngramBtn->setChecked(true);
+ prefWidget->isContainedBtn->setChecked(false);
+ prefWidget->containsBtn->setChecked(false);
+ prefWidget->wholeBtn->setChecked(true);
+ prefWidget->hasWordBtn->setChecked(true);
+
+ changed=true;
+}
+
+void TmxCompendiumPreferencesWidget::setURL(const QString url)
+{
+ prefWidget->urlInput->setURL(url);
+ changed=false;
+}
+
+void TmxCompendiumPreferencesWidget::setCaseSensitive(bool on)
+{
+ prefWidget->caseBtn->setChecked(on);
+ changed=false;
+}
+
+void TmxCompendiumPreferencesWidget::setMatchEqual(bool on)
+{
+ prefWidget->equalBtn->setChecked(on);
+ changed=false;
+}
+
+void TmxCompendiumPreferencesWidget::setMatchNGram(bool on)
+{
+ prefWidget->ngramBtn->setChecked(on);
+ changed=false;
+}
+
+void TmxCompendiumPreferencesWidget::setMatchIsContained(bool on)
+{
+ prefWidget->isContainedBtn->setChecked(on);
+ changed=false;
+}
+
+void TmxCompendiumPreferencesWidget::setMatchContains(bool on)
+{
+ prefWidget->containsBtn->setChecked(on);
+ changed=false;
+}
+
+void TmxCompendiumPreferencesWidget::setWholeWords(bool on)
+{
+ prefWidget->wholeBtn->setChecked(on);
+ changed=false;
+}
+
+
+void TmxCompendiumPreferencesWidget::setMatchWords(bool on)
+{
+ prefWidget->hasWordBtn->setChecked(on);
+ changed=false;
+}
+
+
+
+QString TmxCompendiumPreferencesWidget::url()
+{
+ changed=false;
+ return prefWidget->urlInput->url();
+}
+
+bool TmxCompendiumPreferencesWidget::caseSensitive()
+{
+ changed=false;
+
+ return prefWidget->caseBtn->isChecked();
+}
+
+bool TmxCompendiumPreferencesWidget::matchEqual()
+{
+ changed=false;
+
+ return prefWidget->equalBtn->isChecked();
+}
+
+bool TmxCompendiumPreferencesWidget::matchNGram()
+{
+ changed=false;
+
+ return prefWidget->ngramBtn->isChecked();
+}
+
+bool TmxCompendiumPreferencesWidget::matchIsContained()
+{
+ changed=false;
+
+ return prefWidget->isContainedBtn->isChecked();
+}
+
+bool TmxCompendiumPreferencesWidget::matchContains()
+{
+ changed=false;
+
+ return prefWidget->containsBtn->isChecked();
+}
+
+bool TmxCompendiumPreferencesWidget::wholeWords()
+{
+ changed=false;
+
+ return prefWidget->wholeBtn->isChecked();
+}
+
+
+bool TmxCompendiumPreferencesWidget::matchWords()
+{
+ changed=false;
+
+ return prefWidget->hasWordBtn->isChecked();
+}
+
+
+
+bool TmxCompendiumPreferencesWidget::settingsChanged() const
+{
+ return changed;
+}
+
+void TmxCompendiumPreferencesWidget::setChanged()
+{
+ changed=true;
+}
+
+
+void TmxCompendiumPreferencesWidget::equalBtnToggled(bool on)
+{
+ if(!on)
+ {
+ if(!prefWidget->isContainedBtn->isChecked()
+ && !prefWidget->ngramBtn->isChecked()
+ && !prefWidget->containsBtn->isChecked()
+ && !prefWidget->hasWordBtn->isChecked())
+ {
+ prefWidget->equalBtn->setChecked(true);
+ }
+ }
+}
+
+void TmxCompendiumPreferencesWidget::ngramBtnToggled(bool on)
+{
+ if(!on)
+ {
+ if(!prefWidget->isContainedBtn->isChecked()
+ && !prefWidget->equalBtn->isChecked()
+ && !prefWidget->containsBtn->isChecked()
+ && !prefWidget->hasWordBtn->isChecked())
+ {
+ prefWidget->equalBtn->setChecked(true);
+ }
+ }
+}
+
+void TmxCompendiumPreferencesWidget::isContainedBtnToggled(bool on)
+{
+ if(!on)
+ {
+ if(!prefWidget->equalBtn->isChecked()
+ && !prefWidget->ngramBtn->isChecked()
+ && !prefWidget->containsBtn->isChecked()
+ && !prefWidget->hasWordBtn->isChecked())
+ {
+ prefWidget->isContainedBtn->setChecked(true);
+ }
+ }
+}
+
+void TmxCompendiumPreferencesWidget::containsBtnToggled(bool on)
+{
+ if(!on)
+ {
+ if(!prefWidget->isContainedBtn->isChecked()
+ && !prefWidget->ngramBtn->isChecked()
+ && !prefWidget->equalBtn->isChecked()
+ && !prefWidget->hasWordBtn->isChecked())
+ {
+ prefWidget->containsBtn->setChecked(true);
+ }
+ }
+}
+
+void TmxCompendiumPreferencesWidget::hasWordBtnToggled(bool on)
+{
+ if(!on)
+ {
+ if(!prefWidget->isContainedBtn->isChecked()
+ && !prefWidget->ngramBtn->isChecked()
+ && !prefWidget->equalBtn->isChecked()
+ && !prefWidget->containsBtn->isChecked())
+ {
+ prefWidget->hasWordBtn->setChecked(true);
+ }
+ }
+}
+
+
+
+#include "preferenceswidget.moc"
diff --git a/kbabel/kbabeldict/modules/tmx/preferenceswidget.h b/kbabel/kbabeldict/modules/tmx/preferenceswidget.h
new file mode 100644
index 00000000..c8356c3d
--- /dev/null
+++ b/kbabel/kbabeldict/modules/tmx/preferenceswidget.h
@@ -0,0 +1,97 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2002 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#ifndef PREFERENCESWIDGET_H
+#define PREFERENCESWIDGET_H
+
+#include "searchengine.h"
+
+class TmxCompendiumPWidget;
+
+class TmxCompendiumPreferencesWidget : public PrefWidget
+{
+ Q_OBJECT
+
+public:
+ TmxCompendiumPreferencesWidget(QWidget *parent=0, const char* name=0);
+ virtual ~TmxCompendiumPreferencesWidget();
+
+ virtual void apply();
+ virtual void cancel();
+ virtual void standard();
+
+ void setURL(const QString url);
+ void setMatchEqual(bool);
+ void setMatchNGram(bool);
+ void setMatchIsContained(bool);
+ void setMatchContains(bool);
+ void setMatchWords(bool);
+ void setWholeWords(bool);
+ void setCaseSensitive(bool);
+
+ QString url();
+ bool matchEqual();
+ bool matchNGram();
+ bool matchIsContained();
+ bool matchContains();
+ bool matchWords();
+ bool wholeWords();
+ bool caseSensitive();
+
+
+ bool settingsChanged() const;
+
+signals:
+ void restoreSettings();
+ void applySettings();
+
+public:
+ TmxCompendiumPWidget *prefWidget;
+
+protected slots:
+ void setChanged();
+ void equalBtnToggled(bool);
+ void ngramBtnToggled(bool);
+ void isContainedBtnToggled(bool);
+ void containsBtnToggled(bool);
+ void hasWordBtnToggled(bool);
+
+private:
+ bool changed;
+
+};
+
+#endif
diff --git a/kbabel/kbabeldict/modules/tmx/pwidget.ui b/kbabel/kbabeldict/modules/tmx/pwidget.ui
new file mode 100644
index 00000000..ef6c9967
--- /dev/null
+++ b/kbabel/kbabeldict/modules/tmx/pwidget.ui
@@ -0,0 +1,216 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>TmxCompendiumPWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>TMXPWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>452</width>
+ <height>291</height>
+ </rect>
+ </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>GroupBox1</cstring>
+ </property>
+ <property name="title">
+ <string>&amp;Path to Compendium File</string>
+ </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="KURLRequester">
+ <property name="name">
+ <cstring>urlInput</cstring>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>ButtonGroup1</cstring>
+ </property>
+ <property name="title">
+ <string>Options</string>
+ </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="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout4</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QCheckBox" row="0" column="1">
+ <property name="name">
+ <cstring>wholeBtn</cstring>
+ </property>
+ <property name="text">
+ <string>Onl&amp;y whole words</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="0" column="0">
+ <property name="name">
+ <cstring>caseBtn</cstring>
+ </property>
+ <property name="text">
+ <string>Case sensiti&amp;ve</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>A text matches if:</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout3</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QCheckBox" row="0" column="0">
+ <property name="name">
+ <cstring>equalBtn</cstring>
+ </property>
+ <property name="text">
+ <string>E&amp;qual to searched text</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="1">
+ <property name="name">
+ <cstring>hasWordBtn</cstring>
+ </property>
+ <property name="text">
+ <string>Contains a &amp;word of searched text</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="1">
+ <property name="name">
+ <cstring>isContainedBtn</cstring>
+ </property>
+ <property name="text">
+ <string>Co&amp;ntained in searched text</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="0">
+ <property name="name">
+ <cstring>ngramBtn</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Similar to searched text</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="0" column="1">
+ <property name="name">
+ <cstring>containsBtn</cstring>
+ </property>
+ <property name="text">
+ <string>Contains searched te&amp;xt</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </vbox>
+ </widget>
+ <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>20</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>KURLRequester</class>
+ <header location="global">kurlrequester.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="XPM.GZ" length="646">789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758</data>
+ </image>
+</images>
+<tabstops>
+ <tabstop>caseBtn</tabstop>
+</tabstops>
+<includes>
+ <include location="global" impldecl="in declaration">kseparator.h</include>
+</includes>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kurlrequester.h</includehint>
+</includehints>
+</UI>
diff --git a/kbabel/kbabeldict/modules/tmx/tmxcompendium.cpp b/kbabel/kbabeldict/modules/tmx/tmxcompendium.cpp
new file mode 100644
index 00000000..152bc536
--- /dev/null
+++ b/kbabel/kbabeldict/modules/tmx/tmxcompendium.cpp
@@ -0,0 +1,1007 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2002 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include <klocale.h>
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <kstaticdeleter.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kinstance.h>
+#include <kio/netaccess.h>
+
+#include <qtextstream.h>
+#include <qtimer.h>
+
+#include "tmxcompendiumdata.h"
+#include "tmxcompendium.h"
+#include "preferenceswidget.h"
+#include "pc_factory.h"
+
+#include <catalogitem.h>
+
+// ngram length and minimal matching for fuzzy search
+#define NGRAM_LEN 3
+#define LIM_NGRAM 50
+
+static KStaticDeleter< QDict<TmxCompendiumData> > compDataDeleter;
+QDict<TmxCompendiumData> *TmxCompendium::_compDict = 0;
+
+TmxCompendium::TmxCompendium(QObject *parent, const char *name)
+ : SearchEngine(parent, name)
+{
+ prefWidget=0;
+ data=0;
+ error=false;
+ stop=false;
+ active=false;
+ initialized=false;
+ loading=false;
+
+ langCode = KGlobal::locale()->language();
+
+ caseSensitive = false;
+ wholeWords=true;
+
+ matchEqual = true;
+ matchNGram = true;
+ matchIsContained = false;
+ matchContains = true;
+ matchWords=true;
+
+
+ loadTimer = new QTimer(this);
+ connect(loadTimer,SIGNAL(timeout()),this,SLOT(slotLoadCompendium()));
+}
+
+TmxCompendium::~TmxCompendium()
+{
+ if(isSearching())
+ {
+ stopSearch();
+ }
+
+ unregisterData();
+}
+
+bool TmxCompendium::isReady() const
+{
+ return (isSearching() || !error);
+}
+
+
+bool TmxCompendium::isSearching() const
+{
+ return (active || loading);
+}
+
+
+void TmxCompendium::saveSettings(KConfigBase *config)
+{
+ if(autoUpdate && prefWidget && prefWidget->settingsChanged())
+ {
+ applySettings();
+ }
+
+ config->writeEntry("CaseSensitive",caseSensitive);
+ config->writeEntry("WholeWords", wholeWords);
+
+ config->writeEntry("MatchEqual", matchEqual);
+ config->writeEntry("MatchIsContained",matchIsContained);
+ config->writeEntry("MatchContains", matchContains);
+ config->writeEntry("MatchWords", matchWords);
+ config->writeEntry("MatchNGram", matchNGram);
+
+ config->writeEntry("Compendium", url);
+}
+
+void TmxCompendium::readSettings(KConfigBase *config)
+{
+ caseSensitive = config->readBoolEntry("CaseSensitive", false);
+ wholeWords = config->readBoolEntry("WholeWords",true);
+
+ matchEqual = config->readBoolEntry("MatchEqual", true);
+ matchIsContained = config->readBoolEntry("MatchIsContained", false);
+ matchContains = config->readBoolEntry("MatchContains",true);
+ matchWords = config->readBoolEntry("MatchWords",true);
+ matchNGram = config->readBoolEntry("MatchNGram",true);
+
+ QString newPath = config->readEntry("Compendium","http://i18n.kde.org/po_overview/@LANG@.messages");
+ if(!initialized)
+ {
+ url = newPath;
+ }
+ else if(newPath != url)
+ {
+ url = newPath;
+ loadCompendium();
+ }
+
+
+ restoreSettings();
+}
+
+PrefWidget *TmxCompendium::preferencesWidget(QWidget *parent)
+{
+ prefWidget = new TmxCompendiumPreferencesWidget(parent,"tmxcompendium_prefwidget");
+ connect(prefWidget, SIGNAL(applySettings()), this, SLOT(applySettings()));
+ connect(prefWidget, SIGNAL(restoreSettings())
+ , this, SLOT(restoreSettings()));
+
+ restoreSettings();
+
+ return prefWidget;
+}
+
+const KAboutData *TmxCompendium::about() const
+{
+ return PcFactory::instance()->aboutData();
+}
+
+
+QString TmxCompendium::name() const
+{
+ return i18n("TMX Compendium");
+}
+
+QString TmxCompendium::id() const
+{
+ return "tmxcompendium";
+}
+
+QString TmxCompendium::lastError()
+{
+ return errorMsg;
+}
+
+
+bool TmxCompendium::startSearch(const QString& text, uint pluralForm, const SearchFilter*)
+{
+ if(autoUpdate && prefWidget && prefWidget->settingsChanged())
+ {
+ applySettings();
+ }
+
+ if(isSearching())
+ return false;
+
+ clearResults();
+ stop = false;
+ active = true;
+
+ if(!initialized)
+ {
+ if(loadTimer->isActive())
+ loadTimer->stop();
+
+ slotLoadCompendium();
+ }
+
+ if(error || !data)
+ {
+ active = false;
+ return false;
+ }
+
+ if(data->active())
+ {
+ active = false;
+ return true;
+ }
+
+ emit started();
+
+
+ QValueList<int> foundIndices;
+ QValueList<int> checkedIndices;
+ uint checkCounter=0;
+
+ const int *index = data->exactDict(text);
+ if(index)
+ {
+ foundIndices.append(*index);
+
+ SearchResult *result = new SearchResult;
+ result->requested = text;
+ result->found = data->msgid(*index);
+ result->translation = data->msgstr(*index);
+ result->score = 100;
+
+ TranslationInfo *info = new TranslationInfo;
+ info->location = directory(realURL,0);
+ info->translator = QString::null;
+ info->description = QString::null;
+ result->descriptions.append(info);
+
+ results.append(result);
+
+ emit numberOfResultsChanged(results.count());
+ emit resultFound(result);
+ }
+
+ QString searchStr=TmxCompendiumData::simplify(text);
+
+
+ if(!caseSensitive)
+ {
+ searchStr = searchStr.lower();
+ }
+
+ QString temp = searchStr;
+ temp = temp.lower();
+
+ const QValueList<int> *indexList = data->allDict(temp);
+ if(indexList)
+ {
+ QValueList<int>::ConstIterator it;
+ for( it = indexList->begin(); it != indexList->end(); ++it )
+ {
+ if(foundIndices.contains(*it))
+ {
+ continue;
+ }
+
+ QString origStr = data->msgid(*it);
+ origStr = TmxCompendiumData::simplify(origStr);
+
+
+ if(!caseSensitive)
+ {
+ origStr = origStr.lower();
+ }
+
+ if(origStr==searchStr)
+ {
+ foundIndices.append(*it);
+
+ SearchResult *result = new SearchResult;
+ result->requested = text;
+ result->found = data->msgid(*it);
+ result->translation = data->msgstr(*it);
+ // FIXME: handle plural forms properly
+ result->score = score(result->requested,result->found.first());
+
+ TranslationInfo *info = new TranslationInfo;
+ info->location = directory(realURL,0);
+ info->translator = QString::null;
+ info->description = QString::null;
+ result->descriptions.append(info);
+
+ addResult(result);
+ }
+ }
+ }
+
+ QStringList wList = TmxCompendiumData::wordList(searchStr);
+ for ( QStringList::Iterator wit = wList.begin()
+ ; wit != wList.end(); ++wit )
+ {
+ if(stop)
+ break;
+
+ indexList = data->wordDict((*wit).lower());
+ if(indexList)
+ {
+ QValueList<int>::ConstIterator it;
+ for( it = indexList->begin(); it != indexList->end(); ++it )
+ {
+ if(stop)
+ break;
+
+ if(foundIndices.contains(*it))
+ {
+ continue;
+ }
+
+ if(checkedIndices.contains(*it))
+ {
+ continue;
+ }
+
+ checkedIndices.append(*it);
+ checkCounter++;
+
+ if( (100*(checkCounter+1))%data->numberOfEntries() < 100)
+ {
+ emit progress( (100*(checkCounter+1))/data->numberOfEntries());
+ }
+
+ kapp->processEvents(100);
+
+ QString origStr = data->msgid(*it);
+ origStr = TmxCompendiumData::simplify(origStr);
+
+
+ if(!caseSensitive)
+ {
+ origStr = origStr.lower();
+ }
+
+ bool found = false;
+ if(matchWords)
+ {
+ if(!caseSensitive)
+ {
+ found=true;
+ }
+ else
+ {
+ QString s=*wit;
+ QString o=origStr;
+
+ if(wholeWords)
+ {
+ s=" "+*wit+" ";
+ o=" "+origStr+" ";
+ }
+ if(o.contains(s))
+ {
+ found=true;
+ }
+ }
+ }
+
+
+ if(!found && origStr==searchStr)
+ {
+ found =true;
+ }
+
+ // if there is an string which just contains ignored characters,
+ // continue
+ if(!found && origStr.isEmpty() ||
+ (origStr.length() == 1 && text.length() > 1))
+ {
+ continue;
+ }
+
+
+ if(!found && matchContains && !wholeWords)
+ {
+ QString s=maskString(searchStr);
+ QRegExp searchReg(s);
+
+ if(searchReg.search(origStr) >= 0)
+ found=true;
+ }
+
+ if(!found && matchIsContained && !wholeWords)
+ {
+ QString s=maskString(origStr);
+ QRegExp reg(s);
+
+ if(reg.search(searchStr) >= 0)
+ {
+ found = true;
+ }
+ }
+ if(!found && matchWords && !wholeWords)
+ {
+ QStringList list = TmxCompendiumData::wordList(searchStr);
+
+ for ( QStringList::Iterator wit2 = list.begin()
+ ; wit2 != list.end(); ++wit2 )
+ {
+ QString s=maskString(*wit2);
+ QRegExp reg(s);
+
+ if(reg.search(origStr) >= 0)
+ {
+ found = true;
+ }
+ }
+ }
+
+ if(found)
+ {
+ foundIndices.append(*it);
+
+ SearchResult *result = new SearchResult;
+ result->requested = text;
+ result->found = data->msgid(*it);
+ result->translation = data->msgstr(*it);
+ // FIXME: handle plural forms properly
+ result->score = score(result->requested,(result->found.first()));
+
+ TranslationInfo *info = new TranslationInfo;
+ info->location = directory(realURL,0);
+ info->translator = QString::null;
+ info->description = QString::null;
+ result->descriptions.append(info);
+
+ addResult(result);
+ }
+ }
+ }
+ }
+
+
+ if( matchNGram ||
+ (!wholeWords && (matchContains || matchIsContained || matchWords))
+ )
+ {
+ QRegExp searchReg;
+ if(matchContains)
+ {
+ QString s=maskString(searchStr);
+ searchReg.setPattern(s);
+ }
+
+
+ bool breakLoop=false;
+ int i=-1;
+ while(!breakLoop)
+ {
+ if(stop)
+ {
+ breakLoop=true;
+ break;
+ }
+
+ i++;
+
+ if(checkedIndices.contains(i))
+ {
+ continue;
+ }
+
+ checkedIndices.append(i);
+ checkCounter++;
+
+ if(foundIndices.contains(i))
+ {
+ continue;
+ }
+
+ kapp->processEvents(100);
+
+ if(i >= data->numberOfEntries())
+ {
+ breakLoop = true;
+ break;
+ }
+
+ if( (100*(checkCounter+1))%data->numberOfEntries() < 100)
+ {
+ emit progress( (100*(checkCounter+1))/data->numberOfEntries());
+ }
+
+ QString origStr = data->msgid(i);
+ origStr = TmxCompendiumData::simplify(origStr);
+
+ if(!caseSensitive)
+ {
+ origStr = origStr.lower();
+ }
+
+
+ // if there is an string which just contains ignored characters,
+ // continue
+ if(origStr.isEmpty() ||
+ (origStr.length() == 1 && text.length() > 1))
+ {
+ continue;
+ }
+
+ bool found = false;
+ if(matchContains && searchReg.search(origStr) >= 0)
+ {
+ found=true;
+ }
+
+
+ if(!found && matchIsContained)
+ {
+ QString s=maskString(origStr);
+ QRegExp reg(s);
+
+ if(reg.search(searchStr) >= 0)
+ {
+ found = true;
+ }
+ }
+ if(!found && matchWords)
+ {
+ QStringList list = TmxCompendiumData::wordList(searchStr);
+
+ for ( QStringList::Iterator wit2 = list.begin()
+ ; wit2 != list.end(); ++wit2 )
+ {
+ QString s=maskString(*wit2);
+
+ if(wholeWords)
+ {
+ origStr = " "+origStr+" ";
+ s=" "+s+" ";
+ }
+ QRegExp reg(s);
+
+ if(reg.search(origStr) >= 0)
+ {
+ found = true;
+ }
+ }
+ }
+
+ if(!found && matchNGram)
+ {
+ // to get more results one could
+ // interchange searchStr and origStr when
+ // the latter is shorter
+
+ found = ( ngramMatch(searchStr,origStr,NGRAM_LEN)
+ > LIM_NGRAM );
+ }
+
+ if(found)
+ {
+ foundIndices.append(i);
+
+ SearchResult *result = new SearchResult;
+ result->requested = text;
+ result->found = data->msgid(i);
+ result->translation = data->msgstr(i);
+ // FIXME: handle plural forms properly
+ result->score = score(result->requested,(result->found.first()));
+
+ TranslationInfo *info = new TranslationInfo;
+ info->location = directory(realURL,0);
+ info->translator = QString::null;
+ info->description = QString::null;
+ result->descriptions.append(info);
+
+ addResult(result);
+ }
+ }
+ }
+
+ if( (100*(checkCounter+1))/data->numberOfEntries() < 100 && !stop)
+ {
+ for(int i=(100*(checkCounter+1))/data->numberOfEntries(); i<=100; i++)
+ {
+ emit progress(i);
+ }
+ }
+
+
+ active = false;
+ stop = false;
+ emit finished();
+
+ return true;
+}
+
+void TmxCompendium::stopSearch()
+{
+ stop=true;
+}
+
+
+void TmxCompendium::applySettings()
+{
+ if(!prefWidget)
+ return;
+
+ if(isSearching())
+ stopSearch();
+
+ caseSensitive = prefWidget->caseSensitive();
+ wholeWords = prefWidget->wholeWords();
+
+ matchEqual = prefWidget->matchEqual();
+ matchNGram = prefWidget->matchNGram();
+ matchIsContained = prefWidget->matchIsContained();
+ matchContains = prefWidget->matchContains();
+ matchWords = prefWidget->matchWords();
+
+
+ bool needLoading=false;
+
+
+ QString newPath = prefWidget->url();
+ if(!initialized)
+ {
+ url = newPath;
+ }
+ else if(newPath != url)
+ {
+ url = newPath;
+ needLoading = true;
+ }
+
+ if(needLoading)
+ {
+ loadCompendium();
+ initialized=false;
+ }
+}
+
+void TmxCompendium::restoreSettings()
+{
+ if(!prefWidget)
+ return;
+
+ prefWidget->setCaseSensitive(caseSensitive);
+ prefWidget->setWholeWords(wholeWords);
+ prefWidget->setURL(url);
+
+ prefWidget->setMatchEqual(matchEqual);
+ prefWidget->setMatchNGram(matchNGram);
+ prefWidget->setMatchIsContained(matchIsContained);
+ prefWidget->setMatchContains(matchContains);
+ prefWidget->setMatchWords(matchWords);
+}
+
+void TmxCompendium::loadCompendium()
+{
+ if(!loading && !loadTimer->isActive())
+ loadTimer->start(100,true);
+}
+
+void TmxCompendium::slotLoadCompendium()
+{
+ if(loading)
+ return;
+
+ if(loadTimer->isActive())
+ loadTimer->stop();
+
+ loading = true;
+
+ if(data)
+ {
+ unregisterData();
+ }
+
+
+ QString path=url;
+
+ if(path.contains("@LANG@"))
+ {
+ path.replace("@LANG@",langCode);
+ }
+ KURL u=KCmdLineArgs::makeURL(path.local8Bit());
+ realURL = u.url();
+
+ registerData();
+
+
+ if(!data)
+ {
+ kdError() << "no data object in tmxcompendium?" << endl;
+
+ loading=false;
+ return;
+ }
+
+ if(!data->initialized())
+ {
+ if(!data->active())
+ {
+ data->load(u,langCode);
+ recheckData();
+ if(error)
+ {
+ emit hasError(errorMsg);
+ }
+ }
+ else
+ {
+ connect(data, SIGNAL(progressEnds()), this, SLOT(recheckData()));
+ }
+ }
+ else
+ {
+ recheckData();
+ if(error)
+ {
+ emit hasError(errorMsg);
+ }
+ }
+
+ initialized=true;
+}
+
+void TmxCompendium::recheckData()
+{
+ if(data)
+ {
+ disconnect(data, SIGNAL(progressEnds()), this, SLOT(recheckData()));
+
+ error = data->hasErrors();
+ errorMsg = data->errorMsg();
+ }
+
+ loading=false;
+}
+
+QString TmxCompendium::maskString(QString s) const
+{
+ s.replace('\\',"\\\\");
+ s.replace('?',"\\?");
+ s.replace('[',"\\[");
+ s.replace('.',"\\.");
+ s.replace('*',"\\*");
+ s.replace('+',"\\+");
+ s.replace('^',"\\^");
+ s.replace('$',"\\$");
+ s.replace('(',"\\(");
+ s.replace(')',"\\)");
+ s.replace('{',"\\{");
+ s.replace('}',"\\}");
+ s.replace('|',"\\|");
+
+ return s;
+}
+
+void TmxCompendium::addResult(SearchResult *result)
+{
+ if(results.last() && results.last()->score >= result->score)
+ {
+ results.append(result);
+ }
+ else
+ {
+ SearchResult *sr;
+ for(sr = results.first(); sr != 0; sr=results.next())
+ {
+ if(sr->score < result->score)
+ {
+ results.insert(results.at(),result);
+ emit resultsReordered();
+ break;
+ }
+ }
+
+ if(!sr)
+ {
+ results.append(result);
+ }
+ }
+
+ emit numberOfResultsChanged(results.count());
+ emit resultFound(result);
+}
+
+
+void TmxCompendium::setLanguageCode(const QString& lang)
+{
+ if(initialized && url.contains("@LANG@") && lang!=langCode
+ && !loadTimer->isActive() )
+ {
+ initialized=false;
+ }
+
+ langCode=lang;
+}
+
+QString TmxCompendium::translate(const QString& text, uint pluralForm)
+{
+ if(!initialized)
+ {
+ if(loadTimer->isActive())
+ loadTimer->stop();
+
+ slotLoadCompendium();
+ }
+
+ if(error || !data || data->active())
+ {
+ return QString::null;
+ }
+
+
+ const int *index = data->exactDict(text);
+
+ if(index)
+ {
+ return data->msgstr(*index);
+ }
+
+ return QString::null;
+}
+
+QString TmxCompendium::fuzzyTranslation(const QString& text, int &score, uint pluralForm)
+{
+ if(!initialized)
+ {
+ if(loadTimer->isActive())
+ loadTimer->stop();
+
+ slotLoadCompendium();
+ }
+
+ if(error || !data || data->active())
+ {
+ return QString::null;
+ }
+
+ // try to find fuzzy string
+ bool breakLoop = false;
+ stop = false;
+ int i=-1;
+ int best_matching = -1;
+ int best_match = 0;
+ int total = data->numberOfEntries();
+
+ QString searchStr = TmxCompendiumData::simplify(text);
+
+ //kdDebug(750) << "find best match for " << searchStr << endl;
+
+ while(!breakLoop)
+ {
+
+ // progress and loop control
+ if(stop)
+ {
+ breakLoop=true;
+ break;
+ }
+
+ i++;
+
+ if(i >= total)
+ {
+ breakLoop = true;
+ break;
+ }
+
+ if( (100*(i+1))%total < 100)
+ {
+ emit progress( (100*(i+1))/total);
+ }
+
+ // get a message from the catalog
+ QString origStr = data->msgid(i);
+ origStr = TmxCompendiumData::simplify(origStr);
+
+ // don't match too long strings for short search string
+ if (origStr.length() > 2*searchStr.length())
+ continue;
+ // kdDebug(750) << i << ": matching " << origStr << endl;
+
+ int ngram_result = ngramMatch(searchStr,origStr);
+
+ if (ngram_result > best_match) {
+ best_match = ngram_result;
+ best_matching = i;
+
+ // kdDebug(750) << "[" << ngram_result << "] " << text << "-"
+ // << origStr << endl;
+ }
+ }
+
+ if (best_match > LIM_NGRAM) {
+ score = best_match;
+ return data->msgstr(best_matching);
+ }
+
+ return QString::null;
+}
+
+
+void TmxCompendium::unregisterData()
+{
+ if(data)
+ {
+ disconnect(data, SIGNAL(progressStarts(const QString&)), this
+ , SIGNAL(progressStarts(const QString&)));
+ disconnect(data, SIGNAL(progressEnds()), this , SIGNAL(progressEnds()));
+ disconnect(data, SIGNAL(progress(int)), this , SIGNAL(progress(int)));
+
+ if(data->active())
+ {
+ disconnect(data,SIGNAL(progressEnds()),this,SLOT(recheckData()));
+ }
+
+ if(data->unregisterObject(this))
+ {
+ if(!data->active())
+ {
+ compendiumDict()->remove(realURL);
+ }
+ else
+ {
+ connect(data,SIGNAL(progressEnds()),this,SLOT(removeData()));
+ }
+ }
+
+ data=0;
+ }
+}
+
+void TmxCompendium::registerData()
+{
+ data = compendiumDict()->find(realURL);
+ if(!data)
+ {
+ data = new TmxCompendiumData;
+ compendiumDict()->insert(realURL,data);
+ }
+
+ data->registerObject(this);
+
+ if(data->active())
+ {
+ emit progressStarts(i18n("Loading PO compendium"));
+ }
+
+ connect(data, SIGNAL(progressStarts(const QString&)), this
+ , SIGNAL(progressStarts(const QString&)));
+ connect(data, SIGNAL(progressEnds()), this , SIGNAL(progressEnds()));
+ connect(data, SIGNAL(progress(int)), this , SIGNAL(progress(int)));
+}
+
+void TmxCompendium::removeData()
+{
+ const QObject *s=sender();
+ if(s && s->inherits("TmxCompendiumData"))
+ {
+ const TmxCompendiumData *d=static_cast<const TmxCompendiumData*>(s);
+ if(d)
+ {
+ QDictIterator<TmxCompendiumData> it(*compendiumDict());
+ while(it.current())
+ {
+ if(it.current() == d)
+ {
+ if(!d->hasObjects())
+ {
+ compendiumDict()->remove(it.currentKey());
+ }
+
+ break;
+ }
+
+ ++it;
+ }
+ }
+
+ }
+}
+
+QDict<TmxCompendiumData> *TmxCompendium::compendiumDict()
+{
+ if(!_compDict)
+ {
+ _compDict=compDataDeleter.setObject( new QDict<TmxCompendiumData> );
+ _compDict->setAutoDelete(true);
+ }
+
+ return _compDict;
+}
+
+
+
+#include "tmxcompendium.moc"
diff --git a/kbabel/kbabeldict/modules/tmx/tmxcompendium.desktop b/kbabel/kbabeldict/modules/tmx/tmxcompendium.desktop
new file mode 100644
index 00000000..cae7d333
--- /dev/null
+++ b/kbabel/kbabeldict/modules/tmx/tmxcompendium.desktop
@@ -0,0 +1,50 @@
+[Desktop Entry]
+Type=Service
+Name=TMX Compendium Module for KBabelDict
+Name[bg]=TMX компендиум за KBabelDict
+Name[bs]=Modul TMX kompendijuma za KBabelDict
+Name[ca]=Mòdul del Compendi TMX per a KBabelDict
+Name[cs]=Modul s TMX kompendiem pro KBabelDict
+Name[cy]=Modiwl Compendiwm TMX i KBabelDict
+Name[da]=TMX kompendium-module for KBabelDict
+Name[de]=TMX-Kompendium-Modul für KBabelDict
+Name[el]=ΆÏθÏωμα επιτομής TMX για το KBabelDict
+Name[es]=Módulo de compendio TMX para KBabelDict
+Name[et]=KBabelDicti TMX kompendiumi moodul
+Name[eu]=TMX laburpen modulua KBabelDict-entzat
+Name[fa]=پیمانۀ مختصر TMX برای KBabelDict
+Name[fi]=KBabelDict-ohjelman TMX-kokoelmatiedostomoduuli
+Name[fr]=Module de fichier de référence des TMX pour KBabelDict
+Name[gl]=Módulo de compendio TMX para KBabelDict
+Name[hi]=के-बेबल-डिकà¥à¤¶ के लिठटीà¤à¤®à¤à¤•à¥à¤¸ कमà¥à¤ªà¥‡à¤‚डियम मॉडà¥à¤¯à¥‚ल
+Name[hu]=TMX összefoglaló modul a KBabelDicthez
+Name[is]=TMX ágrips eining fyrir KBabel orðabókina
+Name[it]=Modulo TMX Compendium per KBabelDict
+Name[ja]=KBabelDict TMX è¦ç´„モジュール
+Name[ka]=TMX კáƒáƒœáƒ¡áƒžáƒ”ქტის მáƒáƒ“ული KBabelDict-სთვის
+Name[kk]=KBabelDict-тың TMX аудармалар жиынтық модулі
+Name[lt]=KBabelDict TMX tekstyno modulis
+Name[ms]=Modul Kompendium TMX untuk KBabelDict
+Name[nb]=TMX-kompendium-modul for KBabelDict
+Name[nds]=TMX-Kompendiummoduul för KBabelDict
+Name[ne]=KBabelDict का लागि टीà¤à¤®à¤à¤•à¥à¤¸ संकà¥à¤·à¥‡à¤ª मोडà¥à¤¯à¥à¤²
+Name[nl]=TMX-samenvattingmodule voor KBabelDict
+Name[nn]=TMX-kompendiemodul for KBabelDict
+Name[pa]=ਕੇਬਬੇਲ-ਸ਼ਬਦਕੋਸ਼ ਲਈ TMX ਅਨà©à¨µà¨¾à¨¦ ਮੈਡੀਊਲ
+Name[pl]=Moduł Kompendium TMX dla KBabelDict
+Name[pt]=Módulo de Compêndio de TMX para o KBabelDict
+Name[pt_BR]=Módulo de Compêndio TMX para o KBabelDict
+Name[ru]=Модуль опиÑÐ°Ð½Ð¸Ñ TMX Ð´Ð»Ñ KBabelDict
+Name[sk]=TMX kompendium pre KBabelDict
+Name[sl]=Modul zbornika TMX za KBabelDict
+Name[sr]=Модул TMX зборника за KBabelDict
+Name[sr@Latn]=Modul TMX zbornika za KBabelDict
+Name[sv]=TMX-kompendiemodul för Kbabeldict
+Name[ta]=Kபாபேலà¯à®•à¯à®•à®¾à®© காமà¯à®ªà¯†à®©à¯à®Ÿà®¿à®¯à®®à¯ TMX கூறà¯
+Name[tg]=Модули таÑвири TMX барои KBabelDict
+Name[tr]=KBabelDict için TMX Özet Modülü
+Name[uk]=Модуль збірки перекладів TMX Ð´Ð»Ñ KBabelDict
+Name[zh_CN]=KBabelDict çš„ TMX 概è¦è¯å…¸æ¨¡å—
+Name[zh_TW]=KBabelDict TMX 摘è¦æ¨¡çµ„
+X-KDE-Library=kbabeldict_tmxcompendium
+ServiceTypes=KBabelDictModule
diff --git a/kbabel/kbabeldict/modules/tmx/tmxcompendium.h b/kbabel/kbabeldict/modules/tmx/tmxcompendium.h
new file mode 100644
index 00000000..9a2f8fba
--- /dev/null
+++ b/kbabel/kbabeldict/modules/tmx/tmxcompendium.h
@@ -0,0 +1,137 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2002 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#ifndef TMXCOMPENDIUM_H
+#define TMXCOMPENDIUM_H
+
+#include "tmxcompendiumdata.h"
+#include "searchengine.h"
+
+#include <qdict.h>
+#include <qfile.h>
+#include <qguardedptr.h>
+
+class TmxCompendiumPreferencesWidget;
+class KConfigBase;
+class QTimer;
+
+class TmxCompendium : public SearchEngine
+{
+ Q_OBJECT
+
+public:
+ TmxCompendium(QObject *parent=0, const char *name=0);
+ virtual ~TmxCompendium();
+
+ virtual bool isReady() const;
+
+ virtual QString translate(const QString& text, uint pluralForm);
+ virtual QString fuzzyTranslation(const QString& text, int &score, uint pluralForm);
+
+ virtual bool isSearching() const;
+
+ virtual void saveSettings(KConfigBase *config);
+ virtual void readSettings(KConfigBase *config);
+
+ virtual PrefWidget *preferencesWidget(QWidget *parent);
+
+ virtual const KAboutData *about() const;
+
+ virtual QString name() const;
+
+ virtual QString id() const;
+
+ virtual QString lastError();
+
+
+public slots:
+ virtual bool startSearch(const QString& text, uint pluralForm, const SearchFilter* filter);
+ virtual void stopSearch();
+ virtual void setLanguageCode(const QString& lang);
+
+protected slots:
+ /** reads the current settings from the preferences dialog */
+ void applySettings();
+
+ /** sets the current settings in the preferences dialog */
+ void restoreSettings();
+
+ void slotLoadCompendium();
+
+ void recheckData();
+ void removeData();
+
+protected:
+ void loadCompendium();
+ void addResult(SearchResult *);
+ QString maskString(QString string) const;
+
+ void registerData();
+ void unregisterData();
+
+private:
+ QGuardedPtr<TmxCompendiumPreferencesWidget> prefWidget;
+ TmxCompendiumData *data;
+ QTimer *loadTimer;
+
+ QString url;
+ QString realURL;
+ QString langCode;
+
+ bool caseSensitive;
+ bool wholeWords;
+
+ bool matchEqual;
+ bool matchIsContained;
+ bool matchContains;
+ bool matchWords;
+ bool matchNGram;
+
+ bool buildIndex;
+ uint freeMemDelay;
+
+ bool error;
+ QString errorMsg;
+
+ bool stop;
+ bool active;
+ bool initialized;
+ bool loading;
+
+ static QDict<TmxCompendiumData> *_compDict;
+ static QDict<TmxCompendiumData> *compendiumDict();
+};
+
+#endif
diff --git a/kbabel/kbabeldict/modules/tmx/tmxcompendiumdata.cpp b/kbabel/kbabeldict/modules/tmx/tmxcompendiumdata.cpp
new file mode 100644
index 00000000..3fa84aa4
--- /dev/null
+++ b/kbabel/kbabeldict/modules/tmx/tmxcompendiumdata.cpp
@@ -0,0 +1,308 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2001 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2002 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#include "tmxcompendiumdata.h"
+
+#include <qdom.h>
+#include <qfile.h>
+
+#include <tagextractor.h>
+#include <resources.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kio/netaccess.h>
+
+using namespace KBabel;
+
+TmxCompendiumData::TmxCompendiumData(QObject *parent)
+ : QObject(parent)
+ , _active(false)
+ , _error(false)
+ , _initialized(false)
+ , _exactDict(9887)
+ , _allDict(9887)
+ , _wordDict(9887)
+{
+ _exactDict.setAutoDelete(true);
+ _allDict.setAutoDelete(true);
+ _wordDict.setAutoDelete(true);
+}
+
+
+bool TmxCompendiumData::load(const KURL& url, const QString& language)
+{
+ kdDebug(KBABEL_SEARCH) << "Load " << url.url() << " in " << language << endl;
+ if(_active)
+ return false;
+
+
+ _error = false;
+ _active = true;
+
+ _exactDict.clear();
+ _allDict.clear();
+ _wordDict.clear();
+
+
+ emit progressStarts(i18n("Loading TMX compendium"));
+
+ QDomDocument doc( "mydocument" );
+
+ QString target;
+
+ if( KIO::NetAccess::download( url, target ) )
+ {
+ QFile f( target );
+ if ( !f.open( IO_ReadOnly ) )
+ {
+ _error = true;
+ _errorMsg = i18n( "Cannot open the file." );
+ }
+ else if ( !doc.setContent( &f ) ) {
+ _error = true;
+ _errorMsg = i18n( "Cannot parse XML data." );
+ }
+ f.close();
+ KIO::NetAccess::removeTempFile(target);
+ } else {
+ _error = true;
+ _errorMsg = i18n( "Cannot open the file." );
+ }
+
+ QDomElement docElem = doc.documentElement();
+
+ if( docElem.tagName() != "tmx" || !(docElem.hasAttribute("version")
+ && docElem.attribute("version") == "1.4" ) )
+ {
+ _error = true;
+ _errorMsg = i18n( "Unsupported format.");
+ }
+
+
+ if( _error )
+ {
+ _errorMsg = i18n("Error while trying to read file for TMX Compendium module:\n"
+ "%1\n"
+ "Reason: %2")
+ .arg(url.prettyURL()).arg(_errorMsg);
+
+ kdDebug(KBABEL_SEARCH) << "Error: " << _errorMsg << endl;
+
+ emit progressEnds();
+
+ _active = false;
+ _initialized=true;
+
+ return false;
+ }
+
+ emit progressStarts(i18n("Building indices"));
+
+ QDomNodeList tuTags = docElem.elementsByTagName("tu");
+ uint total = tuTags.count();
+
+ _originals.clear();
+ _originals.resize(total);
+ _translations.clear();
+ _translations.resize(total);
+
+ uint lastindex = 0;
+
+ for(uint i=0; i < total; i++)
+ {
+ if( (100*(i+1))%total < 100 )
+ {
+ emit progress((100*(i+1))/total);
+ kapp->processEvents(100);
+ }
+
+ QDomNodeList tuvTags = tuTags.item(i).toElement().elementsByTagName("tuv");
+ QString english, other;
+ for( uint j = 0 ; j < tuvTags.count() ; j++ )
+ {
+ QDomElement el = tuvTags.item(j).toElement();
+ if( el.attribute("xml:lang").upper() == "EN" ) english = el.text();
+ if( el.attribute("xml:lang").upper().startsWith(language.upper()) )
+ other = el.text();
+ }
+
+ if( !english.isEmpty() && !other.isEmpty() )
+ {
+ kdDebug(KBABEL_SEARCH) << english << " to " << lastindex << endl;
+ _originals[lastindex] = english;
+ _translations[lastindex] = other;
+
+ QString temp = english;
+
+ int *index = new int(lastindex);
+ _exactDict.insert(temp,index);
+
+ temp = simplify(temp);
+ temp = temp.lower();
+
+ if(!temp.isEmpty() && temp.length() > 1)
+ {
+ QValueList<int> *indexList=_allDict[temp];
+
+ if(!indexList)
+ {
+ indexList = new QValueList<int>;
+ _allDict.insert(temp,indexList);
+ }
+
+ indexList->append(lastindex);
+
+ QStringList wList = wordList(temp);
+ for ( QStringList::Iterator it = wList.begin()
+ ; it != wList.end(); ++it )
+ {
+ if( (*it).length() > 1)
+ {
+ indexList=_wordDict[*it];
+
+ if(!indexList)
+ {
+ indexList = new QValueList<int>;
+ _wordDict.insert(*it,indexList);
+ }
+
+ indexList->append(lastindex);
+ }
+ }
+ }
+ lastindex++;
+ }
+ }
+
+
+ // remove words, that are too frequent
+ uint max=_allDict.count()/10;
+ QDictIterator< QValueList<int> > it(_wordDict);
+ while ( it.current() )
+ {
+ if(it.current()->count() > max)
+ {
+ _wordDict.remove(it.currentKey());
+ }
+ else
+ {
+ ++it;
+ }
+ }
+
+ if( lastindex == 0)
+ {
+ _error = true;
+ _errorMsg = i18n("Empty database.");
+ }
+
+ kdDebug(KBABEL_SEARCH) << "load done" << endl;
+
+ _initialized=true;
+
+ emit progressEnds();
+
+ _active = false;
+
+ return true;
+}
+
+const int* TmxCompendiumData::exactDict(const QString& text) const
+{
+ return _exactDict[text];
+}
+
+const QValueList<int>* TmxCompendiumData::allDict(const QString& text) const
+{
+ return _allDict[text];
+}
+
+const QValueList<int>* TmxCompendiumData::wordDict(const QString& text) const
+{
+ return _wordDict[text];
+}
+
+const QString TmxCompendiumData::msgid(const int index) const
+{
+ return _originals[index];
+}
+
+const QString TmxCompendiumData::msgstr(const int index) const
+{
+ return _translations[index];
+}
+
+
+void TmxCompendiumData::registerObject(QObject *obj)
+{
+ if(!_registered.containsRef(obj))
+ _registered.append(obj);
+}
+
+bool TmxCompendiumData::unregisterObject(QObject *obj)
+{
+ _registered.removeRef(obj);
+
+ return _registered.count()==0;
+}
+
+bool TmxCompendiumData::hasObjects() const
+{
+ return _registered.count()==0;
+}
+
+QString TmxCompendiumData::simplify(const QString& string)
+{
+ QString result;
+
+ TagExtractor te;
+ te.setString(string);
+ result=te.plainString();
+
+ result=result.simplifyWhiteSpace();
+ result=result.stripWhiteSpace();
+
+ return result;
+}
+
+QStringList TmxCompendiumData::wordList(const QString& string)
+{
+ QString result=TmxCompendiumData::simplify(string);
+
+ return QStringList::split(' ',result);
+}
+
+#include "tmxcompendiumdata.moc"
diff --git a/kbabel/kbabeldict/modules/tmx/tmxcompendiumdata.h b/kbabel/kbabeldict/modules/tmx/tmxcompendiumdata.h
new file mode 100644
index 00000000..bc88a92e
--- /dev/null
+++ b/kbabel/kbabeldict/modules/tmx/tmxcompendiumdata.h
@@ -0,0 +1,106 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2001 by Matthias Kiefer
+ <matthias.kiefer@gmx.de>
+ 2002 by Stanislav Visnovsky
+ <visnovsky@kde.org>
+
+ 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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+#ifndef TMXCOMPENDIUMDATA_H
+#define TMXCOMPENDIUMDATA_H
+
+
+#include <kurl.h>
+#include <qdict.h>
+#include <qobject.h>
+#include <qstringlist.h>
+#include <qvaluelist.h>
+#include <qvaluevector.h>
+#include <qptrlist.h>
+
+class TmxCompendiumData : public QObject
+{
+ Q_OBJECT
+
+public:
+ TmxCompendiumData(QObject *parent=0);
+
+ bool load(const KURL& url, const QString& language);
+
+ const int *exactDict(const QString& text) const;
+ const QValueList<int> *allDict(const QString& text) const;
+ const QValueList<int> *wordDict(const QString& text) const;
+
+ const QString msgid(const int index) const;
+ const QString msgstr(const int index) const;
+ const int numberOfEntries() const { return _exactDict.count(); }
+
+ bool active() const { return _active; }
+ bool initialized() const { return _initialized; }
+ bool hasErrors() const { return _error; }
+ QString errorMsg() const { return _errorMsg; }
+
+ /** registers an object, that uses this data */
+ void registerObject(QObject *);
+ /**
+ * unregisters an object, that uses this data
+ *
+ * @return true, if this was the last object
+ */
+ bool unregisterObject(QObject *);
+
+ bool hasObjects() const;
+
+
+ static QString simplify(const QString& text);
+ static QStringList wordList(const QString& text);
+
+signals:
+ void progressStarts(const QString&);
+ void progressEnds();
+ void progress(int);
+
+
+private:
+ bool _active;
+ bool _error;
+ bool _initialized;
+ QString _errorMsg;
+
+ QDict<int> _exactDict;
+ QDict< QValueList<int> > _allDict;
+ QDict< QValueList<int> > _wordDict;
+
+ QValueVector<QString> _originals;
+ QValueVector<QString> _translations;
+
+ QPtrList<QObject> _registered;
+};
+
+#endif
diff --git a/kbabel/kbabeldict/searchengine.cpp b/kbabel/kbabeldict/searchengine.cpp
new file mode 100644
index 00000000..95ab5694
--- /dev/null
+++ b/kbabel/kbabeldict/searchengine.cpp
@@ -0,0 +1,283 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+
+#include "searchengine.h"
+
+#include <kdebug.h>
+
+SearchResult::SearchResult()
+{
+ score=0;
+ descriptions.setAutoDelete(true);
+}
+
+SearchResult::SearchResult(const SearchResult& r)
+{
+ requested=r.requested;
+ found=r.found;
+ translation=r.translation;
+ plainTranslation=r.plainTranslation;
+ plainFound=r.plainFound;
+ plainRequested=r.plainRequested;
+ descriptions.setAutoDelete(true);
+ score=r.score;
+
+ QPtrListIterator<TranslationInfo> it(r.descriptions);
+ for ( ; it.current(); ++it )
+ {
+ TranslationInfo *ti=new TranslationInfo(*(*it));
+ descriptions.append(ti);
+ }
+
+}
+
+PrefWidget::PrefWidget(QWidget *parent, const char *name)
+ : QWidget(parent,name)
+{
+}
+
+PrefWidget::~PrefWidget()
+{
+}
+
+
+SearchEngine::SearchEngine(QObject *parent, const char *name)
+ : QObject(parent, name)
+{
+ autoUpdate=false;
+ results.setAutoDelete(true);
+}
+
+SearchEngine::~SearchEngine()
+{
+}
+
+bool SearchEngine::startSearchInTranslation(const QString&, unsigned int, const SearchFilter*)
+{
+ return true;
+}
+
+bool SearchEngine::usesRichTextResults()
+{
+ return false;
+}
+
+bool SearchEngine::isEditable()
+{
+ return false;
+}
+
+void SearchEngine::edit()
+{
+}
+
+void SearchEngine::setAutoUpdateOptions(bool activate)
+{
+ autoUpdate=activate;
+}
+
+SearchResult *SearchEngine::result(int n)
+{
+ SearchResult *r=0;
+
+ if(n >= 0 && n < (int)results.count())
+ r = results.at(n);
+
+ return r;
+}
+
+int SearchEngine::numberOfResults() const
+{
+ return results.count();
+}
+
+SearchResult *SearchEngine::nextResult()
+{
+ SearchResult *r= results.next();
+ if(r)
+ return r;
+ else
+ {
+ return 0;
+ }
+}
+
+SearchResult *SearchEngine::prevResult()
+{
+ SearchResult *r= results.prev();
+ if(r)
+ return r;
+ else
+ {
+ return 0;
+ }
+}
+
+SearchResult *SearchEngine::firstResult()
+{
+ SearchResult *r= results.first();
+ if(r)
+ return r;
+ else
+ {
+ return 0;
+ }
+}
+
+
+SearchResult *SearchEngine::lastResult()
+{
+ SearchResult *r= results.last();
+ if(r)
+ return r;
+ else
+ {
+ return 0;
+ }
+}
+
+void SearchEngine::clearResults()
+{
+ results.clear();
+ emit numberOfResultsChanged(0);
+}
+
+
+
+void SearchEngine::setEditedFile(const QString&)
+{
+}
+
+
+void SearchEngine::setEditedPackage(const QString&)
+{
+}
+
+void SearchEngine::setLanguageCode(const QString&)
+{
+}
+
+void SearchEngine::setLanguage(const QString&,const QString&)
+{
+}
+
+
+
+void SearchEngine::stringChanged(const QStringList&,const QString&,unsigned int, const QString&)
+{
+}
+
+
+QString SearchEngine::directory(const QString& path, int n)
+{
+ if(n<0)
+ return QString::null;
+
+ int begin=path.findRev('/');
+ int end=path.length();
+
+ if(begin < 0)
+ {
+ kdDebug() << "not found" << endl;
+ if(n==0)
+ return path;
+ else
+ return QString::null;
+ }
+
+ for(int i=0; i < n; i++)
+ {
+ if(begin==0)
+ {
+ return QString::null;
+ }
+
+ end = begin;
+ begin = path.findRev('/', end-1);
+
+ if(begin < 0)
+ {
+ return QString::null;
+ }
+ }
+
+ begin++;
+ return path.mid(begin,end-begin);
+}
+
+
+uint SearchEngine::score(const QString& orig, const QString& found)
+{
+ if(orig == found)
+ return 100;
+
+ uint scoreA = ngramMatch(found, orig);
+ uint scoreB = ngramMatch(orig,found);
+ uint score = QMIN(scoreA, scoreB);
+
+ QString f = found.lower();
+ QString o = orig.lower();
+
+ scoreA = ngramMatch(f, o);
+ scoreB = ngramMatch(o, f);
+ score = (QMIN(scoreA, scoreB)+score)/2;
+
+ return score;
+}
+
+uint SearchEngine::ngramMatch (const QString& text1, const QString& text2,
+ uint ngram_len)
+{
+ if (text1.length() < ngram_len || text2.length() < ngram_len)
+ return 0;
+
+ uint cnt=0;
+ uint ngram_cnt = text1.length() - ngram_len + 1;
+
+ for (uint i = 0; i < ngram_cnt; i++) {
+ if (text2.find(text1.mid(i,ngram_len)) >= 0)
+ cnt++;
+ }
+
+ return (cnt*100) / ngram_cnt;
+}
+
+
+bool SearchFilter::match( const TranslationInfo& toCheck )
+{
+ // FIXME: not implemented yet
+ return true;
+}
+
+#include "searchengine.moc"
diff --git a/kbabel/kbabeldict/searchengine.h b/kbabel/kbabeldict/searchengine.h
new file mode 100644
index 00000000..db722362
--- /dev/null
+++ b/kbabel/kbabeldict/searchengine.h
@@ -0,0 +1,534 @@
+/* ****************************************************************************
+ This file is part of KBabel
+
+ Copyright (C) 2000 by Matthias Kiefer
+ <matthias.kiefer@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; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+
+**************************************************************************** */
+
+#ifndef SEARCH_ENGINE_H
+#define SEARCH_ENGINE_H
+
+#include <qdatetime.h>
+#include <qptrlist.h>
+#include <qobject.h>
+#include <qstring.h>
+#include <qwidget.h>
+#include <kaboutdata.h>
+#include <kconfigbase.h>
+
+
+/*
+ * This class gives information about the translator, etc.
+ * Information, that is not available in a specific implementation of
+ * the SearchEngine, should be left empty.
+ */
+class KDE_EXPORT TranslationInfo
+{
+public:
+ /**
+ * Information about the location, where this entry was found.
+ * For example the PO-file it was found in, etc.
+ * */
+ QString location;
+
+ /**
+ * The complete path of the file, where this entry was found
+ */
+ QString filePath;
+
+
+ /** The date of the last change */
+ QDateTime lastChange;
+
+ /** The language, the translation belongs to */
+ QString languageCode;
+
+ /**
+ * The translator of this string
+ * For example the translator found in the header of the PO-file.
+ */
+ QString translator;
+
+ /**
+ * The name of a project this translation is a part of.
+ */
+ QString projectName;
+
+ /**
+ * Keywords defined for @ref projectName. For example KDE_3_1_BRANCH (project branch)
+ */
+ QStringList projectKeywords;
+
+ /**
+ * Part/context in a project, for example "multimedia", "admin", etc.
+ */
+ QString projectContext;
+
+ /**
+ * Status of the translation, for example "approved", "spellchecked", "unknown"
+ */
+ QString status;
+
+ /**
+ * Additional information to be presented to the user, for example a comment
+ */
+ QString description;
+};
+
+
+/**
+ * This class contains a result from the search
+ * plus additional information where it was found,
+ * the date and time of the last change, the translator, etc.
+ */
+class KDE_EXPORT SearchResult
+{
+public:
+ SearchResult();
+ SearchResult(const SearchResult&);
+
+ /** The requested string to search for */
+ QString requested;
+
+ /** The string that, was found (a list if it is a plural form) */
+ QStringList found;
+
+ /** The number of a plural form to search for */
+ uint requestedPluralForm;
+
+ /** The translation of the found string */
+ QString translation;
+
+ /** The number of a plural form of the translated string found */
+ uint translationPluralForm;
+
+ /**
+ * This string contains the plain translation if you are
+ * using rich text. If you don't use rich text, you can leave
+ * it empty
+ */
+ QString plainTranslation;
+
+ /**
+ * This string contains the plain string, that was found, if you are
+ * using rich text. If you don't use rich text, you can leave
+ * it empty
+ */
+ QString plainFound;
+
+ /**
+ * This string contains the plain requested string if you are
+ * using rich text. If you don't use rich text, you can leave
+ * it empty
+ */
+ QString plainRequested;
+
+ /**
+ * Constains a score for the found translation. 0 means exact matching.
+ * The higher the score is, the worse is the matching.
+ * How to compute the score is not yet really clear :-(
+ */
+ int score;
+
+ QPtrList<TranslationInfo> descriptions;
+};
+
+/**
+ *
+ */
+class KDE_EXPORT SearchFilter
+{
+public:
+ SearchFilter() :
+ _projects()
+ , _location( QString::null )
+ , _languageCode( QString::null )
+ , _origLanguageCode( QString::null )
+ , _translators()
+ , _projectKeywords()
+ , _projectContexts()
+ , _translationStatus()
+ {}
+
+ virtual ~SearchFilter() {}
+
+ void setProjectName( const QString& project ) { _projects = project; }
+ void setProjectName( const QStringList& projects ) { _projects = projects; }
+
+ /**
+ * Information about the location, where this entry was found.
+ * For example the PO-file it was found in, etc.
+ * */
+ void setLocation( const QString& location) { _location = location; }
+ QString location() const { return _location; }
+
+ /** The original language, the translation was made from */
+ void setOriginalLanguage( const QString& languageCode) { _origLanguageCode = languageCode; }
+
+ /** The language, the translation belongs to */
+ void setTranslationLanguage( const QString& languageCode) { _languageCode = languageCode; }
+
+ /**
+ * The translator of this string
+ * For example the translator found in the header of the PO-file.
+ */
+ void setTranslator( const QString& translator) { _translators = translator ; }
+ void setTranslator( const QStringList& translators) { _translators = translators ; }
+
+ /**
+ * Keywords defined for @ref projectName. For example KDE_3_1_BRANCH (project branch)
+ */
+ void setProjectKeywords( const QStringList& projectKeywords ) { _projectKeywords = projectKeywords; }
+
+ /**
+ * Part/context in a project, for example "multimedia", "admin", etc.
+ */
+ void setProjectContext( const QString& projectContext) { _projectContexts = projectContext; }
+ void setProjectContext( const QStringList& projectContexts) { _projectContexts = projectContexts; }
+
+ /**
+ * Status of the translation, for example "approved", "spellchecked", "unknown"
+ */
+ void setStatus( const QString& translationStatus) { _translationStatus = translationStatus; }
+ void setStatus( const QStringList& translationStati) { _translationStatus = translationStati; }
+
+ /**
+ * The key method of the class - check, if the argument
+ * matches this filter.
+ */
+ virtual bool match( const TranslationInfo& toCheck );
+
+private:
+ QStringList _projects;
+ QString _location;
+ QString _languageCode;
+ QString _origLanguageCode;
+ QStringList _translators;
+ QStringList _projectKeywords ;
+ QStringList _projectContexts;
+ QStringList _translationStatus;
+};
+
+/**
+ * This class is the base class for the preferences widget used to
+ * setup the search engines. Inherit from this and reimplement all
+ * necessary function. The widget should not be bigger than 400x400.
+ * If you need more space, you maybe want to use a tabbed widget.
+ */
+class KDE_EXPORT PrefWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ PrefWidget(QWidget *parent, const char* name=0);
+ virtual ~PrefWidget();
+
+public slots:
+ /**
+ * apply changes of the settings
+ */
+ virtual void apply()=0;
+ /**
+ * revert made changes
+ */
+ virtual void cancel()=0;
+ /**
+ * set settings to the standard options
+ */
+ virtual void standard()=0;
+};
+
+
+class KDE_EXPORT SearchEngine : public QObject
+{
+ Q_OBJECT
+
+public:
+ SearchEngine(QObject *parent=0, const char *name=0);
+ virtual ~SearchEngine();
+
+
+
+ /** @return the search result number n */
+ virtual SearchResult *result(int n);
+
+ /** @return the number of search results */
+ virtual int numberOfResults() const;
+
+ /** @return true, if a search is currently active */
+ virtual bool isSearching() const = 0;
+
+
+ /** save the settings in the given config object */
+ virtual void saveSettings(KConfigBase *config) = 0;
+ virtual void readSettings(KConfigBase *config) = 0;
+
+ /** @returns true, if it was initialized correctly */
+ virtual bool isReady() const =0;
+
+
+ /**
+ * @returns the exact translation of text or a empty string
+ * if no exact match was found.
+ */
+ virtual QString translate(const QString& text, const uint pluralForm = 0)=0;
+
+ /**
+ * @returns the translation of text according to the plugin settings or a empty string
+ * if no match was found.
+ */
+ virtual QString searchTranslation(const QString&, int &score, const uint pluralForm = 0) {
+ Q_UNUSED(pluralForm);
+
+ score = 0; return QString::null;
+ }
+
+ /**
+ * @returns a fuzzy translation of text or a empty string
+ * if no good match was found.
+ */
+ virtual QString fuzzyTranslation(const QString& /*text*/, int &score, const uint pluralForm = 0) {
+ Q_UNUSED(pluralForm);
+
+ score = 0; return QString::null; };
+
+
+ /**
+ * Finds all messages belonging to package package. If nothing is found,
+ * the list is empty.
+ * @param package The name of the file, something like "kbabel.po"
+ * @param resultList Will contain the found messages afterwards
+ * @param error If an error occured, this should contain a description
+ *
+ * @return true, if successfull
+ */
+ virtual bool messagesForFilter(const SearchFilter* filter
+ , QValueList<SearchResult>& resultList, QString& error)
+ {
+ Q_UNUSED(filter);
+ Q_UNUSED(resultList);
+
+ error = i18n("not implemented");
+ return false;
+ }
+
+ /**
+ * @returns true, if the searchresults are given as rich text
+ * the default implementation returns false
+ */
+ virtual bool usesRichTextResults();
+
+ /** @returns true, if the the entries in the database can be edited */
+ virtual bool isEditable();
+
+ /**
+ * @returns a widget which lets the user setup all preferences of this
+ * search engine. The returned widget should not be bigger than
+ * 400x400. If you need more space, you maybe want to use
+ * a tabbed widget.
+ * @param parent the parent of the returned widget
+ */
+ virtual PrefWidget* preferencesWidget(QWidget *parent)=0;
+
+ /** @returns information about this SearchEngine */
+ virtual const KAboutData *about() const= 0;
+
+ /** @returns the i18n name of this search engine */
+ virtual QString name() const= 0;
+
+ /** @returns a untranslated name of this engine */
+ virtual QString id() const= 0;
+
+ /** @returns the last error message */
+ virtual QString lastError() = 0;
+
+
+ /**
+ * sets the engine to always ask the preferences dialog for settings
+ * if is existing before starting the search.
+ */
+ virtual void setAutoUpdateOptions(bool activate);
+
+
+ /**
+ * @returns how good @param text1 matches @param text2
+ * comparing 3-grams .. n-grams, the returned value is
+ * a number between 0 and 100. @param ngram_len should be
+ * a value between 3 and 5.
+ */
+ static uint ngramMatch (const QString& text1, const QString& text2,
+ uint ngram_len=3);
+
+public slots:
+ /**
+ * starts a search for string s in the original text
+ * @returns false, if an error occured. Use @ref lastError
+ * to get the last error message
+ */
+ virtual bool startSearch(const QString& s, uint pluralForm = 0, const SearchFilter* filter = 0) = 0;
+
+ /**
+ * starts a search for string s in the translated text
+ * @returns false, if an error occured. Use @ref lastError
+ * to get the last error message
+ */
+ virtual bool startSearchInTranslation(const QString& s, uint pluralForm = 0, const SearchFilter* filter = 0);
+
+
+ /** stops a search */
+ virtual void stopSearch() = 0;
+
+ /** @return the next search result */
+ virtual SearchResult *nextResult();
+
+ /** @return the previous search result */
+ virtual SearchResult *prevResult();
+
+ /** @return the first search result */
+ virtual SearchResult *firstResult();
+
+ /** @return the last search result */
+ virtual SearchResult *lastResult();
+
+ /** clears the result list */
+ virtual void clearResults();
+
+
+ /**
+ * This method allows a search engine to use different settings depending
+ * on the edited file. The default implementation does nothing.
+ * @param file The edited file with path
+ */
+ virtual void setEditedFile(const QString& file);
+
+ /**
+ * This method allows a search engine to use different settings depending
+ * on the edited package. The default implementation does nothing.
+ * @param package The name of the package, that is currently translated.
+ */
+ virtual void setEditedPackage(const QString& package);
+
+ /**
+ * This method allows a search engine to use different settings depending
+ * on the language code. The default implementation does nothing.
+ * @param lang The current language code (e.g. de).
+ */
+ virtual void setLanguageCode(const QString& lang);
+ virtual void setLanguage(const QString& languageCode, const QString& languageName);
+
+
+
+ /**
+ * This method is called, if something has been changed in the
+ * current file. See @ref setEditedFile if you want to know the file
+ * name
+ * @param orig the original string (list of all plural forms)
+ * @param translation the translated string
+ * @param pluralForm the number of the plural form of the translation
+ * @param description the additional description, e.g., a PO comment
+ */
+ virtual void stringChanged( const QStringList& orig, const QString& translated
+ , const uint translationPluralForm, const QString& description);
+
+ /**
+ * If the database is editable this slot should open an dialog to let
+ * the user edit the contents of the database.
+ */
+ virtual void edit();
+
+ /************ convenience functions for distring normalization, etc.**********/
+
+ /**
+ * @returns the n-th directory name of path. Counting is started at
+ * end of path. Example: directory("/usr/local/src/foobar, 0")
+ * returns "foobar", while n=1 would return "src"
+ * FIXME: isn't it a code duplication?
+ */
+ static QString directory(const QString& path, int n);
+
+ /**
+ * computes a score to assess the match of the two strings:
+ * 0 means exact match, bigger means worse
+ */
+ static uint score(const QString& orig, const QString& found);
+
+signals:
+ /** signals, that a new search started */
+ void started();
+
+ /**
+ * signals progress in searching
+ * @param p should be between 0 and 100
+ * */
+ void progress(int p);
+
+ /**
+ * Use this, if you want to set your own message on the
+ * progressbar or if you do something else then searching,
+ * maybe loading a big file
+ */
+ void progressStarts(const QString&);
+
+ void progressEnds();
+
+ /**
+ * signals, that the number of search results has changed
+ * @param n the new number of results
+ * */
+ void numberOfResultsChanged(int n);
+
+ /**
+ * signals, that the order of the results in the list has changed.
+ * For example because a better matching string has been prepended.
+ */
+ void resultsReordered();
+
+ /**
+ * signals, that a new result was found
+ */
+ void resultFound(const SearchResult*);
+
+ /**
+ * signals, that search has finished
+ */
+ void finished();
+
+ /**
+ * signals, that an error occured, for example, that you wasn't
+ * able to open a database.
+ */
+ void hasError(const QString& error);
+
+protected:
+ QPtrList<SearchResult> results;
+ bool autoUpdate;
+};
+
+
+#endif // SEARCH_ENGINE_H