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.co