summaryrefslogtreecommitdiffstats
path: root/kdeui
diff options
context:
space:
mode:
Diffstat (limited to 'kdeui')
-rw-r--r--kdeui/AUTHORS97
-rw-r--r--kdeui/MAINTAINERS97
-rw-r--r--kdeui/Mainpage.dox43
-rw-r--r--kdeui/Makefile.am172
-rw-r--r--kdeui/README.kspell17
-rw-r--r--kdeui/TODO.kspell34
-rw-r--r--kdeui/TODO.xmlgui91
-rw-r--r--kdeui/about/Makefile.am9
-rw-r--r--kdeui/about/bar-bottom-left.pngbin0 -> 369 bytes
-rw-r--r--kdeui/about/bar-bottom-middle.pngbin0 -> 160 bytes
-rw-r--r--kdeui/about/bar-bottom-right.pngbin0 -> 346 bytes
-rw-r--r--kdeui/about/bar-middle-left.pngbin0 -> 126 bytes
-rw-r--r--kdeui/about/bar-middle-right.pngbin0 -> 141 bytes
-rw-r--r--kdeui/about/bar-top-left.pngbin0 -> 358 bytes
-rw-r--r--kdeui/about/bar-top-middle.pngbin0 -> 145 bytes
-rw-r--r--kdeui/about/bar-top-right.pngbin0 -> 359 bytes
-rw-r--r--kdeui/about/bottom-left.pngbin0 -> 665 bytes
-rw-r--r--kdeui/about/bottom-middle.pngbin0 -> 174 bytes
-rw-r--r--kdeui/about/bottom-right.pngbin0 -> 4922 bytes
-rw-r--r--kdeui/about/box-bottom-left.pngbin0 -> 470 bytes
-rw-r--r--kdeui/about/box-bottom-middle.pngbin0 -> 103 bytes
-rw-r--r--kdeui/about/box-bottom-right.pngbin0 -> 462 bytes
-rw-r--r--kdeui/about/box-middle-left.pngbin0 -> 95 bytes
-rw-r--r--kdeui/about/box-middle-right.pngbin0 -> 95 bytes
-rw-r--r--kdeui/about/box-top-left.pngbin0 -> 450 bytes
-rw-r--r--kdeui/about/box-top-middle.pngbin0 -> 104 bytes
-rw-r--r--kdeui/about/box-top-right.pngbin0 -> 496 bytes
-rw-r--r--kdeui/about/kde_infopage.css239
-rw-r--r--kdeui/about/kde_infopage_rtl.css11
-rw-r--r--kdeui/about/top-left.pngbin0 -> 15484 bytes
-rw-r--r--kdeui/about/top-middle.pngbin0 -> 233 bytes
-rw-r--r--kdeui/about/usage-example.html64
-rw-r--r--kdeui/aboutkde.pngbin0 -> 33092 bytes
-rw-r--r--kdeui/colors/Makefile.am10
-rw-r--r--kdeui/colors/README2
-rw-r--r--kdeui/colors/rgb.txt753
-rw-r--r--kdeui/dcolorarrow.xbm6
-rw-r--r--kdeui/dcolorreset.xpm19
-rw-r--r--kdeui/kaboutapplication.cpp188
-rw-r--r--kdeui/kaboutapplication.h94
-rw-r--r--kdeui/kaboutdialog.cpp1797
-rw-r--r--kdeui/kaboutdialog.h633
-rw-r--r--kdeui/kaboutdialog_private.h143
-rw-r--r--kdeui/kaboutkde.cpp89
-rw-r--r--kdeui/kaboutkde.h62
-rw-r--r--kdeui/kaccelgen.h280
-rw-r--r--kdeui/kaction.cpp1278
-rw-r--r--kdeui/kaction.h676
-rw-r--r--kdeui/kactionclasses.cpp2401
-rw-r--r--kdeui/kactionclasses.h1422
-rw-r--r--kdeui/kactioncollection.cpp802
-rw-r--r--kdeui/kactioncollection.h393
-rw-r--r--kdeui/kactionselector.cpp538
-rw-r--r--kdeui/kactionselector.h402
-rw-r--r--kdeui/kactionshortcutlist.h79
-rw-r--r--kdeui/kactivelabel.cpp142
-rw-r--r--kdeui/kactivelabel.h87
-rw-r--r--kdeui/kanimwidget.cpp212
-rw-r--r--kdeui/kanimwidget.h144
-rw-r--r--kdeui/karrowbutton.cpp113
-rw-r--r--kdeui/karrowbutton.h94
-rw-r--r--kdeui/kauthicon.cpp203
-rw-r--r--kdeui/kauthicon.h173
-rw-r--r--kdeui/kbugreport.cpp536
-rw-r--r--kdeui/kbugreport.h121
-rw-r--r--kdeui/kbuttonbox.cpp377
-rw-r--r--kdeui/kbuttonbox.h170
-rw-r--r--kdeui/kcharselect.cpp546
-rw-r--r--kdeui/kcharselect.h266
-rw-r--r--kdeui/kcmenumngr.cpp129
-rw-r--r--kdeui/kcmenumngr.h114
-rw-r--r--kdeui/kcmodule.cpp220
-rw-r--r--kdeui/kcmodule.h361
-rw-r--r--kdeui/kcolorbtn.h12
-rw-r--r--kdeui/kcolorbutton.cpp207
-rw-r--r--kdeui/kcolorbutton.h115
-rw-r--r--kdeui/kcolorcombo.cpp264
-rw-r--r--kdeui/kcolorcombo.h95
-rw-r--r--kdeui/kcolordialog.cpp1616
-rw-r--r--kdeui/kcolordialog.h496
-rw-r--r--kdeui/kcolordlg.h6
-rw-r--r--kdeui/kcolordrag.cpp112
-rw-r--r--kdeui/kcolordrag.h79
-rw-r--r--kdeui/kcombobox.cpp686
-rw-r--r--kdeui/kcombobox.h779
-rw-r--r--kdeui/kcommand.cpp379
-rw-r--r--kdeui/kcommand.h289
-rw-r--r--kdeui/kcompletionbox.cpp562
-rw-r--r--kdeui/kcompletionbox.h246
-rw-r--r--kdeui/kconfigdialog.cpp259
-rw-r--r--kdeui/kconfigdialog.h279
-rw-r--r--kdeui/kcursor.cpp434
-rw-r--r--kdeui/kcursor.h224
-rw-r--r--kdeui/kcursor_private.h99
-rw-r--r--kdeui/kdatepicker.cpp549
-rw-r--r--kdeui/kdatepicker.h257
-rw-r--r--kdeui/kdatepik.h6
-rw-r--r--kdeui/kdatetbl.cpp1031
-rw-r--r--kdeui/kdatetbl.h447
-rw-r--r--kdeui/kdatetimewidget.cpp74
-rw-r--r--kdeui/kdatetimewidget.h92
-rw-r--r--kdeui/kdatewidget.cpp177
-rw-r--r--kdeui/kdatewidget.h90
-rw-r--r--kdeui/kdcopactionproxy.cpp159
-rw-r--r--kdeui/kdcopactionproxy.h112
-rw-r--r--kdeui/kdepackages.h1301
-rw-r--r--kdeui/kdetrayproxy/Makefile.am13
-rw-r--r--kdeui/kdetrayproxy/kdetrayproxy.cpp196
-rw-r--r--kdeui/kdetrayproxy/kdetrayproxy.desktop134
-rw-r--r--kdeui/kdetrayproxy/kdetrayproxy.h50
-rw-r--r--kdeui/kdetrayproxy/module.cpp33
-rw-r--r--kdeui/kdetrayproxy/module.h39
-rw-r--r--kdeui/kdialog.cpp321
-rw-r--r--kdeui/kdialog.h211
-rw-r--r--kdeui/kdialogbase.cpp1844
-rw-r--r--kdeui/kdialogbase.h1632
-rw-r--r--kdeui/kdialogbase_priv.h71
-rw-r--r--kdeui/kdockwidget.cpp3331
-rw-r--r--kdeui/kdockwidget.h1539
-rw-r--r--kdeui/kdockwidget_p.h89
-rw-r--r--kdeui/kdockwidget_private.cpp712
-rw-r--r--kdeui/kdockwidget_private.h335
-rw-r--r--kdeui/kdockwindow.h41
-rw-r--r--kdeui/kdualcolorbtn.h6
-rw-r--r--kdeui/kdualcolorbutton.cpp283
-rw-r--r--kdeui/kdualcolorbutton.h159
-rw-r--r--kdeui/keditcl.h436
-rw-r--r--kdeui/keditcl1.cpp718
-rw-r--r--kdeui/keditcl2.cpp1127
-rw-r--r--kdeui/keditlistbox.cpp418
-rw-r--r--kdeui/keditlistbox.h272
-rw-r--r--kdeui/kedittoolbar.cpp1455
-rw-r--r--kdeui/kedittoolbar.h439
-rw-r--r--kdeui/kfontcombo.cpp354
-rw-r--r--kdeui/kfontcombo.h179
-rw-r--r--kdeui/kfontdialog.cpp799
-rw-r--r--kdeui/kfontdialog.h504
-rw-r--r--kdeui/kfontrequester.cpp127
-rw-r--r--kdeui/kfontrequester.h157
-rw-r--r--kdeui/kguiitem.cpp229
-rw-r--r--kdeui/kguiitem.h98
-rw-r--r--kdeui/khelpmenu.cpp320
-rw-r--r--kdeui/khelpmenu.h281
-rw-r--r--kdeui/kiconview.cpp734
-rw-r--r--kdeui/kiconview.h281
-rw-r--r--kdeui/kiconviewsearchline.cpp274
-rw-r--r--kdeui/kiconviewsearchline.h179
-rw-r--r--kdeui/kinputdialog.cpp468
-rw-r--r--kdeui/kinputdialog.h290
-rw-r--r--kdeui/kjanuswidget.cpp1148
-rw-r--r--kdeui/kjanuswidget.h606
-rw-r--r--kdeui/kkeybutton.cpp178
-rw-r--r--kdeui/kkeybutton.h91
-rw-r--r--kdeui/kkeydialog.cpp1209
-rw-r--r--kdeui/kkeydialog.h407
-rw-r--r--kdeui/klanguagebutton.cpp284
-rw-r--r--kdeui/klanguagebutton.h182
-rw-r--r--kdeui/kled.cpp644
-rw-r--r--kdeui/kled.h329
-rw-r--r--kdeui/klineedit.cpp1382
-rw-r--r--kdeui/klineedit.h656
-rw-r--r--kdeui/klineeditdlg.cpp194
-rw-r--r--kdeui/klineeditdlg.h125
-rw-r--r--kdeui/klistbox.cpp266
-rw-r--r--kdeui/klistbox.h128
-rw-r--r--kdeui/klistview.cpp2365
-rw-r--r--kdeui/klistview.h1085
-rw-r--r--kdeui/klistviewlineedit.h65
-rw-r--r--kdeui/klistviewsearchline.cpp501
-rw-r--r--kdeui/klistviewsearchline.h264
-rw-r--r--kdeui/kmainwindow.cpp1249
-rw-r--r--kdeui/kmainwindow.h1067
-rw-r--r--kdeui/kmainwindowiface.cpp194
-rw-r--r--kdeui/kmainwindowiface.h161
-rw-r--r--kdeui/kmenubar.cpp563
-rw-r--r--kdeui/kmenubar.h114
-rw-r--r--kdeui/kmessagebox.cpp1071
-rw-r--r--kdeui/kmessagebox.h1166
-rw-r--r--kdeui/knuminput.cpp1180
-rw-r--r--kdeui/knuminput.h957
-rw-r--r--kdeui/knumvalidator.cpp371
-rw-r--r--kdeui/knumvalidator.h212
-rw-r--r--kdeui/kpanelapplet.cpp198
-rw-r--r--kdeui/kpanelapplet.h395
-rw-r--r--kdeui/kpanelappmenu.cpp182
-rw-r--r--kdeui/kpanelappmenu.h99
-rw-r--r--kdeui/kpanelextension.cpp163
-rw-r--r--kdeui/kpanelextension.h346
-rw-r--r--kdeui/kpanelmenu.cpp158
-rw-r--r--kdeui/kpanelmenu.h182
-rw-r--r--kdeui/kpartgui.dtd181
-rw-r--r--kdeui/kpassdlg.cpp721
-rw-r--r--kdeui/kpassdlg.h414
-rw-r--r--kdeui/kpassivepopup.cpp498
-rw-r--r--kdeui/kpassivepopup.h363
-rw-r--r--kdeui/kpixmapio-perf.pngbin0 -> 3899 bytes
-rw-r--r--kdeui/kpixmapio.cpp908
-rw-r--r--kdeui/kpixmapio.h185
-rw-r--r--kdeui/kpixmapregionselectordialog.cpp127
-rw-r--r--kdeui/kpixmapregionselectordialog.h107
-rw-r--r--kdeui/kpixmapregionselectorwidget.cpp450
-rw-r--r--kdeui/kpixmapregionselectorwidget.h170
-rw-r--r--kdeui/kpopupmenu.cpp689
-rw-r--r--kdeui/kpopupmenu.h281
-rw-r--r--kdeui/kprogress.cpp414
-rw-r--r--kdeui/kprogress.h401
-rw-r--r--kdeui/kpushbutton.cpp220
-rw-r--r--kdeui/kpushbutton.h161
-rw-r--r--kdeui/krestrictedline.cpp81
-rw-r--r--kdeui/krestrictedline.h95
-rw-r--r--kdeui/krootpixmap.cpp332
-rw-r--r--kdeui/krootpixmap.h216
-rw-r--r--kdeui/kruler.cpp742
-rw-r--r--kdeui/kruler.h521
-rw-r--r--kdeui/ksconfig.cpp1028
-rw-r--r--kdeui/ksconfig.h293
-rw-r--r--kdeui/kscrollview.cpp189
-rw-r--r--kdeui/kscrollview.h62
-rw-r--r--kdeui/kselect.cpp534
-rw-r--r--kdeui/kselect.h373
-rw-r--r--kdeui/kseparator.cpp116
-rw-r--r--kdeui/kseparator.h87
-rw-r--r--kdeui/ksharedpixmap.cpp228
-rw-r--r--kdeui/ksharedpixmap.h115
-rw-r--r--kdeui/kshortcutdialog.cpp529
-rw-r--r--kdeui/kshortcutdialog.h96
-rw-r--r--kdeui/kshortcutdialog_advanced.ui254
-rw-r--r--kdeui/kshortcutdialog_simple.ui120
-rw-r--r--kdeui/kspell.cpp1577
-rw-r--r--kdeui/kspell.h568
-rw-r--r--kdeui/kspelldlg.cpp285
-rw-r--r--kdeui/kspelldlg.h114
-rw-r--r--kdeui/kspellui.ui300
-rw-r--r--kdeui/ksplashscreen.cpp42
-rw-r--r--kdeui/ksplashscreen.h62
-rw-r--r--kdeui/ksqueezedtextlabel.cpp87
-rw-r--r--kdeui/ksqueezedtextlabel.h84
-rw-r--r--kdeui/kstatusbar.cpp156
-rw-r--r--kdeui/kstatusbar.h208
-rw-r--r--kdeui/kstdaction.cpp323
-rw-r--r--kdeui/kstdaction.h614
-rw-r--r--kdeui/kstdaction_p.h139
-rw-r--r--kdeui/kstdguiitem.cpp287
-rw-r--r--kdeui/kstdguiitem.h183
-rw-r--r--kdeui/kstringvalidator.cpp90
-rw-r--r--kdeui/kstringvalidator.h141
-rw-r--r--kdeui/kswitchlanguagedialog.cpp349
-rw-r--r--kdeui/kswitchlanguagedialog.h87
-rw-r--r--kdeui/ksyntaxhighlighter.cpp677
-rw-r--r--kdeui/ksyntaxhighlighter.h184
-rw-r--r--kdeui/ksystemtray.cpp335
-rw-r--r--kdeui/ksystemtray.h205
-rw-r--r--kdeui/ktabbar.cpp427
-rw-r--r--kdeui/ktabbar.h113
-rw-r--r--kdeui/ktabctl.cpp336
-rw-r--r--kdeui/ktabctl.h90
-rw-r--r--kdeui/ktabwidget.cpp524
-rw-r--r--kdeui/ktabwidget.h294
-rw-r--r--kdeui/ktextbrowser.cpp145
-rw-r--r--kdeui/ktextbrowser.h133
-rw-r--r--kdeui/ktextedit.cpp419
-rw-r--r--kdeui/ktextedit.h174
-rw-r--r--kdeui/ktimewidget.cpp58
-rw-r--r--kdeui/ktimewidget.h86
-rw-r--r--kdeui/ktimezonewidget.cpp133
-rw-r--r--kdeui/ktimezonewidget.h112
-rw-r--r--kdeui/ktip-background.pngbin0 -> 190 bytes
-rw-r--r--kdeui/ktip-bulb.pngbin0 -> 14134 bytes
-rw-r--r--kdeui/ktip.cpp424
-rw-r--r--kdeui/ktip.h192
-rw-r--r--kdeui/ktoolbar.cpp2259
-rw-r--r--kdeui/ktoolbar.h1128
-rw-r--r--kdeui/ktoolbarbutton.cpp781
-rw-r--r--kdeui/ktoolbarbutton.h330
-rw-r--r--kdeui/ktoolbarhandler.cpp246
-rw-r--r--kdeui/ktoolbarhandler.h69
-rw-r--r--kdeui/ktoolbarlabelaction.cpp117
-rw-r--r--kdeui/ktoolbarlabelaction.h137
-rw-r--r--kdeui/ktoolbarradiogroup.cpp77
-rw-r--r--kdeui/ktoolbarradiogroup.h88
-rw-r--r--kdeui/kurllabel.cpp450
-rw-r--r--kdeui/kurllabel.h407
-rw-r--r--kdeui/kwhatsthismanager.cpp121
-rw-r--r--kdeui/kwhatsthismanager_p.h58
-rw-r--r--kdeui/kwindowinfo.cpp178
-rw-r--r--kdeui/kwindowinfo.h145
-rw-r--r--kdeui/kwindowlistmenu.cpp257
-rw-r--r--kdeui/kwindowlistmenu.h70
-rw-r--r--kdeui/kwizard.cpp57
-rw-r--r--kdeui/kwizard.h62
-rw-r--r--kdeui/kwordwrap.cpp269
-rw-r--r--kdeui/kwordwrap.h149
-rw-r--r--kdeui/kxmlgui.h6
-rw-r--r--kdeui/kxmlgui.xsd445
-rw-r--r--kdeui/kxmlguibuilder.cpp441
-rw-r--r--kdeui/kxmlguibuilder.h96
-rw-r--r--kdeui/kxmlguiclient.cpp951
-rw-r--r--kdeui/kxmlguiclient.h367
-rw-r--r--kdeui/kxmlguifactory.cpp614
-rw-r--r--kdeui/kxmlguifactory.h220
-rw-r--r--kdeui/kxmlguifactory_p.cpp836
-rw-r--r--kdeui/kxmlguifactory_p.h254
-rw-r--r--kdeui/libkdeui.nmcheck5
-rw-r--r--kdeui/libkdeui_weak.nmcheck2
-rwxr-xr-xkdeui/preparetips66
-rw-r--r--kdeui/qxembed.cpp1385
-rw-r--r--kdeui/qxembed.h234
-rw-r--r--kdeui/tests/Makefile.am105
-rw-r--r--kdeui/tests/RayTracedGear.pngbin0 -> 5844 bytes
-rw-r--r--kdeui/tests/background_1.pngbin0 -> 7209 bytes
-rw-r--r--kdeui/tests/go.pngbin0 -> 3286 bytes
-rw-r--r--kdeui/tests/itemcontainertest.cpp225
-rw-r--r--kdeui/tests/itemcontainertest.h45
-rw-r--r--kdeui/tests/kaboutdialogtest.cpp72
-rw-r--r--kdeui/tests/kaccelgentest.cpp51
-rw-r--r--kdeui/tests/kactiontest.cpp38
-rw-r--r--kdeui/tests/kalphaicontest.h24
-rw-r--r--kdeui/tests/kblendtest.cpp98
-rw-r--r--kdeui/tests/kblendtest.h24
-rw-r--r--kdeui/tests/kbuttonboxtest.cpp205
-rw-r--r--kdeui/tests/kcharselecttest.cpp16
-rw-r--r--kdeui/tests/kcolordlgtest.cpp41
-rw-r--r--kdeui/tests/kcolortest.cpp169
-rw-r--r--kdeui/tests/kcolortest.h21
-rw-r--r--kdeui/tests/kcomboboxtest.cpp227
-rw-r--r--kdeui/tests/kcomboboxtest.h44
-rw-r--r--kdeui/tests/kcompletiontest.cpp198
-rw-r--r--kdeui/tests/kcompletiontest.h67
-rw-r--r--kdeui/tests/kdatepicktest.cpp16
-rw-r--r--kdeui/tests/kdatetimewidgettest.cpp14
-rw-r--r--kdeui/tests/kdatewidgettest.cpp16
-rw-r--r--kdeui/tests/kdesattest.cpp65
-rw-r--r--kdeui/tests/kdesattest.h31
-rw-r--r--kdeui/tests/kdialogbasetest.cpp77
-rw-r--r--kdeui/tests/kdocktest.cpp65
-rw-r--r--kdeui/tests/kdocktest.h19
-rw-r--r--kdeui/tests/kdockwidgetdemo.cpp796
-rw-r--r--kdeui/tests/kdockwidgetdemo.h164
-rw-r--r--kdeui/tests/kdockwidgettest.cpp255
-rw-r--r--kdeui/tests/kdockwidgettest.h72
-rw-r--r--kdeui/tests/kdualcolortest.cpp63
-rw-r--r--kdeui/tests/kdualcolortest.h20
-rw-r--r--kdeui/tests/keditlistboxtest.cpp21
-rw-r--r--kdeui/tests/kedittest.cpp14
-rw-r--r--kdeui/tests/kfontdialogtest.cpp51
-rw-r--r--kdeui/tests/kgradienttest.cpp108
-rw-r--r--kdeui/tests/kgradienttest.h24
-rw-r--r--kdeui/tests/khashtest.cpp137
-rw-r--r--kdeui/tests/khashtest.h26
-rw-r--r--kdeui/tests/kinputdialogtest.cpp67
-rw-r--r--kdeui/tests/kjanuswidgettest.cpp25
-rw-r--r--kdeui/tests/kledtest.cpp160
-rw-r--r--kdeui/tests/kledtest.h56
-rw-r--r--kdeui/tests/klineeditdlgtest.cpp19
-rw-r--r--kdeui/tests/klineedittest.cpp137
-rw-r--r--kdeui/tests/klineedittest.h41
-rw-r--r--kdeui/tests/klistviewtest.cpp39
-rw-r--r--kdeui/tests/kmainwindowrestoretest.cpp41
-rw-r--r--kdeui/tests/kmainwindowrestoretest.h48
-rw-r--r--kdeui/tests/kmainwindowtest.cpp38
-rw-r--r--kdeui/tests/kmainwindowtest.h18
-rw-r--r--kdeui/tests/kmessageboxtest.cpp242
-rw-r--r--kdeui/tests/knuminputtest.cpp145
-rw-r--r--kdeui/tests/knuminputtest.h23
-rw-r--r--kdeui/tests/kpalettetest.cpp38
-rw-r--r--kdeui/tests/kpanelmenutest.cpp72
-rw-r--r--kdeui/tests/kpanelmenutest.h21
-rw-r--r--kdeui/tests/kpixmapregionselectordialogtest.cpp33
-rw-r--r--kdeui/tests/kpopuptest.cpp40
-rw-r--r--kdeui/tests/kprogresstest.cpp58
-rw-r--r--kdeui/tests/krulertest.cpp375
-rw-r--r--kdeui/tests/krulertest.h91
-rw-r--r--kdeui/tests/kseparatortest.cpp51
-rw-r--r--kdeui/tests/kspelltest.cpp57
-rw-r--r--kdeui/tests/ksqueezedtextlabeltest.cpp13
-rw-r--r--kdeui/tests/kstatusbartest.cpp121
-rw-r--r--kdeui/tests/kstatusbartest.h33
-rw-r--r--kdeui/tests/ksystemtraytest.cpp14
-rw-r--r--kdeui/tests/ktabctltest.cpp105
-rw-r--r--kdeui/tests/ktabctltest.h30
-rw-r--r--kdeui/tests/ktabwidgettest.cpp366
-rw-r--r--kdeui/tests/ktabwidgettest.h69
-rw-r--r--kdeui/tests/ktextedittest.cpp43
-rw-r--r--kdeui/tests/ktimewidgettest.cpp14
-rw-r--r--kdeui/tests/ktoolbarlabelactiontest.cpp97
-rw-r--r--kdeui/tests/ktoolbarlabelactiontestui.rc9
-rw-r--r--kdeui/tests/kunbalancedgrdtest.cpp176
-rw-r--r--kdeui/tests/kunbalancedgrdtest.h49
-rw-r--r--kdeui/tests/kwindowtest.cpp528
-rw-r--r--kdeui/tests/kwindowtest.h71
-rw-r--r--kdeui/tests/kwizardtest.cpp54
-rw-r--r--kdeui/tests/kwordwraptest.cpp43
-rw-r--r--kdeui/tests/kxmlguitest.cpp64
-rw-r--r--kdeui/tests/kxmlguitest.h19
-rw-r--r--kdeui/tests/kxmlguitest_part.rc8
-rw-r--r--kdeui/tests/kxmlguitest_shell.rc7
-rw-r--r--kdeui/tests/qxembedtest.cpp88
-rw-r--r--kdeui/tests/testimage.pngbin0 -> 35951 bytes
-rw-r--r--kdeui/ui_standards.rc211
399 files changed, 116123 insertions, 0 deletions
diff --git a/kdeui/AUTHORS b/kdeui/AUTHORS
new file mode 100644
index 000000000..9e7ce9592
--- /dev/null
+++ b/kdeui/AUTHORS
@@ -0,0 +1,97 @@
+Dawit Alemayehu <adawit@earthlink.net>
+KLineEdit, KComboBox
+
+Espen Sand <espen@kde.org>:
+KDialogBase, KAboutDialog (based on work by Mirko), KHelpMenu, KTextBrowser
+and various adjustments here and there.
+
+Daniel M. Duley <mosfet@kde.org>
+Maintainer of KPixmapEffect, KStyle, KThemeStyle, and KThemeBase - as well as
+general misc coding here and there.
+
+Matthias Kalle Dalheimer <kalle@kde.org>:
+classes KApplication, KConfig, KTextStream, KColorSet,
+automake, autoconf, maintenance
+
+Richard Moore <moorer@cs.man.ac.uk>:
+KLedLamp class, KNewPanner class.
+
+Martynas Kunigelis <algikun@santaka.ktu.lt>:
+KProgress class
+
+Steffen Hansen <stefh@dit.ou.dk>:
+KURL class
+
+Torben Weis <weis@stud.uni-frankfurt.de>
+DnD stuff, KSocket and KServerSocket classes, KPixmap
+
+Alexander Sanda <alex@darkstar.ping.at>
+Read and write numerical config entries, KPanner, KTabControl,
+KPopupMenu, KMessageBox, KEdit widgets.
+
+Martin Jones <mjones@powerup.com.au>
+Bugfixes in KPixmap and KURL, KColorDialog, KSelector
+KColorButton
+
+Keith Brown <kbrown@pdq.net>
+KTreeList class
+
+Bernd Johannes Wuebben <wuebben@math.cornell.edu>
+KFontDialog class
+
+Tim D. Gilman <tdgilman@best.com>
+KDatePicker, KDateTable class
+
+Nicolas Hadacek <hadacek@kde.org>
+Key configuration classes, bug fixes
+
+Christoph Neerfeld <Christoph.Neerfeld@mail.bonn.netsurf.de>
+KIconLoader class
+
+Sven Radej <sven.radej@iname.com>
+KLineEdit, KCombo, KToolbar, KStatusBar
+
+Rainer Bawidamann <Rainer.Bawidamann@wohnheim.uni-ulm.de>
+Rubberbanding in KTreeList
+
+Andre Fornacon <afo@fh-zwickau.de>
+KSpinBox
+
+Michael Wiedmann <mw@miwie.in-berlin.de>
+KRestrictedLine, KIntegerLine
+
+Matthias Ettrich <ettrich@kde.org>
+KWMModuleApplication, tearing/docking of ktoolbar and kmenubar, heavy
+modifications to kbutton
+
+Stephan Kulow <coolo@kde.org>
+first versions of KTopLevelWidget and KToolBar, heavy modifications to
+automake and autoconf
+
+Joerg Habenicht <j.habenicht@europemail.com>
+KLed class
+
+Thomas Tanghus <tanghus@earthling.net>
+Classes KNotebook and KWizard
+
+Jorge Monteiro <jomo@casema.net>
+KContainerLayout class
+
+Kurt Granroth <granroth@kde.org>
+KURLLabel class
+
+Jörg Habenicht <habenich@kbs.uni-hannover.de>
+KRuler class
+
+Rene Beutler <rbeutler@iiic.ethz.ch>
+Widget Identifying System
+
+Maxim Judin <novaprint@mtu-net.ru>
+created the Dockwidget class set
+
+Falk Brettschneider <gigafalk@yahoo.com>
+contributes for the Dockwidget class set
+
+Holger Freyther <freyther@yahoo.com>
+KDialogBase, KGuiItem, KStdGuiItem, KAction,
+added KMessageBox::questionYesNoCancel( )
diff --git a/kdeui/MAINTAINERS b/kdeui/MAINTAINERS
new file mode 100644
index 000000000..16942949f
--- /dev/null
+++ b/kdeui/MAINTAINERS
@@ -0,0 +1,97 @@
+Here are the code maintainers for each part of this library. Any problems or
+suggested patches for a class should be directed to the responsible person for
+that class.
+
+When adding yourself as a maintainer, don't be afraid to reorder the files to a
+more logical grouping.
+
+kaboutapplication.cpp
+kaboutdialog.cpp
+kaboutkde.cpp
+kaction.cpp Holger Freyther <freyther@kde.org>, Martijn Klingens <klingens@kde.org>
+kanimwidget.cpp Waldo Bastian <bastian@kde.org>
+karrowbutton.cpp Frerich Raabe <raabe@kde.org>
+kauthicon.cpp
+kbugreport.cpp
+kbuttonbox.cpp
+kcharselect.cpp
+kcmenumngr.cpp
+kcmodule.cpp
+kcolorbutton.cpp
+kcolorcombo.cpp
+kcolordialog.cpp Waldo Bastian <bastian@kde.org>
+kcolordrag.cpp
+kcombobox.cpp Dawit Alemayehu <adawit@kde.org>, Carsten Pfeiffer <pfeiffer@kde.org>
+kcommand.cpp Werner Trobin <trobin@kde.org>
+kcompletionbox.cpp Carsten Pfeiffer <pfeiffer@kde.org>
+kcursor.cpp Carsten Pfeiffer <pfeiffer@kde.org>
+kdatepicker.cpp
+kdatetbl.cpp
+kdatetimewidget.cpp Hans Petter Bieker <bieker@kde.org>
+kdatewidget.cpp Waldo Bastian <bastian@kde.org>
+kdcopactionproxy.cpp
+kdialog.cpp
+kdialogbase.cpp Waldo Bastian <bastian@kde.org>
+kdockwidget.cpp Joseph Wenninger <jowenn@kde.org>
+kdockwidget_private.cpp Joseph Wenninger <jowenn@kde.org>
+kdualcolorbutton.cpp
+keditcl1.cpp Waldo Bastian <bastian@kde.org>
+keditcl2.cpp Waldo Bastian <bastian@kde.org>
+keditlistbox.cpp
+kedittoolbar.cpp
+kfontcombo.cpp
+kfontdialog.cpp
+kguiitem.cpp Holger Freyther <freyther@kde.org>, Martijn Klingens <klingens@kde.org>
+khelpmenu.cpp
+kiconview.cpp
+kjanuswidget.cpp Ravikiran Rajagopal <ravi@ee.eng.ohio-state.edu>
+kkeybutton.cpp Ellis Whitehead <ellis@kde.org>
+kkeydialog.cpp Ellis Whitehead <ellis@kde.org>
+kled.cpp
+klineedit.cpp Dawit Alemayehu <adawit@kde.org>, Carsten Pfeiffer <pfeiffer@kde.org>
+klineeditdlg.cpp
+klistbox.cpp
+klistview.cpp
+kmainwindow.cpp
+kmainwindowiface.cpp
+kmenubar.cpp
+kmessagebox.cpp Waldo Bastian <bastian@kde.org>
+knuminput.cpp Dirk Mueller <mueller@kde.org>
+knumvalidator.cpp
+kpanelapplet.cpp
+kpanelappmenu.cpp
+kpanelextension.cpp
+kpanelmenu.cpp
+kpassdlg.cpp Waldo Bastian <bastian@kde.org>
+kpixmapio.cpp
+kpopupmenu.cpp Holger Freyther <freyther@kde.org>
+kprogress.cpp
+kpushbutton.cpp Carsten Pfeiffer <pfeiffer@kde.org>, Martijn Klingens <klingens@kde.org>
+krestrictedline.cpp
+krootpixmap.cpp
+kruler.cpp
+kselect.cpp
+kseparator.cpp Waldo Bastian <bastian@kde.org>
+ksharedpixmap.cpp
+kshortcutdialog.cpp Ellis Whitehead <ellis@kde.org>
+ksqueezedtextlabel.cpp
+kstatusbar.cpp
+kstdaction.cpp
+kstdguiitem.cpp Holger Freyther <freyther@kde.org>, Martijn Klingens <klingens@kde.org>
+kstringvalidator.cpp Marc Mutz <mutz@kde.org>
+ksystemtray.cpp
+ktabctl.cpp
+ktextbrowser.cpp
+ktimewidget Hans Petter Bieker <bieker@kde.org>
+ktip.cpp
+ktoolbar.cpp Waldo Bastian <bastian@kde.org>
+ktoolbarbutton.cpp Waldo Bastian <bastian@kde.org>
+ktoolbarradiogroup.cpp
+kurllabel.cpp
+kwindowlistmenu.cpp
+kwizard.cpp
+kwordwrap.cpp David Faure <faure@kde.org>
+kxmlguibuilder.cpp
+kxmlguiclient.cpp
+kxmlguifactory.cpp
+qxembed.cpp
diff --git a/kdeui/Mainpage.dox b/kdeui/Mainpage.dox
new file mode 100644
index 000000000..1e360ee1c
--- /dev/null
+++ b/kdeui/Mainpage.dox
@@ -0,0 +1,43 @@
+/*
+ A dummy source file for documenting the library.
+ Sirtaj Singh Kang <taj@kde.org>
+ $Id$
+ Distributed under the LGPL.
+*/
+
+/**
+* @mainpage The KDE User Interface library
+*
+* This library provides standard user interface elements for use in
+* KDE applications. If your KDE application has a GUI, you will almost
+* certainly link to libkdeui.
+*
+* Most applications with single or multiple toplevel widgets
+* should use the KMainWindow class in this library, which
+* automatically provides features like session management and simplified
+* toolbar/menubar/statusbar creation.
+*
+* A spell-checker library is also provided.
+* KSpell offers easy access to International ISpell or ASpell
+* (at the user's option) as well as a spell-checker GUI
+* ("Add", "Replace", etc.).
+*
+* You can use KSpell to
+* automatically spell-check an ASCII file as well as to implement
+* online spell-checking and to spell-check proprietary format and
+* marked up (e.g. HTML, TeX) documents. The relevant methods for
+* these three procedures are check(), checkWord(), and
+* checkList(), respectively.
+*
+* KSpellConfig holds configuration information about KSpell as well
+* as acting as an options-setting dialog.
+*
+* KSpell usually works asynchronously. If you do not need that, you should
+* simply use KSpell::modalCheck(). It won't return until the
+* passed string is processed or the spell checking canceled.
+* During modal spell checking your GUI is still repainted, but the user may
+* only interact with the KSpell dialog.
+*
+* @see KSpell, KSpellConfig
+*/
+
diff --git a/kdeui/Makefile.am b/kdeui/Makefile.am
new file mode 100644
index 000000000..6524105b1
--- /dev/null
+++ b/kdeui/Makefile.am
@@ -0,0 +1,172 @@
+
+# This file is part of the KDE libraries
+# Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org)
+# (C) 1997 Stephan Kulow (coolo@kde.org)
+
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this library; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+SUBDIRS = . kdetrayproxy tests about
+
+INCLUDES= -I$(top_srcdir)/kdefx -I$(top_srcdir)/interfaces $(all_includes)
+
+# For the future: examine if condensing the tons of *_LDFLAGS variables
+# into $(all_libraries) isn't better
+AM_LDFLAGS = $(LDFLAGS_AS_NEEDED) $(LDFLAGS_NEW_DTAGS)
+
+lib_LTLIBRARIES = libkdeui.la libkspell.la
+libkdeui_la_LDFLAGS = $(KDE_MT_LDFLAGS) -no-undefined -version-info 6:0:2
+libkdeui_la_LIBADD = ../kdecore/libkdecore.la
+
+libkspell_la_LDFLAGS = $(KDE_MT_LDFLAGS) -version-info 6:0:2 -no-undefined
+libkspell_la_LIBADD = libkdeui.la
+libkspell_la_SOURCES = dummy.cpp
+
+picsdir = $(kde_datadir)/kdeui/pics
+pics_DATA = aboutkde.png ktip-bulb.png ktip-background.png
+
+include_HEADERS = kprogress.h kcolordlg.h \
+ kcolordialog.h kselect.h \
+ kdatepik.h kdatepicker.h kdatetbl.h kfontdialog.h kpopupmenu.h \
+ kfontrequester.h ktabctl.h kstatusbar.h \
+ kmainwindow.h kmainwindowiface.h ktoolbar.h kmenubar.h \
+ knuminput.h kseparator.h klineedit.h \
+ krestrictedline.h kcolorbutton.h kcolorbtn.h \
+ ksystemtray.h kdockwindow.h kbuttonbox.h \
+ keditcl.h kled.h keditlistbox.h \
+ kwizard.h kkeydialog.h kkeybutton.h \
+ kurllabel.h kruler.h kcursor.h \
+ klineeditdlg.h kinputdialog.h kactivelabel.h \
+ kcharselect.h kcolordrag.h qxembed.h \
+ knumvalidator.h kdialog.h kdialogbase.h \
+ kjanuswidget.h kaboutdialog.h \
+ kauthicon.h kmessagebox.h ksharedpixmap.h \
+ kdualcolorbtn.h kdualcolorbutton.h ktoolbarbutton.h \
+ ktoolbarradiogroup.h ktextbrowser.h \
+ kaction.h kactioncollection.h kactionclasses.h khelpmenu.h kswitchlanguagedialog.h \
+ kcmodule.h kcmenumngr.h kpanelmenu.h kpanelappmenu.h \
+ kactionshortcutlist.h kstdaction.h kcombobox.h \
+ kiconview.h klistview.h klistbox.h kbugreport.h kpassdlg.h \
+ kxmlguiclient.h kxmlgui.h kxmlguibuilder.h kxmlguifactory.h \
+ kpixmapio.h kwordwrap.h \
+ kedittoolbar.h kdockwidget.h kanimwidget.h \
+ krootpixmap.h kaboutkde.h kaboutapplication.h \
+ kpanelapplet.h kpushbutton.h kdcopactionproxy.h kcolorcombo.h \
+ kpanelextension.h kcompletionbox.h ksqueezedtextlabel.h \
+ kcommand.h kwindowlistmenu.h kfontcombo.h kaccelgen.h ktip.h \
+ kdatewidget.h karrowbutton.h kguiitem.h kstdguiitem.h \
+ kstringvalidator.h kwindowinfo.h \
+ ktextedit.h kpassivepopup.h \
+ kdatetimewidget.h ktimewidget.h ktimezonewidget.h kscrollview.h \
+ kspell.h ksconfig.h kspelldlg.h ksyntaxhighlighter.h \
+ ktabbar.h ktabwidget.h ksplashscreen.h kconfigdialog.h \
+ kactionselector.h klanguagebutton.h klistviewsearchline.h \
+ kpixmapregionselectorwidget.h kpixmapregionselectordialog.h \
+ kiconviewsearchline.h ktoolbarlabelaction.h kshortcutdialog.h
+
+# the order of the sources isn't randomly (at least not completely).
+# the order is predictated by the use of X11 header files
+# the files on the first line need to occur first when compiling
+# with --enable-final since they use X defines that get undefined
+# in ksharedpixmap.cpp
+libkdeui_la_SOURCES = \
+ qxembed.cpp ksharedpixmap.cpp kpixmapio.cpp \
+ kpopupmenu.cpp ktoolbar.cpp kaction.cpp kstdaction.cpp \
+ kactioncollection.cpp kactionclasses.cpp \
+ kurllabel.cpp kmenubar.cpp kinputdialog.cpp \
+ knuminput.cpp klineedit.cpp klistview.cpp kprogress.cpp \
+ kcolordialog.cpp kselect.cpp kdatepicker.cpp \
+ kdatetbl.cpp kfontrequester.cpp kfontdialog.cpp ktabctl.cpp \
+ kstatusbar.cpp kmainwindow.cpp \
+ keditlistbox.cpp kscrollview.cpp \
+ kseparator.cpp krestrictedline.cpp \
+ kcolorbutton.cpp ksystemtray.cpp \
+ kbuttonbox.cpp keditcl1.cpp keditcl2.cpp kled.cpp \
+ kshortcutdialog_simple.ui kshortcutdialog_advanced.ui \
+ kshortcutdialog.cpp kkeybutton.cpp kkeydialog.cpp \
+ kruler.cpp kcursor.cpp klineeditdlg.cpp \
+ kcharselect.cpp kcolordrag.cpp \
+ knumvalidator.cpp kdialog.cpp kdialogbase.cpp \
+ kjanuswidget.cpp kaboutdialog.cpp \
+ kauthicon.cpp kmessagebox.cpp kdualcolorbutton.cpp \
+ ktoolbarradiogroup.cpp ktoolbarbutton.cpp \
+ ktextbrowser.cpp khelpmenu.cpp kswitchlanguagedialog.cpp \
+ kcmenumngr.cpp kpanelmenu.cpp \
+ kiconview.cpp klistbox.cpp kwordwrap.cpp kbugreport.cpp \
+ kcombobox.cpp kpassdlg.cpp kxmlguiclient.cpp kxmlguifactory.cpp \
+ kxmlguifactory_p.cpp kxmlguibuilder.cpp kedittoolbar.cpp \
+ kpanelappmenu.cpp kdockwidget.cpp kdockwidget_private.cpp \
+ kanimwidget.cpp krootpixmap.cpp kaboutkde.cpp \
+ kaboutapplication.cpp kpanelapplet.cpp kdcopactionproxy.cpp \
+ kcolorcombo.cpp kpushbutton.cpp kpanelextension.cpp \
+ kcompletionbox.cpp ksqueezedtextlabel.cpp kcmodule.cpp \
+ kcommand.cpp kwindowlistmenu.cpp kfontcombo.cpp ktip.cpp \
+ kdatewidget.cpp karrowbutton.cpp kmainwindowiface.cpp \
+ kmainwindowiface.skel kguiitem.cpp kstdguiitem.cpp \
+ kstringvalidator.cpp kactivelabel.cpp \
+ kwindowinfo.cpp ktextedit.cpp kwizard.cpp kpassivepopup.cpp \
+ ktoolbarhandler.cpp kdatetimewidget.cpp ktimewidget.cpp ktimezonewidget.cpp \
+ ksconfig.cpp kspelldlg.cpp \
+ kspell.cpp ksyntaxhighlighter.cpp ktabbar.cpp ktabwidget.cpp \
+ ksplashscreen.cpp kspellui.ui kconfigdialog.cpp \
+ kactionselector.cpp klanguagebutton.cpp klistviewsearchline.cpp \
+ kpixmapregionselectorwidget.cpp kpixmapregionselectordialog.cpp \
+ kwhatsthismanager.cpp kiconviewsearchline.cpp \
+ ktoolbarlabelaction.cpp
+
+noinst_HEADERS = kdockwidget_private.h kdockwidget_p.h klistviewlineedit.h \
+ kdialogbase_priv.h kaboutdialog_private.h kcursor_private.h \
+ kdepackages.h kxmlguifactory_p.h \
+ kstdaction_p.h kwhatsthismanager_p.h
+
+scripts_SCRIPTS = preparetips
+scriptsdir = $(kde_bindir)
+
+libkdeui_la_METASOURCES = AUTO
+libkdeui_la_NMCHECK = $(srcdir)/libkdeui.nmcheck
+libkdeui_la_NMCHECKWEAK = $(srcdir)/libkdeui_weak.nmcheck $(top_srcdir)/kdecore/libkdecore_weak.nmcheck \
+ $(top_srcdir)/dcop/libDCOP_weak.nmcheck $(top_srcdir)/kdecore/libqt-mt_weak.nmcheck
+
+rcdir = $(kde_confdir)/ui
+rc_DATA = ui_standards.rc
+
+EXTRA_DIST = CHANGES.kdatepicker USERS.kdatepicker kpixmapio-perf.png dcolorreset.xpm kpartgui.dtd dcolorarrow.xbm colors Mainpage.dox
+
+.PHONY: kdepackages
+
+kdepackages:
+ -rm $(srcdir)/kdepackages.h
+ curl "http://bugsold.kde.org/xml.cgi?data=versiontable" > tmp_download
+ echo "// DO NOT EDIT - EDIT bugs/Maintainers instead" > $(srcdir)/kdepackages.h
+ echo "const char * const packages[] = {" >> $(srcdir)/kdepackages.h
+ cat tmp_download | egrep "product|component" | grep -v "</product>" | \
+ sed -e "s,<product name=\"\([^\"]*\)\">,product=\"\1\"; component=\"general\",; \
+ s#<component>\([^<]*\)</component>#component=\"\1\"#" > tmp_download2
+ (while read i; do eval $$i; echo "\"$$product/$$component\","; done) < tmp_download2 | \
+ sed -e "s,/general\",/00general\"," | LC_ALL=C sort -u | \
+ grep -v 'valgrind/' | sed -e "s,/00general\",\"," >> $(srcdir)/kdepackages.h
+ echo "0 };" >> $(srcdir)/kdepackages.h
+ rm tmp_download2 tmp_download
+
+dummy.cpp:
+ echo "#ifdef _AIX" >dummy.cpp
+ echo "namespace {" >> dummy.cpp
+ echo "void *not_empty_file;" >>dummy.cpp
+ echo "}" >> dummy.cpp
+ echo "#endif" >> dummy.cpp
+
+DOXYGEN_REFERENCES = kdecore kdefx dcop kio kutils
+DOXYGEN_SET_INTERNAL_DOCS = YES
+include ../admin/Doxyfile.am
diff --git a/kdeui/README.kspell b/kdeui/README.kspell
new file mode 100644
index 000000000..9ae1afe84
--- /dev/null
+++ b/kdeui/README.kspell
@@ -0,0 +1,17 @@
+KSpell, by David Sweet
+----------------------
+KSpell provides an interface to ASpell and International ISpell 3.1. You
+should use it like a UI widget to provide spellchecking in your application.
+See kspell.h and http://www.chaos.umd.edu/~dsweet/KDE/KSpell for
+documentation.
+
+Settings
+--------
+A configuration dialog/widget is also provided. This class (KSpellConfig) acts
+not only as a widget allowing the user to set KSpell preferences, but also
+as a data abstraction class allowing you to get and set the preferences from
+within your program. You can pass an instance of KSpellConfig to KSpell
+and the spellchecker will run with the appropriate preference settings. The
+preferences, when saved (see kspelldlg.h) are saved globally. If needed,
+you can read them with KSpellDlg and set and use application-specific
+spellchecking settings.
diff --git a/kdeui/TODO.kspell b/kdeui/TODO.kspell
new file mode 100644
index 000000000..99c9df408
--- /dev/null
+++ b/kdeui/TODO.kspell
@@ -0,0 +1,34 @@
+from Daniel Naber, 2002-02-17:
+
+- there's the pspell library that offers an API to ispell and aspell,
+ it would make our code much simpler. It's not asynchronous by itself,
+ but maybe that can be added in KSpell.
+
+- add an option to ignore HTML/XML markup (-h). It's currently not
+ possible (i.e. it doesn't work) because we feed the text into ispell
+ line by line and it gets confused if tags are spread over more
+ than one line.
+
+from Wolfram Diestel:
+
+- add more charsets - need support from users of this charsets
+- rewrite the all the stuff to make it more asynchronous:
+ o one process should send data
+ o one process should read data
+ synchronization is done only by counting empty output lines from ispell
+
+old todo from David Sweet
+-------------------------
+
+properly handle capitalization on "Replace All" (in parseOneResponse())
+
+ensure that KSpell is reusable with the same replace/ignore lists
+ for multiple spellchecks in a single editing session
+
+allow saving of ignore/replace lists for multiple spellchecks of a
+ given document across multiple sessions
+
+add a "move()" function to move the dialog box (calling app should use this
+ in response to a misspelled() signal to move the d.b. out of the way
+ of the misspelled word)
+ This is done, but it doesn't work on the first call -- any ideas?
diff --git a/kdeui/TODO.xmlgui b/kdeui/TODO.xmlgui
new file mode 100644
index 000000000..3c3d4f8a4
--- /dev/null
+++ b/kdeui/TODO.xmlgui
@@ -0,0 +1,91 @@
+Bug with toolbars: a->saveState(); delete a; b->saveState(); delete b;
+will store wrong positions (index, offset and newline).
+When removing an xmlgui-client involves destroying toolbars, we need to save the
+whole set of toolbar positions of the mainwindow, into the xmlgui-client.
+
+Data structure:
+struct KToolBarPos {
+ short int index;
+ short int offset;
+ bool newLine;
+};
+typedef QValueVector<KToolBarPos> KToolBarPosList;
+
+API:
+KToolBarPosList KMainWindow::toolBarPositionList() const;
+
+The remaining problem is to know when to call it:
+* when we know in advance that we'll be able to remove toolbars?
+ (when creating the client we could remember if we created a toolbar and store
+ that bit of information, to re-use it when removing the client again)
+* when removing the first toolbar (of a given client); then we need
+to differentiate between first and following toolbars
+* always, if fast enough? With tons of plugins that might not be a good idea.
+
+========== More long term
+
+Problems:
+* No ui_standards.rc merging for parts
+* Confusing tag names (MergeLocal vs DefineGroup) for similar features
+* Two different merging codes (DOM-tree merging for ui_standards, xmlguifactory merging
+between xmlguiclients).
+
+Solution:
+* Get rid of the custom DOM-tree merging code from kxmlguiclient (for ui_standards.rc),
+use the existing merging code from kxmlguifactory instead
+* MergeLocal and DefineGroup are renamed MergeGroup, and append= becomes equivalent to group=.
+* Action is renamed MergeAction, and uses a new kind of place holder
+(one that matches actions by name during merging)
+So ui_standards.rc needs to be turned into <MergeAction>s and <MergeGroup>s only.
+* This also means that it will be possible to have only merge tags (and custom items
+like separators and tearoffhandle etc.) in a container, in which case it should
+not appear in the GUI. For that, ContainerNode must be improved so that it supports
+having no real GUI container attached to it.
+Big problem here. This means not building a container until we find that it
+really has an action (and the other way round: deleting a container when
+removing its last action, as we do, but still keeping a ContainerNode around...)
+(A ContainerNode is destroyed when its owner guiclient is removed from the factory,
+no change here).
+
+* A new XMLGUIClient provides the ui_standards.rc XML. It has the same instance
+as the mainwindow's guiclient. It provides no actions. No problems, since it
+only has <Merge*> tags.
+
+But that new xmlguiclient will 'own' the containers, so KEditToolbar will
+give wrong information.
+
+=====>
+This means the following KEditToolbar improvement is necessary:
+(it's an almost unrelated and necessary change there anyway, usability-wise)
+
+It would use merging, to present a merged view of the toolbars
+When the user inserts an action to a toolbar, we know which client the action
+belongs to, so we know which XML file to modify.
+BUT if the user adds actions in non-contiguous positions, we need to
+create <DefineGroup name="client1_tmp1"> groups, so that the merging actually does
+what the user asked for (!!)
+
+This allows to get rid of the "toolbar <client>" combobox stuff, and just have
+a list of toolbars there.
+
+Implementation: it can do this by providing its own KXMLGUIBuilder, to a
+new factory. The guiclients would be wrapped in a KXMLGUIClientProxy,
+which would forward the action() and domElement() calls - because a client
+can be in only one factory at a time.
+
+This custom builder needs to know about action plugging too, we don't really want
+to call KAction::plug here. So this would be 'virtualized' (new virtual, in a new
+interface to keep BC, that by default calls plug, but does something else in
+kedittoolbar's builder).
+
+
+======
+
+Additional benefits:
+* Any XML file can use the new <MergeAction> feature to modify the way a
+child client (e.g. a part) is getting merged, without adding group attributes
+to the child client (useful for a binary-only one, e.g.)
+
+--
+David Faure <faure@kde.org>
+Simon Hausmann <hausmann@kde.org>
diff --git a/kdeui/about/Makefile.am b/kdeui/about/Makefile.am
new file mode 100644
index 000000000..6bff21130
--- /dev/null
+++ b/kdeui/about/Makefile.am
@@ -0,0 +1,9 @@
+
+kde_infopage_datadir = $(kde_datadir)/kdeui/about
+kde_infopage_data_DATA = \
+ bar-bottom-left.png bar-top-right.png bar-bottom-middle.png bottom-left.png \
+ box-middle-left.png top-left.png bar-bottom-right.png bottom-middle.png \
+ box-middle-right.png top-middle.png bar-middle-left.png bottom-right.png \
+ box-top-left.png bar-middle-right.png box-bottom-left.png box-top-middle.png \
+ bar-top-left.png box-bottom-middle.png box-top-right.png bar-top-middle.png \
+ box-bottom-right.png kde_infopage.css kde_infopage_rtl.css
diff --git a/kdeui/about/bar-bottom-left.png b/kdeui/about/bar-bottom-left.png
new file mode 100644
index 000000000..30a323592
--- /dev/null
+++ b/kdeui/about/bar-bottom-left.png
Binary files differ
diff --git a/kdeui/about/bar-bottom-middle.png b/kdeui/about/bar-bottom-middle.png
new file mode 100644
index 000000000..b2ebbbed5
--- /dev/null
+++ b/kdeui/about/bar-bottom-middle.png
Binary files differ
diff --git a/kdeui/about/bar-bottom-right.png b/kdeui/about/bar-bottom-right.png
new file mode 100644
index 000000000..e664e1511
--- /dev/null
+++ b/kdeui/about/bar-bottom-right.png
Binary files differ
diff --git a/kdeui/about/bar-middle-left.png b/kdeui/about/bar-middle-left.png
new file mode 100644
index 000000000..72fda9ec2
--- /dev/null
+++ b/kdeui/about/bar-middle-left.png
Binary files differ
diff --git a/kdeui/about/bar-middle-right.png b/kdeui/about/bar-middle-right.png
new file mode 100644
index 000000000..eb8d3201c
--- /dev/null
+++ b/kdeui/about/bar-middle-right.png
Binary files differ
diff --git a/kdeui/about/bar-top-left.png b/kdeui/about/bar-top-left.png
new file mode 100644
index 000000000..b05fd216c
--- /dev/null
+++ b/kdeui/about/bar-top-left.png
Binary files differ
diff --git a/kdeui/about/bar-top-middle.png b/kdeui/about/bar-top-middle.png
new file mode 100644
index 000000000..387f81017
--- /dev/null
+++ b/kdeui/about/bar-top-middle.png
Binary files differ
diff --git a/kdeui/about/bar-top-right.png b/kdeui/about/bar-top-right.png
new file mode 100644
index 000000000..a552ff91d
--- /dev/null
+++ b/kdeui/about/bar-top-right.png
Binary files differ
diff --git a/kdeui/about/bottom-left.png b/kdeui/about/bottom-left.png
new file mode 100644
index 000000000..78c9fece3
--- /dev/null
+++ b/kdeui/about/bottom-left.png
Binary files differ
diff --git a/kdeui/about/bottom-middle.png b/kdeui/about/bottom-middle.png
new file mode 100644
index 000000000..41e52dd8a
--- /dev/null
+++ b/kdeui/about/bottom-middle.png
Binary files differ
diff --git a/kdeui/about/bottom-right.png b/kdeui/about/bottom-right.png
new file mode 100644
index 000000000..ef81b04a8
--- /dev/null
+++ b/kdeui/about/bottom-right.png
Binary files differ
diff --git a/kdeui/about/box-bottom-left.png b/kdeui/about/box-bottom-left.png
new file mode 100644
index 000000000..49b1be6d9
--- /dev/null
+++ b/kdeui/about/box-bottom-left.png
Binary files differ
diff --git a/kdeui/about/box-bottom-middle.png b/kdeui/about/box-bottom-middle.png
new file mode 100644
index 000000000..fd09ebb66
--- /dev/null
+++ b/kdeui/about/box-bottom-middle.png
Binary files differ
diff --git a/kdeui/about/box-bottom-right.png b/kdeui/about/box-bottom-right.png
new file mode 100644
index 000000000..4013c8ff4
--- /dev/null
+++ b/kdeui/about/box-bottom-right.png
Binary files differ
diff --git a/kdeui/about/box-middle-left.png b/kdeui/about/box-middle-left.png
new file mode 100644
index 000000000..1cd801a45
--- /dev/null
+++ b/kdeui/about/box-middle-left.png
Binary files differ
diff --git a/kdeui/about/box-middle-right.png b/kdeui/about/box-middle-right.png
new file mode 100644
index 000000000..54c5b0391
--- /dev/null
+++ b/kdeui/about/box-middle-right.png
Binary files differ
diff --git a/kdeui/about/box-top-left.png b/kdeui/about/box-top-left.png
new file mode 100644
index 000000000..29f91c129
--- /dev/null
+++ b/kdeui/about/box-top-left.png
Binary files differ
diff --git a/kdeui/about/box-top-middle.png b/kdeui/about/box-top-middle.png
new file mode 100644
index 000000000..5ea907597
--- /dev/null
+++ b/kdeui/about/box-top-middle.png
Binary files differ
diff --git a/kdeui/about/box-top-right.png b/kdeui/about/box-top-right.png
new file mode 100644
index 000000000..f86163176
--- /dev/null
+++ b/kdeui/about/box-top-right.png
Binary files differ
diff --git a/kdeui/about/kde_infopage.css b/kdeui/about/kde_infopage.css
new file mode 100644
index 000000000..69085675e
--- /dev/null
+++ b/kdeui/about/kde_infopage.css
@@ -0,0 +1,239 @@
+
+/*
+ * text styles
+ */
+
+img {margin: 0px; padding: 0px}
+body {margin: 0px; padding: 0px; background-color: #418ade;}
+.bar_text a {color: #008;}
+
+#subtext {
+ font-size: 10pt;
+ font-style: italic;
+}
+
+#nextlink {
+ margin-bottom: 0px;
+ text-align: right;
+ font-size: 10pt;
+}
+
+/*
+ * the header
+ */
+
+#header {
+ background-image: url(top-middle.png);
+ width: 100%;
+ height: 131px;
+}
+
+#headerL {
+ position: absolute;
+ background-image: url(top-left.png);
+ left: 0px;
+ height: 131px;
+ width: 147px;
+ z-index: 1;
+}
+
+#headerR {
+ position: absolute;
+ right: 0px;
+}
+
+/* title and tagline are part of the header diff */
+#title {
+ position: absolute;
+ top: 63px;
+ right: 100px;
+ margin-top: -1em;
+ text-align: right;
+ font-size: xx-large;
+ font-weight: bold;
+ text-shadow: #fff 0px 0px 5px;
+ color: #444;
+ z-index: 5;
+}
+
+#tagline {
+ position: absolute;
+ top: 70px;
+ right: 100px;
+ text-align: right;
+ font-size: large;
+ font-weight: bold;
+ text-shadow: #fff 0px 0px 5px;
+ color: #444;
+ z-index: 5;
+}
+
+/*
+ * the nav bar
+ */
+
+#bar {
+ width: 100%;
+ background-color: #5babe5;
+ padding-top: 0.5ex;
+ border-bottom: 1px solid black;
+ padding-bottom: 0.5ex;
+}
+
+#barCenter {
+ text-align: center;
+ color: #282828;
+ font-weight: bold;
+ font-size: small;
+}
+
+#barCenter a.selected, #barCenter a.selected:hover {
+ color: #282828;
+ text-decoration: none;
+ text-shadow: #fff 0px 0px 5px;
+}
+
+
+#barCenter li a:link, #barCenter li a:visited, #barCenter li a:active {
+ color: #282828;
+ text-decoration: none;
+ text-shadow: none;
+}
+
+#barCenter li a:hover {
+ color: #282828;
+ text-decoration: none;
+ text-shadow: #fff 0px 0px 6px;
+}
+
+#barCenter ul {
+ margin: 0;
+ padding: 0;
+}
+
+#barCenter li {
+ display: inline;
+}
+
+#barCenter li:not(:first-child):before { /* Aren't css3 selectors great? */
+ content: " · ";
+}
+
+/*
+ * the main box
+ */
+
+#box {
+ width: 90%;
+ margin-left: 5%;
+ margin-right: 5%;
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+
+#boxT {
+ width: 100%;
+ height: 22px;
+}
+
+#boxTL {
+ width: 25px;
+ height: 22px;
+ float: left;
+ background-image: url(box-top-left.png);
+}
+
+#boxTR {
+ width: 25px;
+ height: 22px;
+ float: right;
+ background-image: url(box-top-right.png);
+}
+
+#boxTC {
+ height: 22px;
+ margin-left: 25px;
+ margin-right: 25px;
+ background-image: url(box-top-middle.png);
+ background-repeat: repeat-x;
+}
+
+#boxL {
+ background-image: url(box-middle-left.png);
+ background-repeat: repeat-y;
+ background-position: left;
+ padding-left: 20px;
+}
+
+#boxCenter {
+ background-color: #dfe7f3;
+ background-position: center;
+ text-align: left;
+}
+
+#boxR {
+ background-image: url(box-middle-right.png);
+ background-repeat: repeat-y;
+ background-position: right;
+ padding-right: 20px;
+}
+
+#boxB {
+ width: 100%;
+ height: 22px;
+}
+
+#boxBL {
+ width: 25px;
+ height: 22px;
+ float: left;
+ background-image: url(box-bottom-left.png);
+}
+
+#boxBR {
+ width: 25px;
+ height: 22px;
+ float: right;
+ background-image: url(box-bottom-right.png);
+}
+
+#boxBC {
+ height: 22px;
+ margin-left: 25px;
+ margin-right: 25px;
+ background-image: url(box-bottom-middle.png);
+ background-repeat: repeat-x;
+}
+
+/*
+ * the footer
+ */
+
+#footer {
+ position: fixed;
+ background-image: url(bottom-middle.png);
+ width: 100%;
+ height: 100px;
+ z-index: -2;
+ bottom:0;
+}
+
+#footerL {
+ position: fixed;
+ background-image: url(bottom-left.png);
+ left: 0px;
+ width: 155px;
+ height: 100px;
+ z-index: -2;
+}
+
+#footerR {
+ position: fixed;
+ background-image: url(bottom-right.png);
+ right: 0px;
+ width: 429px;
+ height: 100px;
+ z-index: -1;
+}
+
+/* vim:set sw=2 et nocindent smartindent: */
diff --git a/kdeui/about/kde_infopage_rtl.css b/kdeui/about/kde_infopage_rtl.css
new file mode 100644
index 000000000..003330196
--- /dev/null
+++ b/kdeui/about/kde_infopage_rtl.css
@@ -0,0 +1,11 @@
+body {direction: rtl}
+
+#boxCenter {
+ text-align: right;
+}
+
+#nextlink {
+ text-align: left;
+}
+
+/* vim:set sw=2 et nocindent smartindent: */
diff --git a/kdeui/about/top-left.png b/kdeui/about/top-left.png
new file mode 100644
index 000000000..d7551c0d5
--- /dev/null
+++ b/kdeui/about/top-left.png
Binary files differ
diff --git a/kdeui/about/top-middle.png b/kdeui/about/top-middle.png
new file mode 100644
index 000000000..bb3fe7428
--- /dev/null
+++ b/kdeui/about/top-middle.png
Binary files differ
diff --git a/kdeui/about/usage-example.html b/kdeui/about/usage-example.html
new file mode 100644
index 000000000..fd78d8cfb
--- /dev/null
+++ b/kdeui/about/usage-example.html
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <meta name="generator" content=
+ "HTML Tidy for Linux/x86 (vers 1st August 2004), see www.w3.org" />
+
+ <style type="text/css">
+ /*<![CDATA[*/
+ @import "%1"; /* kde_infopage.css */
+ %1 /* maybe @import "kde_infopage_rtl.css"; */
+/* CHANGE ME or REMOVE ME */ @import "MY_CSS_FILE.css";
+ /*]]>*/
+ </style>
+
+ <title>%1</title>
+</head>
+
+<body>
+ <div id="header">
+ <div id="headerL"/>
+ <div id="headerR"/>
+
+ <div id="title">
+ %1 <!-- title -->
+ </div>
+
+ <div id="tagline">
+ %1 <!-- tagline -->
+ </div>
+ </div>
+
+ <!-- the bar -->
+ <div id="bar">
+ <div id="barT"><div id="barTL"/><div id="barTR"/><div id="barTC"/></div>
+ <div id="barL">
+ <div id="barR">
+ <div id="barCenter" class="bar_text">
+ <!-- text below the header graphics, above the main box, add your own %1s -->
+ </div>
+ </div>
+ </div>
+ <div id="barB"><div id="barBL"/><div id="barBR"/><div id="barBC"/></div>
+ </div>
+
+ <!-- the main text box -->
+ <div id="box">
+ <div id="boxT"><div id="boxTL"/><div id="boxTR"/><div id="boxTC"/></div>
+ <div id="boxL">
+ <div id="boxR">
+ <div id="boxCenter">
+ <!-- text in the main box, add your own %1s -->
+ </div>
+ </div>
+ </div>
+ <div id="boxB"><div id="boxBL"/><div id="boxBR"/><div id="boxBC"/></div>
+ </div>
+
+ <div id="footer"><div id="footerL"/><div id="footerR"/></div>
+</body>
+</html>
+<!-- vim:set sw=2 et nocindent smartindent: -->
diff --git a/kdeui/aboutkde.png b/kdeui/aboutkde.png
new file mode 100644
index 000000000..23b6e34f3
--- /dev/null
+++ b/kdeui/aboutkde.png
Binary files differ
diff --git a/kdeui/colors/Makefile.am b/kdeui/colors/Makefile.am
new file mode 100644
index 000000000..4a298bc56
--- /dev/null
+++ b/kdeui/colors/Makefile.am
@@ -0,0 +1,10 @@
+
+messages:
+ : > colors.cpp
+ list=`grep '^[0-9]' rgb.txt | tr ' ' ' ' | sed -e "s#^[0-9]* [0-9]* [0-9]* *##" | fgrep -v " " | fgrep -v gray | fgrep -v grey | LC_ALL=C sort -u` ;\
+ for i in $$list; do \
+ echo "i18n(\"color\", \"$$i\");" | sed -e "s#!# #g" >> colors.cpp ;\
+ done
+ $(XGETTEXT) colors.cpp -o $(podir)/kdelibs_colors.pot
+ -rm -f colors.cpp
+
diff --git a/kdeui/colors/README b/kdeui/colors/README
new file mode 100644
index 000000000..b631e99dd
--- /dev/null
+++ b/kdeui/colors/README
@@ -0,0 +1,2 @@
+The rgb.txt comes from x.org (xc/programs/rgb/rgb.txt)
+
diff --git a/kdeui/colors/rgb.txt b/kdeui/colors/rgb.txt
new file mode 100644
index 000000000..62eb8961e
--- /dev/null
+++ b/kdeui/colors/rgb.txt
@@ -0,0 +1,753 @@
+! $Xorg: rgb.txt,v 1.3 2000/08/17 19:54:00 cpqbld Exp $
+255 250 250 snow
+248 248 255 ghost white
+248 248 255 GhostWhite
+245 245 245 white smoke
+245 245 245 WhiteSmoke
+220 220 220 gainsboro
+255 250 240 floral white
+255 250 240 FloralWhite
+253 245 230 old lace
+253 245 230 OldLace
+250 240 230 linen
+250 235 215 antique white
+250 235 215 AntiqueWhite
+255 239 213 papaya whip
+255 239 213 PapayaWhip
+255 235 205 blanched almond
+255 235 205 BlanchedAlmond
+255 228 196 bisque
+255 218 185 peach puff
+255 218 185 PeachPuff
+255 222 173 navajo white
+255 222 173 NavajoWhite
+255 228 181 moccasin
+255 248 220 cornsilk
+255 255 240 ivory
+255 250 205 lemon chiffon
+255 250 205 LemonChiffon
+255 245 238 seashell
+240 255 240 honeydew
+245 255 250 mint cream
+245 255 250 MintCream
+240 255 255 azure
+240 248 255 alice blue
+240 248 255 AliceBlue
+230 230 250 lavender
+255 240 245 lavender blush
+255 240 245 LavenderBlush
+255 228 225 misty rose
+255 228 225 MistyRose
+255 255 255 white
+ 0 0 0 black
+ 47 79 79 dark slate gray
+ 47 79 79 DarkSlateGray
+ 47 79 79 dark slate grey
+ 47 79 79 DarkSlateGrey
+105 105 105 dim gray
+105 105 105 DimGray
+105 105 105 dim grey
+105 105 105 DimGrey
+112 128 144 slate gray
+112 128 144 SlateGray
+112 128 144 slate grey
+112 128 144 SlateGrey
+119 136 153 light slate gray
+119 136 153 LightSlateGray
+119 136 153 light slate grey
+119 136 153 LightSlateGrey
+190 190 190 gray
+190 190 190 grey
+211 211 211 light grey
+211 211 211 LightGrey
+211 211 211 light gray
+211 211 211 LightGray
+ 25 25 112 midnight blue
+ 25 25 112 MidnightBlue
+ 0 0 128 navy
+ 0 0 128 navy blue
+ 0 0 128 NavyBlue
+100 149 237 cornflower blue
+100 149 237 CornflowerBlue
+ 72 61 139 dark slate blue
+ 72 61 139 DarkSlateBlue
+106 90 205 slate blue
+106 90 205 SlateBlue
+123 104 238 medium slate blue
+123 104 238 MediumSlateBlue
+132 112 255 light slate blue
+132 112 255 LightSlateBlue
+ 0 0 205 medium blue
+ 0 0 205 MediumBlue
+ 65 105 225 royal blue
+ 65 105 225 RoyalBlue
+ 0 0 255 blue
+ 30 144 255 dodger blue
+ 30 144 255 DodgerBlue
+ 0 191 255 deep sky blue
+ 0 191 255 DeepSkyBlue
+135 206 235 sky blue
+135 206 235 SkyBlue
+135 206 250 light sky blue
+135 206 250 LightSkyBlue
+ 70 130 180 steel blue
+ 70 130 180 SteelBlue
+176 196 222 light steel blue
+176 196 222 LightSteelBlue
+173 216 230 light blue
+173 216 230 LightBlue
+176 224 230 powder blue
+176 224 230 PowderBlue
+175 238 238 pale turquoise
+175 238 238 PaleTurquoise
+ 0 206 209 dark turquoise
+ 0 206 209 DarkTurquoise
+ 72 209 204 medium turquoise
+ 72 209 204 MediumTurquoise
+ 64 224 208 turquoise
+ 0 255 255 cyan
+224 255 255 light cyan
+224 255 255 LightCyan
+ 95 158 160 cadet blue
+ 95 158 160 CadetBlue
+102 205 170 medium aquamarine
+102 205 170 MediumAquamarine
+127 255 212 aquamarine
+ 0 100 0 dark green
+ 0 100 0 DarkGreen
+ 85 107 47 dark olive green
+ 85 107 47 DarkOliveGreen
+143 188 143 dark sea green
+143 188 143 DarkSeaGreen
+ 46 139 87 sea green
+ 46 139 87 SeaGreen
+ 60 179 113 medium sea green
+ 60 179 113 MediumSeaGreen
+ 32 178 170 light sea green
+ 32 178 170 LightSeaGreen
+152 251 152 pale green
+152 251 152 PaleGreen
+ 0 255 127 spring green
+ 0 255 127 SpringGreen
+124 252 0 lawn green
+124 252 0 LawnGreen
+ 0 255 0 green
+127 255 0 chartreuse
+ 0 250 154 medium spring green
+ 0 250 154 MediumSpringGreen
+173 255 47 green yellow
+173 255 47 GreenYellow
+ 50 205 50 lime green
+ 50 205 50 LimeGreen
+154 205 50 yellow green
+154 205 50 YellowGreen
+ 34 139 34 forest green
+ 34 139 34 ForestGreen
+107 142 35 olive drab
+107 142 35 OliveDrab
+189 183 107 dark khaki
+189 183 107 DarkKhaki
+240 230 140 khaki
+238 232 170 pale goldenrod
+238 232 170 PaleGoldenrod
+250 250 210 light goldenrod yellow
+250 250 210 LightGoldenrodYellow
+255 255 224 light yellow
+255 255 224 LightYellow
+255 255 0 yellow
+255 215 0 gold
+238 221 130 light goldenrod
+238 221 130 LightGoldenrod
+218 165 32 goldenrod
+184 134 11 dark goldenrod
+184 134 11 DarkGoldenrod
+188 143 143 rosy brown
+188 143 143 RosyBrown
+205 92 92 indian red
+205 92 92 IndianRed
+139 69 19 saddle brown
+139 69 19 SaddleBrown
+160 82 45 sienna
+205 133 63 peru
+222 184 135 burlywood
+245 245 220 beige
+245 222 179 wheat
+244 164 96 sandy brown
+244 164 96 SandyBrown
+210 180 140 tan
+210 105 30 chocolate
+178 34 34 firebrick
+165 42 42 brown
+233 150 122 dark salmon
+233 150 122 DarkSalmon
+250 128 114 salmon
+255 160 122 light salmon
+255 160 122 LightSalmon
+255 165 0 orange
+255 140 0 dark orange
+255 140 0 DarkOrange
+255 127 80 coral
+240 128 128 light coral
+240 128 128 LightCoral
+255 99 71 tomato
+255 69 0 orange red
+255 69 0 OrangeRed
+255 0 0 red
+255 105 180 hot pink
+255 105 180 HotPink
+255 20 147 deep pink
+255 20 147 DeepPink
+255 192 203 pink
+255 182 193 light pink
+255 182 193 LightPink
+219 112 147 pale violet red
+219 112 147 PaleVioletRed
+176 48 96 maroon
+199 21 133 medium violet red
+199 21 133 MediumVioletRed
+208 32 144 violet red
+208 32 144 VioletRed
+255 0 255 magenta
+238 130 238 violet
+221 160 221 plum
+218 112 214 orchid
+186 85 211 medium orchid
+186 85 211 MediumOrchid
+153 50 204 dark orchid
+153 50 204 DarkOrchid
+148 0 211 dark violet
+148 0 211 DarkViolet
+138 43 226 blue violet
+138 43 226 BlueViolet
+160 32 240 purple
+147 112 219 medium purple
+147 112 219 MediumPurple
+216 191 216 thistle
+255 250 250 snow1
+238 233 233 snow2
+205 201 201 snow3
+139 137 137 snow4
+255 245 238 seashell1
+238 229 222 seashell2
+205 197 191 seashell3
+139 134 130 seashell4
+255 239 219 AntiqueWhite1
+238 223 204 AntiqueWhite2
+205 192 176 AntiqueWhite3
+139 131 120 AntiqueWhite4
+255 228 196 bisque1
+238 213 183 bisque2
+205 183 158 bisque3
+139 125 107 bisque4
+255 218 185 PeachPuff1
+238 203 173 PeachPuff2
+205 175 149 PeachPuff3
+139 119 101 PeachPuff4
+255 222 173 NavajoWhite1
+238 207 161 NavajoWhite2
+205 179 139 NavajoWhite3
+139 121 94 NavajoWhite4
+255 250 205 LemonChiffon1
+238 233 191 LemonChiffon2
+205 201 165 LemonChiffon3
+139 137 112 LemonChiffon4
+255 248 220 cornsilk1
+238 232 205 cornsilk2
+205 200 177 cornsilk3
+139 136 120 cornsilk4
+255 255 240 ivory1
+238 238 224 ivory2
+205 205 193 ivory3
+139 139 131 ivory4
+240 255 240 honeydew1
+224 238 224 honeydew2
+193 205 193 honeydew3
+131 139 131 honeydew4
+255 240 245 LavenderBlush1
+238 224 229 LavenderBlush2
+205 193 197 LavenderBlush3
+139 131 134 LavenderBlush4
+255 228 225 MistyRose1
+238 213 210 MistyRose2
+205 183 181 MistyRose3
+139 125 123 MistyRose4
+240 255 255 azure1
+224 238 238 azure2
+193 205 205 azure3
+131 139 139 azure4
+131 111 255 SlateBlue1
+122 103 238 SlateBlue2
+105 89 205 SlateBlue3
+ 71 60 139 SlateBlue4
+ 72 118 255 RoyalBlue1
+ 67 110 238 RoyalBlue2
+ 58 95 205 RoyalBlue3
+ 39 64 139 RoyalBlue4
+ 0 0 255 blue1
+ 0 0 238 blue2
+ 0 0 205 blue3
+ 0 0 139 blue4
+ 30 144 255 DodgerBlue1
+ 28 134 238 DodgerBlue2
+ 24 116 205 DodgerBlue3
+ 16 78 139 DodgerBlue4
+ 99 184 255 SteelBlue1
+ 92 172 238 SteelBlue2
+ 79 148 205 SteelBlue3
+ 54 100 139 SteelBlue4
+ 0 191 255 DeepSkyBlue1
+ 0 178 238 DeepSkyBlue2
+ 0 154 205 DeepSkyBlue3
+ 0 104 139 DeepSkyBlue4
+135 206 255 SkyBlue1
+126 192 238 SkyBlue2
+108 166 205 SkyBlue3
+ 74 112 139 SkyBlue4
+176 226 255 LightSkyBlue1
+164 211 238 LightSkyBlue2
+141 182 205 LightSkyBlue3
+ 96 123 139 LightSkyBlue4
+198 226 255 SlateGray1
+185 211 238 SlateGray2
+159 182 205 SlateGray3
+108 123 139 SlateGray4
+202 225 255 LightSteelBlue1
+188 210 238 LightSteelBlue2
+162 181 205 LightSteelBlue3
+110 123 139 LightSteelBlue4
+191 239 255 LightBlue1
+178 223 238 LightBlue2
+154 192 205 LightBlue3
+104 131 139 LightBlue4
+224 255 255 LightCyan1
+209 238 238 LightCyan2
+180 205 205 LightCyan3
+122 139 139 LightCyan4
+187 255 255 PaleTurquoise1
+174 238 238 PaleTurquoise2
+150 205 205 PaleTurquoise3
+102 139 139 PaleTurquoise4
+152 245 255 CadetBlue1
+142 229 238 CadetBlue2
+122 197 205 CadetBlue3
+ 83 134 139 CadetBlue4
+ 0 245 255 turquoise1
+ 0 229 238 turquoise2
+ 0 197 205 turquoise3
+ 0 134 139 turquoise4
+ 0 255 255 cyan1
+ 0 238 238 cyan2
+ 0 205 205 cyan3
+ 0 139 139 cyan4
+151 255 255 DarkSlateGray1
+141 238 238 DarkSlateGray2
+121 205 205 DarkSlateGray3
+ 82 139 139 DarkSlateGray4
+127 255 212 aquamarine1
+118 238 198 aquamarine2
+102 205 170 aquamarine3
+ 69 139 116 aquamarine4
+193 255 193 DarkSeaGreen1
+180 238 180 DarkSeaGreen2
+155 205 155 DarkSeaGreen3
+105 139 105 DarkSeaGreen4
+ 84 255 159 SeaGreen1
+ 78 238 148 SeaGreen2
+ 67 205 128 SeaGreen3
+ 46 139 87 SeaGreen4
+154 255 154 PaleGreen1
+144 238 144 PaleGreen2
+124 205 124 PaleGreen3
+ 84 139 84 PaleGreen4
+ 0 255 127 SpringGreen1
+ 0 238 118 SpringGreen2
+ 0 205 102 SpringGreen3
+ 0 139 69 SpringGreen4
+ 0 255 0 green1
+ 0 238 0 green2
+ 0 205 0 green3
+ 0 139 0 green4
+127 255 0 chartreuse1
+118 238 0 chartreuse2
+102 205 0 chartreuse3
+ 69 139 0 chartreuse4
+192 255 62 OliveDrab1
+179 238 58 OliveDrab2
+154 205 50 OliveDrab3
+105 139 34 OliveDrab4
+202 255 112 DarkOliveGreen1
+188 238 104 DarkOliveGreen2
+162 205 90 DarkOliveGreen3
+110 139 61 DarkOliveGreen4
+255 246 143 khaki1
+238 230 133 khaki2
+205 198 115 khaki3
+139 134 78 khaki4
+255 236 139 LightGoldenrod1
+238 220 130 LightGoldenrod2
+205 190 112 LightGoldenrod3
+139 129 76 LightGoldenrod4
+255 255 224 LightYellow1
+238 238 209 LightYellow2
+205 205 180 LightYellow3
+139 139 122 LightYellow4
+255 255 0 yellow1
+238 238 0 yellow2
+205 205 0 yellow3
+139 139 0 yellow4
+255 215 0 gold1
+238 201 0 gold2
+205 173 0 gold3
+139 117 0 gold4
+255 193 37 goldenrod1
+238 180 34 goldenrod2
+205 155 29 goldenrod3
+139 105 20 goldenrod4
+255 185 15 DarkGoldenrod1
+238 173 14 DarkGoldenrod2
+205 149 12 DarkGoldenrod3
+139 101 8 DarkGoldenrod4
+255 193 193 RosyBrown1
+238 180 180 RosyBrown2
+205 155 155 RosyBrown3
+139 105 105 RosyBrown4
+255 106 106 IndianRed1
+238 99 99 IndianRed2
+205 85 85 IndianRed3
+139 58 58 IndianRed4
+255 130 71 sienna1
+238 121 66 sienna2
+205 104 57 sienna3
+139 71 38 sienna4
+255 211 155 burlywood1
+238 197 145 burlywood2
+205 170 125 burlywood3
+139 115 85 burlywood4
+255 231 186 wheat1
+238 216 174 wheat2
+205 186 150 wheat3
+139 126 102 wheat4
+255 165 79 tan1
+238 154 73 tan2
+205 133 63 tan3
+139 90 43 tan4
+255 127 36 chocolate1
+238 118 33 chocolate2
+205 102 29 chocolate3
+139 69 19 chocolate4
+255 48 48 firebrick1
+238 44 44 firebrick2
+205 38 38 firebrick3
+139 26 26 firebrick4
+255 64 64 brown1
+238 59 59 brown2
+205 51 51 brown3
+139 35 35 brown4
+255 140 105 salmon1
+238 130 98 salmon2
+205 112 84 salmon3
+139 76 57 salmon4
+255 160 122 LightSalmon1
+238 149 114 LightSalmon2
+205 129 98 LightSalmon3
+139 87 66 LightSalmon4
+255 165 0 orange1
+238 154 0 orange2
+205 133 0 orange3
+139 90 0 orange4
+255 127 0 DarkOrange1
+238 118 0 DarkOrange2
+205 102 0 DarkOrange3
+139 69 0 DarkOrange4
+255 114 86 coral1
+238 106 80 coral2
+205 91 69 coral3
+139 62 47 coral4
+255 99 71 tomato1
+238 92 66 tomato2
+205 79 57 tomato3
+139 54 38 tomato4
+255 69 0 OrangeRed1
+238 64 0 OrangeRed2
+205 55 0 OrangeRed3
+139 37 0 OrangeRed4
+255 0 0 red1
+238 0 0 red2
+205 0 0 red3
+139 0 0 red4
+255 20 147 DeepPink1
+238 18 137 DeepPink2
+205 16 118 DeepPink3
+139 10 80 DeepPink4
+255 110 180 HotPink1
+238 106 167 HotPink2
+205 96 144 HotPink3
+139 58 98 HotPink4
+255 181 197 pink1
+238 169 184 pink2
+205 145 158 pink3
+139 99 108 pink4
+255 174 185 LightPink1
+238 162 173 LightPink2
+205 140 149 LightPink3
+139 95 101 LightPink4
+255 130 171 PaleVioletRed1
+238 121 159 PaleVioletRed2
+205 104 137 PaleVioletRed3
+139 71 93 PaleVioletRed4
+255 52 179 maroon1
+238 48 167 maroon2
+205 41 144 maroon3
+139 28 98 maroon4
+255 62 150 VioletRed1
+238 58 140 VioletRed2
+205 50 120 VioletRed3
+139 34 82 VioletRed4
+255 0 255 magenta1
+238 0 238 magenta2
+205 0 205 magenta3
+139 0 139 magenta4
+255 131 250 orchid1
+238 122 233 orchid2
+205 105 201 orchid3
+139 71 137 orchid4
+255 187 255 plum1
+238 174 238 plum2
+205 150 205 plum3
+139 102 139 plum4
+224 102 255 MediumOrchid1
+209 95 238 MediumOrchid2
+180 82 205 MediumOrchid3
+122 55 139 MediumOrchid4
+191 62 255 DarkOrchid1
+178 58 238 DarkOrchid2
+154 50 205 DarkOrchid3
+104 34 139 DarkOrchid4
+155 48 255 purple1
+145 44 238 purple2
+125 38 205 purple3
+ 85 26 139 purple4
+171 130 255 MediumPurple1
+159 121 238 MediumPurple2
+137 104 205 MediumPurple3
+ 93 71 139 MediumPurple4
+255 225 255 thistle1
+238 210 238 thistle2
+205 181 205 thistle3
+139 123 139 thistle4
+ 0 0 0 gray0
+ 0 0 0 grey0
+ 3 3 3 gray1
+ 3 3 3 grey1
+ 5 5 5 gray2
+ 5 5 5 grey2
+ 8 8 8 gray3
+ 8 8 8 grey3
+ 10 10 10 gray4
+ 10 10 10 grey4
+ 13 13 13 gray5
+ 13 13 13 grey5
+ 15 15 15 gray6
+ 15 15 15 grey6
+ 18 18 18 gray7
+ 18 18 18 grey7
+ 20 20 20 gray8
+ 20 20 20 grey8
+ 23 23 23 gray9
+ 23 23 23 grey9
+ 26 26 26 gray10
+ 26 26 26 grey10
+ 28 28 28 gray11
+ 28 28 28 grey11
+ 31 31 31 gray12
+ 31 31 31 grey12
+ 33 33 33 gray13
+ 33 33 33 grey13
+ 36 36 36 gray14
+ 36 36 36 grey14
+ 38 38 38 gray15
+ 38 38 38 grey15
+ 41 41 41 gray16
+ 41 41 41 grey16
+ 43 43 43 gray17
+ 43 43 43 grey17
+ 46 46 46 gray18
+ 46 46 46 grey18
+ 48 48 48 gray19
+ 48 48 48 grey19
+ 51 51 51 gray20
+ 51 51 51 grey20
+ 54 54 54 gray21
+ 54 54 54 grey21
+ 56 56 56 gray22
+ 56 56 56 grey22
+ 59 59 59 gray23
+ 59 59 59 grey23
+ 61 61 61 gray24
+ 61 61 61 grey24
+ 64 64 64 gray25
+ 64 64 64 grey25
+ 66 66 66 gray26
+ 66 66 66 grey26
+ 69 69 69 gray27
+ 69 69 69 grey27
+ 71 71 71 gray28
+ 71 71 71 grey28
+ 74 74 74 gray29
+ 74 74 74 grey29
+ 77 77 77 gray30
+ 77 77 77 grey30
+ 79 79 79 gray31
+ 79 79 79 grey31
+ 82 82 82 gray32
+ 82 82 82 grey32
+ 84 84 84 gray33
+ 84 84 84 grey33
+ 87 87 87 gray34
+ 87 87 87 grey34
+ 89 89 89 gray35
+ 89 89 89 grey35
+ 92 92 92 gray36
+ 92 92 92 grey36
+ 94 94 94 gray37
+ 94 94 94 grey37
+ 97 97 97 gray38
+ 97 97 97 grey38
+ 99 99 99 gray39
+ 99 99 99 grey39
+102 102 102 gray40
+102 102 102 grey40
+105 105 105 gray41
+105 105 105 grey41
+107 107 107 gray42
+107 107 107 grey42
+110 110 110 gray43
+110 110 110 grey43
+112 112 112 gray44
+112 112 112 grey44
+115 115 115 gray45
+115 115 115 grey45
+117 117 117 gray46
+117 117 117 grey46
+120 120 120 gray47
+120 120 120 grey47
+122 122 122 gray48
+122 122 122 grey48
+125 125 125 gray49
+125 125 125 grey49
+127 127 127 gray50
+127 127 127 grey50
+130 130 130 gray51
+130 130 130 grey51
+133 133 133 gray52
+133 133 133 grey52
+135 135 135 gray53
+135 135 135 grey53
+138 138 138 gray54
+138 138 138 grey54
+140 140 140 gray55
+140 140 140 grey55
+143 143 143 gray56
+143 143 143 grey56
+145 145 145 gray57
+145 145 145 grey57
+148 148 148 gray58
+148 148 148 grey58
+150 150 150 gray59
+150 150 150 grey59
+153 153 153 gray60
+153 153 153 grey60
+156 156 156 gray61
+156 156 156 grey61
+158 158 158 gray62
+158 158 158 grey62
+161 161 161 gray63
+161 161 161 grey63
+163 163 163 gray64
+163 163 163 grey64
+166 166 166 gray65
+166 166 166 grey65
+168 168 168 gray66
+168 168 168 grey66
+171 171 171 gray67
+171 171 171 grey67
+173 173 173 gray68
+173 173 173 grey68
+176 176 176 gray69
+176 176 176 grey69
+179 179 179 gray70
+179 179 179 grey70
+181 181 181 gray71
+181 181 181 grey71
+184 184 184 gray72
+184 184 184 grey72
+186 186 186 gray73
+186 186 186 grey73
+189 189 189 gray74
+189 189 189 grey74
+191 191 191 gray75
+191 191 191 grey75
+194 194 194 gray76
+194 194 194 grey76
+196 196 196 gray77
+196 196 196 grey77
+199 199 199 gray78
+199 199 199 grey78
+201 201 201 gray79
+201 201 201 grey79
+204 204 204 gray80
+204 204 204 grey80
+207 207 207 gray81
+207 207 207 grey81
+209 209 209 gray82
+209 209 209 grey82
+212 212 212 gray83
+212 212 212 grey83
+214 214 214 gray84
+214 214 214 grey84
+217 217 217 gray85
+217 217 217 grey85
+219 219 219 gray86
+219 219 219 grey86
+222 222 222 gray87
+222 222 222 grey87
+224 224 224 gray88
+224 224 224 grey88
+227 227 227 gray89
+227 227 227 grey89
+229 229 229 gray90
+229 229 229 grey90
+232 232 232 gray91
+232 232 232 grey91
+235 235 235 gray92
+235 235 235 grey92
+237 237 237 gray93
+237 237 237 grey93
+240 240 240 gray94
+240 240 240 grey94
+242 242 242 gray95
+242 242 242 grey95
+245 245 245 gray96
+245 245 245 grey96
+247 247 247 gray97
+247 247 247 grey97
+250 250 250 gray98
+250 250 250 grey98
+252 252 252 gray99
+252 252 252 grey99
+255 255 255 gray100
+255 255 255 grey100
+169 169 169 dark grey
+169 169 169 DarkGrey
+169 169 169 dark gray
+169 169 169 DarkGray
+0 0 139 dark blue
+0 0 139 DarkBlue
+0 139 139 dark cyan
+0 139 139 DarkCyan
+139 0 139 dark magenta
+139 0 139 DarkMagenta
+139 0 0 dark red
+139 0 0 DarkRed
+144 238 144 light green
+144 238 144 LightGreen
diff --git a/kdeui/dcolorarrow.xbm b/kdeui/dcolorarrow.xbm
new file mode 100644
index 000000000..24cabac69
--- /dev/null
+++ b/kdeui/dcolorarrow.xbm
@@ -0,0 +1,6 @@
+#define dcolorarrow_width 12
+#define dcolorarrow_height 12
+static const unsigned char dcolorarrow_bits[] = {
+ 0x08, 0x00, 0x0c, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x0e, 0x01, 0x0c, 0x01,
+ 0x08, 0x01, 0x00, 0x01, 0xe0, 0x0f, 0xc0, 0x07, 0x80, 0x03, 0x00, 0x01,
+ };
diff --git a/kdeui/dcolorreset.xpm b/kdeui/dcolorreset.xpm
new file mode 100644
index 000000000..4884a3e12
--- /dev/null
+++ b/kdeui/dcolorreset.xpm
@@ -0,0 +1,19 @@
+/* XPM */
+const char * const dcolorreset_xpm[] = {
+"12 12 4 1",
+" c None",
+". c #808080",
+"+ c #000000",
+"@ c #FFFFFF",
+"........ ",
+".++++++. ",
+".++++++. ",
+".++++++. ",
+".++++++.....",
+".++++++.@@@.",
+".++++++.@@@.",
+"........@@@.",
+" .@@@@@@.",
+" .@@@@@@.",
+" .@@@@@@.",
+" ........"};
diff --git a/kdeui/kaboutapplication.cpp b/kdeui/kaboutapplication.cpp
new file mode 100644
index 000000000..594e2a1f5
--- /dev/null
+++ b/kdeui/kaboutapplication.cpp
@@ -0,0 +1,188 @@
+/*
+ * This file is part of the KDE Libraries
+ * Copyright (C) 2000 Waldo Bastian (bastian@kde.org) and
+ * Espen Sand (espen@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+// I (espen) prefer that header files are included alphabetically
+
+#include <qlabel.h>
+#include <kaboutapplication.h>
+#include <kaboutdialog_private.h>
+#include <kaboutdata.h>
+#include <kapplication.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kurllabel.h>
+#include <kactivelabel.h>
+#include "ktextedit.h"
+
+KAboutApplication::KAboutApplication( QWidget *parent, const char *name,
+ bool modal )
+ :KAboutDialog( AbtTabbed|AbtProduct,
+ kapp ? kapp->caption() : QString::null,
+ Close, Close,
+ parent, name, modal )
+{
+ buildDialog(KGlobal::instance()->aboutData());
+}
+
+KAboutApplication::KAboutApplication( const KAboutData *aboutData, QWidget *parent,
+ const char *name, bool modal )
+ :KAboutDialog( AbtTabbed|AbtProduct, aboutData->programName(), Close, Close,
+ parent, name, modal )
+{
+ buildDialog(aboutData);
+}
+
+void KAboutApplication::buildDialog( const KAboutData *aboutData )
+{
+ if( !aboutData )
+ {
+ //
+ // Recovery
+ //
+
+ //i18n "??" is displayed as (pseudo-)version when no data is known about the application
+ setProduct( kapp ? kapp->caption() : QString::null, i18n("??"), QString::null, QString::null );
+ KAboutContainer *appPage = addContainerPage( i18n("&About"));
+
+ QString appPageText =
+ i18n("No information available.\n"
+ "The supplied KAboutData object does not exist.");
+ QLabel *appPageLabel = new QLabel( "\n\n\n\n"+appPageText+"\n\n\n\n", 0 );
+ appPage->addWidget( appPageLabel );
+ return;
+ }
+
+ setProduct( aboutData->programName(), aboutData->version(),
+ QString::null, QString::null );
+
+ if (!aboutData->programLogo().isNull())
+ setProgramLogo( aboutData->programLogo() );
+
+ QString appPageText = aboutData->shortDescription() + "\n";
+
+ if (!aboutData->otherText().isEmpty())
+ appPageText += "\n" + aboutData->otherText()+"\n";
+
+ if (!aboutData->copyrightStatement().isEmpty())
+ appPageText += "\n" + aboutData->copyrightStatement()+"\n";
+
+ KAboutContainer *appPage = addContainerPage( i18n("&About"));
+
+ QLabel *appPageLabel = new QLabel( appPageText, 0 );
+ appPage->addWidget( appPageLabel );
+
+ if (!aboutData->homepage().isEmpty())
+ {
+ KURLLabel *url = new KURLLabel();
+ url->setText(aboutData->homepage());
+ url->setURL(aboutData->homepage());
+ appPage->addWidget( url );
+ connect( url, SIGNAL(leftClickedURL(const QString &)),
+ this, SLOT(openURLSlot(const QString &)));
+ }
+
+ int authorCount = aboutData->authors().count();
+ if (authorCount)
+ {
+ QString authorPageTitle = authorCount == 1 ?
+ i18n("A&uthor") : i18n("A&uthors");
+ KAboutContainer *authorPage = addScrolledContainerPage( authorPageTitle );
+
+ if (!aboutData->customAuthorTextEnabled() || !aboutData->customAuthorRichText().isEmpty ())
+ {
+ QString text;
+ KActiveLabel* activeLabel = new KActiveLabel( authorPage );
+ if (!aboutData->customAuthorTextEnabled())
+ {
+ if ( aboutData->bugAddress().isEmpty() || aboutData->bugAddress() == "submit@bugs.kde.org")
+ text = i18n( "Please use <a href=\"http://bugs.kde.org\">http://bugs.kde.org</a> to report bugs.\n" );
+ else {
+ if( aboutData->authors().count() == 1 && ( aboutData->authors().first().emailAddress() == aboutData->bugAddress() ) )
+ {
+ text = i18n( "Please report bugs to <a href=\"mailto:%1\">%2</a>.\n" ).arg( aboutData->authors().first().emailAddress() ).arg( aboutData->authors().first().emailAddress() );
+ }
+ else {
+ text = i18n( "Please report bugs to <a href=\"mailto:%1\">%2</a>.\n" ).arg(aboutData->bugAddress()).arg(aboutData->bugAddress() );
+ }
+ }
+ }
+ else
+ {
+ text = aboutData->customAuthorRichText();
+ }
+ activeLabel->setText( text );
+ authorPage->addWidget( activeLabel );
+ }
+
+ QValueList<KAboutPerson>::ConstIterator it;
+ for (it = aboutData->authors().begin();
+ it != aboutData->authors().end(); ++it)
+ {
+ authorPage->addPerson( (*it).name(), (*it).emailAddress(),
+ (*it).webAddress(), (*it).task() );
+ }
+ }
+
+ int creditsCount = aboutData->credits().count();
+ if (creditsCount)
+ {
+ KAboutContainer *creditsPage =
+ addScrolledContainerPage( i18n("&Thanks To") );
+ QValueList<KAboutPerson>::ConstIterator it;
+ for (it = aboutData->credits().begin();
+ it != aboutData->credits().end(); ++it)
+ {
+ creditsPage->addPerson( (*it).name(), (*it).emailAddress(),
+ (*it).webAddress(), (*it).task() );
+ }
+ }
+
+ const QValueList<KAboutTranslator> translatorList = aboutData->translators();
+
+ if(translatorList.count() > 0)
+ {
+ QString text = "<qt>";
+
+ QValueList<KAboutTranslator>::ConstIterator it;
+ for(it = translatorList.begin(); it != translatorList.end(); ++it)
+ {
+ text += QString("<p>%1<br>&nbsp;&nbsp;&nbsp;"
+ "<a href=\"mailto:%2\">%2</a></p>")
+ .arg((*it).name())
+ .arg((*it).emailAddress())
+ .arg((*it).emailAddress());
+ }
+
+ text += KAboutData::aboutTranslationTeam() + "</qt>";
+ addTextPage( i18n("T&ranslation"), text, true);
+ }
+
+ if (!aboutData->license().isEmpty() )
+ {
+ addLicensePage( i18n("&License Agreement"), aboutData->license() );
+ }
+
+ //
+ // Make sure the dialog has a reasonable width
+ //
+ setInitialSize( QSize(400,1) );
+}
diff --git a/kdeui/kaboutapplication.h b/kdeui/kaboutapplication.h
new file mode 100644
index 000000000..b3c0ea632
--- /dev/null
+++ b/kdeui/kaboutapplication.h
@@ -0,0 +1,94 @@
+/*
+ * This file is part of the KDE Libraries
+ * Copyright (C) 2000 Waldo Bastian (bastian@kde.org) and
+ * Espen Sand (espen@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef _KABOUT_APPLICATION_H_
+#define _KABOUT_APPLICATION_H_
+
+#include <kaboutdata.h>
+#include <kaboutdialog.h>
+
+/**
+ * @short Standard "About Application" dialog box.
+ *
+ * This class provides the standard "About Application" dialog box
+ * that is used by KHelpMenu. It uses the information of the global
+ * KAboutData that is specified at the start of your program in
+ * main(). Normally you should not use this class directly but rather
+ * the KHelpMenu class or even better just subclass your toplevel
+ * window from KMainWindow. If you do the latter, the help menu and
+ * thereby this dialog box is available through the
+ * KMainWindow::helpMenu() function.
+ *
+ * @author Waldo Bastian (bastian@kde.org) and Espen Sand (espen@kde.org)
+ */
+
+class KDEUI_EXPORT KAboutApplication : public KAboutDialog
+{
+ public:
+ /**
+ * Constructor. Creates a fully featured "About Application" dialog box.
+ * Note that this dialog is made modeless in the KHelpMenu class so
+ * the users may expect a modeless dialog.
+ *
+ * @param parent The parent of the dialog box. You should use the
+ * toplevel window so that the dialog becomes centered.
+ * @param name Internal name of the widget. This name is not used in the
+ * caption.
+ * @param modal If false, this widget will be modeless and must be
+ * made visible using QWidget::show(). Otherwise it will be
+ * modal and must be made visible using QWidget::exec().
+ */
+ KAboutApplication( QWidget *parent=0, const char *name=0, bool modal=true );
+
+ /**
+ * Constructor. Mostly does the same stuff as the previous constructor, except
+ * that it can take a custom KAboutData object instead of the one specified
+ * in your main() function. This is especially useful for applications
+ * which are implemented as (dynamically loaded) libraries, e.g. panel
+ * applets.
+ *
+ * @param aboutData A pointer to a KAboutData object which data
+ * will be used for filling the dialog.
+ * @param parent The parent of the dialog box. You should use the
+ * toplevel window so that the dialog becomes centered.
+ * @param name Internal name of the widget. This name is not used in the
+ * caption.
+ * @param modal If false, this widget will be modeless and must be
+ * made visible using QWidget::show(). Otherwise it will be
+ * modal and must be made visible using QWidget::exec().
+ */
+ KAboutApplication( const KAboutData *aboutData, QWidget *parent=0, const char *name=0, bool modal=true );
+
+/*
+ FIXME: The two constructors should be replaced with the following after the lib freeze:
+
+ KAboutApplication( const KAboutData *aboutData=0, QWidget *parent=0, const char *name=0, bool modal=true );
+
+ This will make buildDialog() obsolete as well (Frerich).
+*/
+ protected:
+ void buildDialog( const KAboutData *aboutData );
+};
+
+
+#endif
+
diff --git a/kdeui/kaboutdialog.cpp b/kdeui/kaboutdialog.cpp
new file mode 100644
index 000000000..3e534acfd
--- /dev/null
+++ b/kdeui/kaboutdialog.cpp
@@ -0,0 +1,1797 @@
+/*
+ * This file is part of the KDE Libraries
+ * Copyright (C) 1999-2001 Mirko Boehm <mirko@kde.org> and
+ * Espen Sand <espensa@online.no>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <qclipboard.h>
+#include <qimage.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <ktextedit.h>
+#include <qobjectlist.h>
+#include <qpainter.h>
+#include <qrect.h>
+#include <qtabwidget.h>
+#include <qtabbar.h>
+
+#include <kapplication.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+#include <klocale.h>
+#include <ktextbrowser.h>
+#include <kurllabel.h>
+#include <kaboutdialog.h>
+#include <kaboutdialog_private.h>
+#include <kdebug.h>
+
+//MOC_SKIP_BEGIN
+template class QPtrList<KAboutContributor>;
+//MOC_SKIP_END
+
+#define WORKTEXT_IDENTATION 16
+#define Grid 3
+
+// ##############################################################
+// MOC OUTPUT FILES:
+#include "kaboutdialog.moc"
+#include "kaboutdialog_private.moc"
+// ##############################################################
+
+class KAboutTabWidget : public QTabWidget
+{
+public:
+ KAboutTabWidget( QWidget* parent ) : QTabWidget( parent ) {}
+ QSize sizeHint() const {
+ return QTabWidget::sizeHint().expandedTo( tabBar()->sizeHint() + QSize(4,4) );
+ }
+};
+
+
+
+
+KAboutContributor::KAboutContributor( QWidget *_parent, const char *wname,
+ const QString &_name,const QString &_email,
+ const QString &_url, const QString &_work,
+ bool showHeader, bool showFrame,
+ bool showBold )
+ : QFrame( _parent, wname ), mShowHeader(showHeader), mShowBold(showBold), d(0)
+{
+ if( showFrame )
+ {
+ setFrameStyle(QFrame::Panel | QFrame::Raised);
+ }
+
+ mLabel[0] = new QLabel( this );
+ mLabel[1] = new QLabel( this );
+ mLabel[2] = new QLabel( this );
+ mLabel[3] = new QLabel( this );
+ mText[0] = new QLabel( this );
+ mText[1] = new KURLLabel( this );
+ mText[2] = new KURLLabel( this );
+ mText[3] = new QLabel( this );
+
+ setName( _name, i18n("Author"), false );
+ setEmail( _email, i18n("Email"), false );
+ setURL( _url, i18n("Homepage"), false );
+ setWork( _work, i18n("Task"), false );
+
+ KURLLabel *kurl = static_cast<KURLLabel *>(mText[1]);
+ kurl->setFloat(true);
+ kurl->setUnderline(true);
+ kurl->setMargin(0);
+ connect(kurl, SIGNAL(leftClickedURL(const QString &)),
+ SLOT(emailClickedSlot(const QString &)));
+
+ kurl = static_cast<KURLLabel *>(mText[2]);
+ kurl->setFloat(true);
+ kurl->setUnderline(true);
+ kurl->setMargin(0);
+ connect(kurl, SIGNAL(leftClickedURL(const QString &)),
+ SLOT(urlClickedSlot(const QString &)));
+
+ mLabel[3]->setAlignment( AlignTop );
+
+ fontChange( font() );
+ updateLayout();
+}
+
+
+void KAboutContributor::setName( const QString &_text, const QString &_header,
+ bool _update )
+{
+ mLabel[0]->setText(_header);
+ mText[0]->setText(_text);
+ if( _update ) { updateLayout(); }
+}
+
+
+void KAboutContributor::setEmail( const QString &_text, const QString &_header,
+ bool _update )
+{
+ mLabel[1]->setText(_header);
+ KURLLabel* const kurl = static_cast<KURLLabel *>(mText[1]);
+ kurl->setText(_text);
+ kurl->setURL(_text);
+ if( _update ) { updateLayout(); }
+}
+
+
+void KAboutContributor::setURL( const QString &_text, const QString &_header,
+ bool _update )
+{
+ mLabel[2]->setText(_header);
+ KURLLabel* const kurl = static_cast<KURLLabel *>(mText[2]);
+ kurl->setText(_text);
+ kurl->setURL(_text);
+ if( _update ) { updateLayout(); }
+}
+
+
+void KAboutContributor::setWork( const QString &_text, const QString &_header,
+ bool _update )
+{
+ mLabel[3]->setText(_header);
+ mText[3]->setText(_text);
+ if( _update ) { updateLayout(); }
+}
+
+
+QString KAboutContributor::getName( void ) const
+{
+ return mText[0]->text();
+}
+
+
+QString KAboutContributor::getEmail( void ) const
+{
+ return mText[1]->text();
+}
+
+
+QString KAboutContributor::getURL( void ) const
+{
+ return mText[2]->text();
+}
+
+
+QString KAboutContributor::getWork( void ) const
+{
+ return mText[3]->text();
+}
+
+
+
+void KAboutContributor::updateLayout( void )
+{
+ delete layout();
+
+ int row = 0;
+ if( !mText[0]->text().isEmpty() ) { ++row; }
+ if( !mText[1]->text().isEmpty() ) { ++row; }
+ if( !mText[2]->text().isEmpty() ) { ++row; }
+ if( !mText[3]->text().isEmpty() ) { ++row; }
+
+
+ QGridLayout *gbox;
+ if( row == 0 )
+ {
+ gbox = new QGridLayout( this, 1, 1, 0 );
+ for( int i=0; i<4; ++i )
+ {
+ mLabel[i]->hide();
+ mText[i]->hide();
+ }
+ }
+ else
+ {
+ if( mText[0]->text().isEmpty() && !mShowHeader )
+ {
+ gbox = new QGridLayout( this, row, 1, frameWidth()+1, 2 );
+ }
+ else
+ {
+ gbox = new QGridLayout( this, row, 2, frameWidth()+1, 2 );
+ if( !mShowHeader )
+ {
+ gbox->addColSpacing( 0, KDialog::spacingHint()*2 );
+ }
+ gbox->setColStretch( 1, 10 );
+ }
+
+ for( int i=0, r=0; i<4; ++i )
+ {
+ mLabel[i]->setFixedHeight( fontMetrics().lineSpacing() );
+ if( i != 3 )
+ {
+ mText[i]->setFixedHeight( fontMetrics().lineSpacing() );
+ }
+
+ if( !mText[i]->text().isEmpty() )
+ {
+ if( mShowHeader )
+ {
+ gbox->addWidget( mLabel[i], r, 0, AlignLeft );
+ gbox->addWidget( mText[i], r, 1, AlignLeft );
+ mLabel[i]->show();
+ mText[i]->show();
+ }
+ else
+ {
+ mLabel[i]->hide();
+ if( !i )
+ {
+ gbox->addMultiCellWidget( mText[i], r, r, 0, 1, AlignLeft );
+ }
+ else
+ {
+ gbox->addWidget( mText[i], r, 1, AlignLeft );
+ }
+ mText[i]->show();
+ }
+ ++r;
+ }
+ else
+ {
+ mLabel[i]->hide();
+ mText[i]->hide();
+ }
+ }
+ }
+
+ gbox->activate();
+ setMinimumSize( sizeHint() );
+}
+
+
+void KAboutContributor::fontChange( const QFont &/*oldFont*/ )
+{
+ if( mShowBold )
+ {
+ QFont f( font() );
+ f.setBold( true );
+ mText[0]->setFont( f );
+ }
+ update();
+}
+
+
+QSize KAboutContributor::sizeHint( void ) const
+{
+ return minimumSizeHint();
+}
+
+
+void KAboutContributor::urlClickedSlot( const QString &u )
+{
+ emit openURL(u);
+}
+
+
+void KAboutContributor::emailClickedSlot( const QString &e )
+{
+ emit sendEmail( mText[0]->text(), e ) ;
+}
+
+
+//
+// Internal widget for the KAboutDialog class.
+//
+KAboutContainerBase::KAboutContainerBase( int layoutType, QWidget *_parent,
+ char *_name )
+ : QWidget( _parent, _name ),
+ mImageLabel(0), mTitleLabel(0), mIconLabel(0),mVersionLabel(0),
+ mAuthorLabel(0), mImageFrame(0),mPageTab(0),mPlainSpace(0),d(0)
+{
+ mTopLayout = new QVBoxLayout( this, 0, KDialog::spacingHint() );
+ if( !mTopLayout ) { return; }
+
+ if( layoutType & AbtImageOnly )
+ {
+ layoutType &= ~(AbtImageLeft|AbtImageRight|AbtTabbed|AbtPlain);
+ }
+ if( layoutType & AbtImageLeft )
+ {
+ layoutType &= ~AbtImageRight;
+ }
+
+ if( layoutType & AbtTitle )
+ {
+ mTitleLabel = new QLabel( this, "title" );
+ mTitleLabel->setAlignment(AlignCenter);
+ mTopLayout->addWidget( mTitleLabel );
+ mTopLayout->addSpacing( KDialog::spacingHint() );
+ }
+
+ if( layoutType & AbtProduct )
+ {
+ QWidget* const productArea = new QWidget( this, "area" );
+ mTopLayout->addWidget( productArea, 0, QApplication::reverseLayout() ? AlignRight : AlignLeft );
+
+ QHBoxLayout* const hbox = new QHBoxLayout(productArea,0,KDialog::spacingHint());
+ if( !hbox ) { return; }
+
+ mIconLabel = new QLabel( productArea );
+ hbox->addWidget( mIconLabel, 0, AlignLeft|AlignHCenter );
+
+ QVBoxLayout* const vbox = new QVBoxLayout();
+ if( !vbox ) { return; }
+ hbox->addLayout( vbox );
+
+ mVersionLabel = new QLabel( productArea, "version" );
+ mAuthorLabel = new QLabel( productArea, "author" );
+ vbox->addWidget( mVersionLabel );
+ vbox->addWidget( mAuthorLabel );
+ hbox->activate();
+
+ mTopLayout->addSpacing( KDialog::spacingHint() );
+ }
+
+ QHBoxLayout* const hbox = new QHBoxLayout();
+ if( !hbox ) { return; }
+ mTopLayout->addLayout( hbox, 10 );
+
+ if( layoutType & AbtImageLeft )
+ {
+ QVBoxLayout* vbox = new QVBoxLayout();
+ hbox->addLayout(vbox);
+ vbox->addSpacing(1);
+ mImageFrame = new QFrame( this );
+ setImageFrame( true );
+ vbox->addWidget( mImageFrame );
+ vbox->addSpacing(1);
+
+ vbox = new QVBoxLayout( mImageFrame, 1 );
+ mImageLabel = new KImageTrackLabel( mImageFrame );
+ connect( mImageLabel, SIGNAL(mouseTrack( int, const QMouseEvent * )),
+ SLOT( slotMouseTrack( int, const QMouseEvent * )) );
+ vbox->addStretch(10);
+ vbox->addWidget( mImageLabel );
+ vbox->addStretch(10);
+ vbox->activate();
+ }
+
+ if( layoutType & AbtTabbed )
+ {
+ mPageTab = new KAboutTabWidget( this );
+ if( !mPageTab ) { return; }
+ hbox->addWidget( mPageTab, 10 );
+ }
+ else if( layoutType & AbtImageOnly )
+ {
+ mImageFrame = new QFrame( this );
+ setImageFrame( true );
+ hbox->addWidget( mImageFrame, 10 );
+
+ QGridLayout* const gbox = new QGridLayout(mImageFrame, 3, 3, 1, 0 );
+ gbox->setRowStretch( 0, 10 );
+ gbox->setRowStretch( 2, 10 );
+ gbox->setColStretch( 0, 10 );
+ gbox->setColStretch( 2, 10 );
+
+ mImageLabel = new KImageTrackLabel( mImageFrame );
+ connect( mImageLabel, SIGNAL(mouseTrack( int, const QMouseEvent * )),
+ SLOT( slotMouseTrack( int, const QMouseEvent * )) );
+ gbox->addWidget( mImageLabel, 1, 1 );
+ gbox->activate();
+ }
+ else
+ {
+ mPlainSpace = new QFrame( this );
+ if( !mPlainSpace ) { return; }
+ hbox->addWidget( mPlainSpace, 10 );
+ }
+
+ if( layoutType & AbtImageRight )
+ {
+ QVBoxLayout *vbox = new QVBoxLayout();
+ hbox->addLayout(vbox);
+ vbox->addSpacing(1);
+ mImageFrame = new QFrame( this );
+ setImageFrame( true );
+ vbox->addWidget( mImageFrame );
+ vbox->addSpacing(1);
+
+ vbox = new QVBoxLayout( mImageFrame, 1 );
+ mImageLabel = new KImageTrackLabel( mImageFrame );
+ connect( mImageLabel, SIGNAL(mouseTrack( int, const QMouseEvent * )),
+ SLOT( slotMouseTrack( int, const QMouseEvent * )) );
+ vbox->addStretch(10);
+ vbox->addWidget( mImageLabel );
+ vbox->addStretch(10);
+ vbox->activate();
+ }
+
+ fontChange( font() );
+}
+
+
+void KAboutContainerBase::show( void )
+{
+ QWidget::show();
+}
+
+QSize KAboutContainerBase::sizeHint( void ) const
+{
+ return minimumSize().expandedTo( QSize( QWidget::sizeHint().width(), 0 ) );
+}
+
+void KAboutContainerBase::fontChange( const QFont &/*oldFont*/ )
+{
+ if( mTitleLabel )
+ {
+ QFont f( KGlobalSettings::generalFont() );
+ f.setBold( true );
+ int fs = f.pointSize();
+ if (fs == -1)
+ fs = QFontInfo(f).pointSize();
+ f.setPointSize( fs+2 ); // Lets not make it too big
+ mTitleLabel->setFont(f);
+ }
+
+ if( mVersionLabel )
+ {
+ QFont f( KGlobalSettings::generalFont() );
+ f.setBold( true );
+ mVersionLabel->setFont(f);
+ mAuthorLabel->setFont(f);
+ mVersionLabel->parentWidget()->layout()->activate();
+ }
+
+ update();
+}
+
+QFrame *KAboutContainerBase::addTextPage( const QString &title,
+ const QString &text,
+ bool richText, int numLines )
+{
+ QFrame* const page = addEmptyPage( title );
+ if( !page ) { return 0; }
+ if( numLines <= 0 ) { numLines = 10; }
+
+ QVBoxLayout* const vbox = new QVBoxLayout( page, KDialog::spacingHint() );
+
+ if( richText )
+ {
+ KTextBrowser* const browser = new KTextBrowser( page, "browser" );
+ browser->setHScrollBarMode( QScrollView::AlwaysOff );
+ browser->setText( text );
+ browser->setMinimumHeight( fontMetrics().lineSpacing()*numLines );
+
+ vbox->addWidget(browser);
+ connect(browser, SIGNAL(urlClick(const QString &)),
+ SLOT(slotUrlClick(const QString &)));
+ connect(browser, SIGNAL(mailClick(const QString &,const QString &)),
+ SLOT(slotMailClick(const QString &,const QString &)));
+ }
+ else
+ {
+ KTextEdit* const textEdit = new KTextEdit( page, "text" );
+ textEdit->setReadOnly( true );
+ textEdit->setMinimumHeight( fontMetrics().lineSpacing()*numLines );
+ textEdit->setWordWrap( QTextEdit::NoWrap );
+ vbox->addWidget( textEdit );
+ }
+
+ return page;
+}
+
+QFrame *KAboutContainerBase::addLicensePage( const QString &title,
+ const QString &text, int numLines)
+{
+ QFrame* const page = addEmptyPage( title );
+ if( !page ) { return 0; }
+ if( numLines <= 0 ) { numLines = 10; }
+
+ QVBoxLayout* const vbox = new QVBoxLayout( page, KDialog::spacingHint() );
+
+ KTextEdit* const textEdit = new KTextEdit( page, "license" );
+ textEdit->setFont( KGlobalSettings::fixedFont() );
+ textEdit->setReadOnly( true );
+ textEdit->setWordWrap( QTextEdit::NoWrap );
+ textEdit->setText( text );
+ textEdit->setMinimumHeight( fontMetrics().lineSpacing()*numLines );
+ vbox->addWidget( textEdit );
+ return page;
+}
+
+
+KAboutContainer *KAboutContainerBase::addContainerPage( const QString &title,
+ int childAlignment,
+ int innerAlignment )
+{
+ if( !mPageTab )
+ {
+ kdDebug(291) << "addPage: " << "Invalid layout" << endl;
+ return 0;
+ }
+
+ KAboutContainer* const container = new KAboutContainer( mPageTab, "container",
+ KDialog::spacingHint(), KDialog::spacingHint(), childAlignment,
+ innerAlignment );
+ mPageTab->addTab( container, title );
+
+ connect(container, SIGNAL(urlClick(const QString &)),
+ SLOT(slotUrlClick(const QString &)));
+ connect(container, SIGNAL(mailClick(const QString &,const QString &)),
+ SLOT(slotMailClick(const QString &,const QString &)));
+
+ return container;
+}
+
+
+KAboutContainer *KAboutContainerBase::addScrolledContainerPage(
+ const QString &title,
+ int childAlignment,
+ int innerAlignment )
+{
+ if( !mPageTab )
+ {
+ kdDebug(291) << "addPage: " << "Invalid layout" << endl;
+ return 0;
+ }
+
+ QFrame* const page = addEmptyPage( title );
+ QVBoxLayout* const vbox = new QVBoxLayout( page, KDialog::spacingHint() );
+ QScrollView* const scrollView = new QScrollView( page );
+ scrollView->viewport()->setBackgroundMode( PaletteBackground );
+ vbox->addWidget( scrollView );
+
+ KAboutContainer* const container = new KAboutContainer( scrollView, "container",
+ KDialog::spacingHint(), KDialog::spacingHint(), childAlignment,
+ innerAlignment );
+ scrollView->addChild( container );
+
+
+ connect(container, SIGNAL(urlClick(const QString &)),
+ SLOT(slotUrlClick(const QString &)));
+ connect(container, SIGNAL(mailClick(const QString &,const QString &)),
+ SLOT(slotMailClick(const QString &,const QString &)));
+
+ return container;
+}
+
+
+QFrame *KAboutContainerBase::addEmptyPage( const QString &title )
+{
+ if( !mPageTab )
+ {
+ kdDebug(291) << "addPage: " << "Invalid layout" << endl;
+ return 0;
+ }
+
+ QFrame* const page = new QFrame( mPageTab, title.latin1() );
+ page->setFrameStyle( QFrame::NoFrame );
+
+ mPageTab->addTab( page, title );
+ return page;
+}
+
+
+KAboutContainer *KAboutContainerBase::addContainer( int childAlignment,
+ int innerAlignment )
+{
+ KAboutContainer* const container = new KAboutContainer( this, "container",
+ 0, KDialog::spacingHint(), childAlignment, innerAlignment );
+ mTopLayout->addWidget( container, 0, childAlignment );
+
+ connect(container, SIGNAL(urlClick(const QString &)),
+ SLOT(slotUrlClick(const QString &)));
+ connect(container, SIGNAL(mailClick(const QString &,const QString &)),
+ SLOT(slotMailClick(const QString &,const QString &)));
+
+ return container;
+}
+
+
+
+void KAboutContainerBase::setTitle( const QString &title )
+{
+ if( !mTitleLabel )
+ {
+ kdDebug(291) << "setTitle: " << "Invalid layout" << endl;
+ return;
+ }
+ mTitleLabel->setText(title);
+}
+
+
+void KAboutContainerBase::setImage( const QString &fileName )
+{
+ if( !mImageLabel )
+ {
+ kdDebug(291) << "setImage: " << "Invalid layout" << endl;
+ return;
+ }
+ if( fileName.isNull() )
+ {
+ return;
+ }
+
+ const QPixmap logo( fileName );
+ if( !logo.isNull() )
+ mImageLabel->setPixmap( logo );
+
+ mImageFrame->layout()->activate();
+}
+
+void KAboutContainerBase::setProgramLogo( const QString &fileName )
+{
+ if( fileName.isNull() )
+ {
+ return;
+ }
+
+ const QPixmap logo( fileName );
+ setProgramLogo( logo );
+}
+
+void KAboutContainerBase::setProgramLogo( const QPixmap &pixmap )
+{
+ if( !mIconLabel )
+ {
+ kdDebug(291) << "setProgramLogo: " << "Invalid layout" << endl;
+ return;
+ }
+ if( !pixmap.isNull() )
+ {
+ mIconLabel->setPixmap( pixmap );
+ }
+}
+
+void KAboutContainerBase::setImageBackgroundColor( const QColor &color )
+{
+ if( mImageFrame )
+ {
+ mImageFrame->setBackgroundColor( color );
+ }
+}
+
+
+void KAboutContainerBase::setImageFrame( bool state )
+{
+ if( mImageFrame )
+ {
+ if( state )
+ {
+ mImageFrame->setFrameStyle( QFrame::Panel | QFrame::Sunken );
+ mImageFrame->setLineWidth(1);
+ }
+ else
+ {
+ mImageFrame->setFrameStyle( QFrame::NoFrame );
+ mImageFrame->setLineWidth(0);
+ }
+ }
+}
+
+
+void KAboutContainerBase::setProduct( const QString &appName,
+ const QString &version,
+ const QString &author,
+ const QString &year )
+{
+ if( !mIconLabel )
+ {
+ kdDebug(291) << "setProduct: " << "Invalid layout" << endl;
+ return;
+ }
+
+ if ( kapp )
+ {
+ mIconLabel->setPixmap( kapp->icon() );
+ kdDebug(291) << "setPixmap (iconName): " << kapp->iconName() << endl;
+ }
+ else
+ kdDebug(291) << "no kapp" << endl;
+
+ const QString msg1 = i18n("%1 %2 (Using KDE %3)").arg(appName).arg(version).
+ arg(QString::fromLatin1(KDE_VERSION_STRING));
+ const QString msg2 = !year.isEmpty() ? i18n("%1 %2, %3").arg('©').arg(year).
+ arg(author) : QString::fromLatin1("");
+
+ //if (!year.isEmpty())
+ // msg2 = i18n("%1 %2, %3").arg('©').arg(year).arg(author);
+
+ mVersionLabel->setText( msg1 );
+ mAuthorLabel->setText( msg2 );
+ if( msg2.isEmpty() )
+ {
+ mAuthorLabel->hide();
+ }
+
+ mIconLabel->parentWidget()->layout()->activate();
+}
+
+
+void KAboutContainerBase::slotMouseTrack( int mode, const QMouseEvent *e )
+{
+ emit mouseTrack( mode, e );
+}
+
+
+void KAboutContainerBase::slotUrlClick( const QString &url )
+{
+ emit urlClick( url );
+}
+
+void KAboutContainerBase::slotMailClick( const QString &_name,
+ const QString &_address )
+{
+ emit mailClick( _name, _address );
+}
+
+
+
+KAboutContainer::KAboutContainer( QWidget *_parent, const char *_name,
+ int _margin, int _spacing,
+ int childAlignment, int innerAlignment )
+ : QFrame( _parent, _name ), d(0)
+{
+ mAlignment = innerAlignment;
+
+ QGridLayout* const gbox = new QGridLayout( this, 3, 3, _margin, _spacing );
+ if( childAlignment & AlignHCenter )
+ {
+ gbox->setColStretch( 0, 10 );
+ gbox->setColStretch( 2, 10 );
+ }
+ else if( childAlignment & AlignRight )
+ {
+ gbox->setColStretch( 0, 10 );
+ }
+ else
+ {
+ gbox->setColStretch( 2, 10 );
+ }
+
+ if( childAlignment & AlignVCenter )
+ {
+ gbox->setRowStretch( 0, 10 );
+ gbox->setRowStretch( 2, 10 );
+ }
+ else if( childAlignment & AlignRight )
+ {
+ gbox->setRowStretch( 0, 10 );
+ }
+ else
+ {
+ gbox->setRowStretch( 2, 10 );
+ }
+
+ mVbox = new QVBoxLayout( _spacing );
+ gbox->addLayout( mVbox, 1, 1 );
+ gbox->activate();
+}
+
+
+void KAboutContainer::childEvent( QChildEvent *e )
+{
+ if( !e->inserted() || !e->child()->isWidgetType() )
+ {
+ return;
+ }
+
+ QWidget* const w = static_cast<QWidget *>(e->child());
+ mVbox->addWidget( w, 0, mAlignment );
+ const QSize s( sizeHint() );
+ setMinimumSize( s );
+
+ QObjectList* const l = const_cast<QObjectList *>(children()); // silence please
+ QObjectListIterator itr( *l );
+ QObject * o;
+ while ( (o = itr.current()) ) {
+ ++itr;
+ if( o->isWidgetType() )
+ {
+ static_cast<QWidget *>(o)->setMinimumWidth( s.width() );
+ }
+ }
+}
+
+
+QSize KAboutContainer::sizeHint( void ) const
+{
+ //
+ // The size is computed by adding the sizeHint().height() of all
+ // widget children and taking the width of the widest child and adding
+ // layout()->margin() and layout()->spacing()
+ //
+
+ QSize total_size;
+
+ int numChild = 0;
+ QObjectList* const l = const_cast<QObjectList *>(children()); // silence please
+
+ QObjectListIterator itr( *l );
+ QObject * o;
+ while ( (o = itr.current()) ) {
+ ++itr;
+ if( o->isWidgetType() )
+ {
+ ++numChild;
+ QWidget* const w= static_cast<QWidget *>(o);
+
+ QSize s = w->minimumSize();
+ if( s.isEmpty() )
+ {
+ s = w->minimumSizeHint();
+ if( s.isEmpty() )
+ {
+ s = w->sizeHint();
+ if( s.isEmpty() )
+ {
+ s = QSize( 100, 100 ); // Default size
+ }
+ }
+ }
+ total_size.setHeight( total_size.height() + s.height() );
+ if( s.width() > total_size.width() ) { total_size.setWidth( s.width() ); }
+ }
+ }
+
+ if( numChild > 0 )
+ {
+ //
+ // Seems I have to add 1 to the height to properly show the border
+ // of the last entry if layout()->margin() is 0
+ //
+
+ total_size.setHeight( total_size.height() + layout()->spacing()*(numChild-1) );
+ total_size += QSize( layout()->margin()*2, layout()->margin()*2 + 1 );
+ }
+ else
+ {
+ total_size = QSize( 1, 1 );
+ }
+ return total_size;
+}
+
+
+QSize KAboutContainer::minimumSizeHint( void ) const
+{
+ return sizeHint();
+}
+
+
+void KAboutContainer::addWidget( QWidget *widget )
+{
+ widget->reparent( this, 0, QPoint(0,0) );
+}
+
+
+void KAboutContainer::addPerson( const QString &_name, const QString &_email,
+ const QString &_url, const QString &_task,
+ bool showHeader, bool showFrame,bool showBold)
+{
+
+ KAboutContributor* const cont = new KAboutContributor( this, "pers",
+ _name, _email, _url, _task, showHeader, showFrame, showBold );
+ connect( cont, SIGNAL( openURL(const QString&)),
+ this, SIGNAL( urlClick(const QString &)));
+ connect( cont, SIGNAL( sendEmail(const QString &, const QString &)),
+ this, SIGNAL( mailClick(const QString &, const QString &)));
+}
+
+
+void KAboutContainer::addTitle( const QString &title, int alignment,
+ bool showFrame, bool showBold )
+{
+
+ QLabel* const label = new QLabel( title, this, "title" );
+ if( showBold )
+ {
+ QFont labelFont( font() );
+ labelFont.setBold( true );
+ label->setFont( labelFont );
+ }
+ if( showFrame )
+ {
+ label->setFrameStyle(QFrame::Panel | QFrame::Raised);
+ }
+ label->setAlignment( alignment );
+}
+
+
+void KAboutContainer::addImage( const QString &fileName, int alignment )
+{
+ if( fileName.isNull() )
+ {
+ return;
+ }
+
+ KImageTrackLabel* const label = new KImageTrackLabel( this, "image" );
+ const QImage logo( fileName );
+ if( !logo.isNull() )
+ {
+ QPixmap pix;
+ pix = logo;
+ label->setPixmap( pix );
+ }
+ label->setAlignment( alignment );
+}
+
+#if 0
+//MOC_SKIP_BEGIN
+
+/** Every person displayed is stored in a KAboutContributor object.
+ * Every contributor, the author and/or the maintainer of the application are
+ * stored in objects of this local class. Every single field may be empty.
+ * To add a contributor, create a KAboutContributor object as a child of your
+ * @ref KAboutDialog, set its contents and add it using add addContributor. */
+class KAboutContributor : public QFrame
+{
+ // ############################################################################
+ Q_OBJECT
+ // ----------------------------------------------------------------------------
+public:
+ /** The Qt constructor. */
+ KAboutContributor(QWidget* parent=0, const char* name=0);
+ /** Set the name (a literal string). */
+ void setName(const QString&);
+ /** Get the name. */
+ QString getName();
+ /** The email address (dito). */
+ void setEmail(const QString&);
+ /** Get the email address. */
+ QString getEmail();
+ /** The URL (dito). */
+ void setURL(const QString&);
+ /** Get the URL. */
+ QString getURL();
+ /** The tasks the person worked on (a literal string). More than one line is
+ * possible, but very long texts might look ugly. */
+ void setWork(const QString&);
+ /** The size hint. Very important here, since KAboutWidget relies on it for
+ * geometry management. */
+ QSize sizeHint();
+ QSize minimumSizeHint(void);
+ virtual void show( void );
+
+ // ----------------------------------------------------------------------------
+protected:
+ // events:
+ /** The resize event. */
+ void resizeEvent(QResizeEvent*);
+ /** The paint event. */
+ void paintEvent(QPaintEvent*);
+ /** The label showing the program version. */
+ QLabel *name;
+ /** The clickable URL label showing the email address. It is only visible if
+ * its text is not empty. */
+ KURLLabel *email;
+ /** Another interactive part that displays the homepage URL. */
+ KURLLabel *url;
+ /** The description of the contributions of the person. */
+ QString work;
+ // ----------------------------------------------------------------------------
+protected slots:
+ /** The homepage URL has been clicked. */
+ void urlClickedSlot(const QString&);
+ /** The email address has been clicked. */
+ void emailClickedSlot(const QString& emailaddress);
+ // ----------------------------------------------------------------------------
+signals:
+ /** The email address has been clicked. */
+ void sendEmail(const QString& name, const QString& email);
+ /** The URL has been clicked. */
+ void openURL(const QString& url);
+ // ############################################################################
+};
+
+
+
+KAboutContributor::KAboutContributor(QWidget* parent, const char* n)
+ : QFrame(parent, n),
+ name(new QLabel(this)),
+ email(new KURLLabel(this)),
+ url(new KURLLabel(this))
+{
+ // ############################################################
+ if(name==0 || email==0)
+ { // this will nearly never happen (out of memory in about box?)
+ kdDebug() << "KAboutContributor::KAboutContributor: Out of memory." << endl;
+ qApp->quit();
+ }
+ setFrameStyle(QFrame::Panel | QFrame::Raised);
+ // -----
+ connect(email, SIGNAL(leftClickedURL(const QString&)),
+ SLOT(emailClickedSlot(const QString&)));
+ connect(url, SIGNAL(leftClickedURL(const QString&)),
+ SLOT(urlClickedSlot(const QString&)));
+ // ############################################################
+}
+
+void
+KAboutContributor::setName(const QString& n)
+{
+ // ############################################################
+ name->setText(n);
+ // ############################################################
+}
+
+QString
+KAboutContributor::getName()
+{
+ // ###########################################################
+ return name->text();
+ // ###########################################################
+}
+void
+KAboutContributor::setURL(const QString& u)
+{
+ // ###########################################################
+ url->setText(u);
+ // ###########################################################
+}
+
+QString
+KAboutContributor::getURL()
+{
+ // ###########################################################
+ return url->text();
+ // ###########################################################
+}
+
+void
+KAboutContributor::setEmail(const QString& e)
+{
+ // ###########################################################
+ email->setText(e);
+ // ###########################################################
+}
+
+QString
+KAboutContributor::getEmail()
+{
+ // ###########################################################
+ return email->text();
+ // ###########################################################
+}
+
+void
+KAboutContributor::emailClickedSlot(const QString& e)
+{
+ // ###########################################################
+ kdDebug() << "KAboutContributor::emailClickedSlot: called." << endl;
+ emit(sendEmail(name->text(), e));
+ // ###########################################################
+}
+
+void
+KAboutContributor::urlClickedSlot(const QString& u)
+{
+ // ###########################################################
+ kdDebug() << "KAboutContributor::urlClickedSlot: called." << endl;
+ emit(openURL(u));
+ // ###########################################################
+}
+
+void
+KAboutContributor::setWork(const QString& w)
+{
+ // ###########################################################
+ work=w;
+ // ###########################################################
+}
+
+#endif
+
+
+#if 0
+QSize
+KAboutContributor::sizeHint()
+{
+ // ############################################################################
+ const int FrameWidth=frameWidth();
+ const int WorkTextWidth=200;
+ int maxx, maxy;
+ QRect rect;
+ // ----- first calculate name and email width:
+ maxx=name->sizeHint().width();
+ maxx=QMAX(maxx, email->sizeHint().width()+WORKTEXT_IDENTATION);
+ // ----- now determine "work" text rectangle:
+ if(!work.isEmpty()) // save time
+ {
+ rect=fontMetrics().boundingRect
+ (0, 0, WorkTextWidth, 32000, WordBreak | AlignLeft, work);
+ }
+ if(maxx<rect.width())
+ {
+ maxx=WorkTextWidth+WORKTEXT_IDENTATION;
+ }
+ maxx=QMAX(maxx, url->sizeHint().width()+WORKTEXT_IDENTATION);
+ // -----
+ maxy=2*(name->sizeHint().height()+Grid); // need a space above the KURLLabels
+ maxy+=/* email */ name->sizeHint().height();
+ maxy+=rect.height();
+ // -----
+ maxx+=2*FrameWidth;
+ maxy+=2*FrameWidth;
+ return QSize(maxx, maxy);
+ // ############################################################################
+}
+
+QSize KAboutContributor::minimumSizeHint(void)
+{
+ return( sizeHint() );
+}
+
+
+void KAboutContributor::show( void )
+{
+ QFrame::show();
+ setMinimumSize( sizeHint() );
+}
+
+
+
+void
+KAboutContributor::resizeEvent(QResizeEvent*)
+{ // the widgets are simply aligned from top to bottom, since the parent is
+ // expected to respect the size hint
+ // ############################################################################
+ int framewidth=frameWidth(), childwidth=width()-2*framewidth;
+ int cy=framewidth;
+ // -----
+ name->setGeometry
+ (framewidth, framewidth, childwidth, name->sizeHint().height());
+ cy=name->height()+Grid;
+ email->setGeometry
+ (framewidth+WORKTEXT_IDENTATION, cy,
+ childwidth-WORKTEXT_IDENTATION, /* email */ name->sizeHint().height());
+ cy+=name->height()+Grid;
+ url->setGeometry
+ (framewidth+WORKTEXT_IDENTATION, cy,
+ childwidth-WORKTEXT_IDENTATION, /* url */ name->sizeHint().height());
+ // the work text is drawn in the paint event
+ // ############################################################################
+}
+
+
+void
+KAboutContributor::paintEvent(QPaintEvent* e)
+{ // the widgets are simply aligned from top to bottom, since the parent is
+ // expected to respect the size hint (the widget is only used locally by now)
+ // ############################################################################
+ int cy=frameWidth()+name->height()+email->height()+Grid+url->height()+Grid;
+ int h=height()-cy-frameWidth();
+ int w=width()-WORKTEXT_IDENTATION-2*frameWidth();
+ // -----
+ QFrame::paintEvent(e);
+ if(work.isEmpty()) return;
+ QPainter paint(this); // construct painter only if there is something to draw
+ // -----
+ paint.drawText(WORKTEXT_IDENTATION, cy, w, h, AlignLeft | WordBreak, work);
+ // ############################################################################
+}
+// MOC_SKIP_END
+#endif
+
+
+#if 0
+QSize KAboutContributor::sizeHint( void )
+{
+ int s = KDialog::spacingHint();
+ int h = fontMetrics().lineSpacing()*3 + 2*s;
+ int m = frameWidth();
+
+ int w = name->sizeHint().width();
+ w = QMAX( w, email->sizeHint().width()+s);
+ w = QMAX( w, url->sizeHint().width()+s);
+
+ if( work.isEmpty() == false )
+ {
+ const int WorkTextWidth=200;
+ QRect r = fontMetrics().boundingRect
+ (0, 0, WorkTextWidth, 32000, WordBreak | AlignLeft, work);
+ if( w < r.width() )
+ {
+ w = QMAX( w, WorkTextWidth+s );
+ }
+ h += QMAX( fontMetrics().lineSpacing(), r.height() ) + s;
+ }
+ return( QSize( w + 2*m, h + 2*m ) );
+
+
+ /*
+ int s = 3;
+ int m = frameWidth() + KDialog::spacingHint();
+ int h = ls * 3 + s * 2;
+ int w = name->sizeHint().width();
+
+ w = QMAX( w, email->sizeHint().width()+WORKTEXT_IDENTATION);
+ w = QMAX( w, url->sizeHint().width()+WORKTEXT_IDENTATION);
+ if( work.isEmpty() == false )
+ {
+ const int WorkTextWidth=200;
+
+ QRect r = fontMetrics().boundingRect
+ (0, 0, WorkTextWidth, 32000, WordBreak | AlignLeft, work);
+ if( w < r.width() )
+ {
+ w = QMAX( w, WorkTextWidth + WORKTEXT_IDENTATION );
+ }
+ h += r.height() + s;
+ }
+ return( QSize( w + 2*m, h + 2*m ) );
+ */
+}
+
+
+//
+// The widgets are simply aligned from top to bottom, since the parent is
+// expected to respect the size hint
+//
+void KAboutContributor::resizeEvent(QResizeEvent*)
+{
+ int x = frameWidth();
+ int s = KDialog::spacingHint();
+ int h = fontMetrics().lineSpacing();
+ int w = width() - 2*x;
+ int y = x;
+
+ name->setGeometry( x, y, w, h );
+ y += h + s;
+ email->setGeometry( x+s, y, w-s, h );
+ y += h + s;
+ url->setGeometry( x+s, y, w-s, h );
+
+ /*
+ int x = frameWidth() + KDialog::spacingHint();
+ int y = x;
+ int w = width() - 2*x;
+ int h = name->sizeHint().height();
+ int s = 3;
+
+ name->setGeometry( x, y, w, h );
+ y += h + s;
+ email->setGeometry( x+WORKTEXT_IDENTATION, y, w-WORKTEXT_IDENTATION, h );
+ y += h + s;
+ url->setGeometry( x+WORKTEXT_IDENTATION, y, w-WORKTEXT_IDENTATION, h );
+ //
+ // the work text is drawn in the paint event
+ //
+ */
+}
+
+
+
+void KAboutContributor::paintEvent( QPaintEvent *e )
+{
+ QFrame::paintEvent(e);
+ if(work.isEmpty()) return;
+
+ int x = frameWidth() + KDialog::spacingHint();
+ int h = fontMetrics().lineSpacing();
+ int y = height() - frameWidth() - fontMetrics().lineSpacing();
+ int w = width() - frameWidth()*2 - KDialog::spacingHint();
+
+ QPainter paint( this );
+ paint.drawText( x, y, w, h, AlignLeft | WordBreak, work );
+
+ /*
+
+ int s = 3;
+ int x = frameWidth() + KDialog::spacingHint() + WORKTEXT_IDENTATION;
+ int w = width()-WORKTEXT_IDENTATION-2*(frameWidth()+KDialog::spacingHint());
+ int y = frameWidth()+KDialog::spacingHint()+(name->sizeHint().height()+s)*3;
+ int h = height()-y-frameWidth();
+
+ QPainter paint( this );
+ paint.drawText( x, y, w, h, AlignLeft | WordBreak, work );
+ */
+}
+#endif
+
+
+
+
+
+
+KAboutWidget::KAboutWidget(QWidget *_parent, const char *_name)
+ : QWidget(_parent, _name),
+ version(new QLabel(this)),
+ cont(new QLabel(this)),
+ logo(new QLabel(this)),
+ author(new KAboutContributor(this)),
+ maintainer(new KAboutContributor(this)),
+ showMaintainer(false),
+ d(0)
+{
+ // #################################################################
+ if( !version || !cont || !logo || !author || !maintainer )
+ {
+ // this will nearly never happen (out of memory in about box?)
+ kdDebug() << "KAboutWidget::KAboutWidget: Out of memory." << endl;
+ qApp->quit();
+ }
+ // -----
+ cont->setText(i18n("Other Contributors:"));
+ logo->setText(i18n("(No logo available)"));
+ logo->setFrameStyle(QFrame::Panel | QFrame::Raised);
+ version->setAlignment(AlignCenter);
+ // -----
+ connect(author, SIGNAL(sendEmail(const QString&, const QString&)),
+ SLOT(sendEmailSlot(const QString&, const QString&)));
+ connect(author, SIGNAL(openURL(const QString&)),
+ SLOT(openURLSlot(const QString&)));
+ connect(maintainer, SIGNAL(sendEmail(const QString&, const QString&)),
+ SLOT(sendEmailSlot(const QString&, const QString&)));
+ connect(maintainer, SIGNAL(openURL(const QString&)),
+ SLOT(openURLSlot(const QString&)));
+ // #################################################################
+}
+
+
+void
+KAboutWidget::adjust()
+{
+ // #################################################################
+ int cx, cy, tempx;
+ int maintWidth, maintHeight;
+ QSize total_size;
+ // -----
+ if(showMaintainer)
+ {
+ total_size=maintainer->sizeHint();
+ maintWidth=total_size.width();
+ maintHeight=total_size.height();
+ } else {
+ maintWidth=0;
+ maintHeight=0;
+ }
+ total_size=author->sizeHint();
+ logo->adjustSize();
+ cy=version->sizeHint().height()+Grid;
+ cx=logo->width();
+ tempx=QMAX(total_size.width(), maintWidth);
+ cx+=Grid+tempx;
+ cx=QMAX(cx, version->sizeHint().width());
+ cy+=QMAX(logo->height(),
+ total_size.height()+(showMaintainer ? Grid+maintHeight : 0));
+ // -----
+ if(!contributors.isEmpty())
+ {
+ cx=QMAX(cx, cont->sizeHint().width());
+ cy+=cont->sizeHint().height()+Grid;
+ QPtrListIterator<KAboutContributor> _pos(contributors);
+ KAboutContributor* currEntry;
+ while ( (currEntry = _pos.current()) )
+ {
+ ++_pos;
+ cy+=currEntry->sizeHint().height();
+ }
+ }
+ // -----
+ setMinimumSize(cx, cy);
+ // #################################################################
+}
+
+void
+KAboutWidget::setLogo(const QPixmap& i)
+{
+ // ############################################################################
+ logo->setPixmap(i);
+ // ############################################################################
+}
+
+void KAboutWidget::sendEmailSlot(const QString &_name, const QString &_email)
+{
+ emit(sendEmail(_name, _email));
+}
+
+void KAboutWidget::openURLSlot(const QString& _url)
+{
+ emit(openURL(_url));
+}
+
+void
+KAboutWidget::setAuthor(const QString &_name, const QString &_email,
+ const QString &_url, const QString &_w)
+{
+ // ############################################################################
+ author->setName(_name);
+ author->setEmail(_email);
+ author->setURL(_url);
+ author->setWork(_w);
+ // ############################################################################
+}
+
+void
+KAboutWidget::setMaintainer(const QString &_name, const QString &_email,
+ const QString &_url, const QString &_w)
+{
+ // ############################################################################
+ maintainer->setName(_name);
+ maintainer->setEmail(_email);
+ maintainer->setWork(_w);
+ maintainer->setURL(_url);
+ showMaintainer=true;
+ // ############################################################################
+}
+
+void
+KAboutWidget::addContributor(const QString &_name, const QString &_email,
+ const QString &_url, const QString &_w)
+{
+ // ############################################################################
+ KAboutContributor* const c=new KAboutContributor(this);
+ // -----
+ c->setName(_name);
+ c->setEmail(_email);
+ c->setURL(_url);
+ c->setWork(_w);
+ contributors.append(c);
+ connect(c, SIGNAL(sendEmail(const QString&, const QString&)),
+ SLOT(sendEmailSlot(const QString&, const QString&)));
+ connect(c, SIGNAL(openURL(const QString&)), SLOT(openURLSlot(const QString&)));
+ // ############################################################################
+}
+
+void
+KAboutWidget::setVersion(const QString &_name)
+{
+ // ############################################################################
+ version->setText(_name);
+ // ############################################################################
+}
+
+void
+KAboutWidget::resizeEvent(QResizeEvent*)
+{
+ // ############################################################################
+ int _x=0, _y, cx, tempx, tempy;
+ // ----- set version label geometry:
+ version->setGeometry(0, 0, width(), version->sizeHint().height());
+ _y=version->height()+Grid;
+ // ----- move logo to correct position:
+ logo->adjustSize();
+ logo->move(0, _y);
+ // ----- move author and maintainer right to it:
+ tempx=logo->width()+Grid;
+ cx=width()-tempx;
+ author->setGeometry
+ (tempx, _y, cx, author->sizeHint().height());
+ maintainer->setGeometry
+ (tempx, _y+author->height()+Grid, cx, maintainer->sizeHint().height());
+
+ _y+=QMAX(logo->height(),
+ author->height()+(showMaintainer ? Grid+maintainer->height() : 0));
+ // -----
+ if(!contributors.isEmpty())
+ {
+ tempy=cont->sizeHint().height();
+ cont->setGeometry(0, _y, width(), tempy);
+ cont->show();
+ _y+=tempy+Grid;
+ } else {
+ cont->hide();
+ }
+ QPtrListIterator<KAboutContributor> _pos(contributors);
+ KAboutContributor* currEntry;
+ while( (currEntry = _pos.current()) )
+ {
+ ++_pos;
+ tempy=currEntry->sizeHint().height();
+ // y+=Grid;
+ currEntry->setGeometry(_x, _y, width(), tempy);
+ _y+=tempy;
+ }
+ if(showMaintainer)
+ {
+ maintainer->show();
+ } else {
+ maintainer->hide();
+ }
+ // ############################################################################
+}
+
+KAboutDialog::KAboutDialog(QWidget *_parent, const char *_name, bool modal)
+ : KDialogBase(_parent, _name, modal, QString::null, Ok, Ok ),
+ about(new KAboutWidget(this)), mContainerBase(0), d(0)
+{
+ // #################################################################
+ if(!about)
+ {
+ // this will nearly never happen (out of memory in about box?)
+ kdDebug() << "KAboutDialog::KAboutDialog: Out of memory." << endl;
+ qApp->quit();
+ }
+ setMainWidget(about);
+ connect(about, SIGNAL(sendEmail(const QString&, const QString&)),
+ SLOT(sendEmailSlot(const QString&, const QString&)));
+ connect(about, SIGNAL(openURL(const QString&)),
+ SLOT(openURLSlot(const QString&)));
+ // #################################################################
+}
+
+
+KAboutDialog::KAboutDialog( int layoutType, const QString &_caption,
+ int buttonMask, ButtonCode defaultButton,
+ QWidget *_parent, const char *_name, bool modal,
+ bool separator, const QString &user1,
+ const QString &user2, const QString &user3 )
+ :KDialogBase( _parent, _name, modal, QString::null, buttonMask, defaultButton,
+ separator, user1, user2, user3 ),
+ about(0), d(0)
+{
+ setPlainCaption( i18n("About %1").arg(_caption) );
+
+ mContainerBase = new KAboutContainerBase( layoutType, this );
+ setMainWidget(mContainerBase);
+
+ connect( mContainerBase, SIGNAL(urlClick(const QString &)),
+ this, SLOT(openURLSlot(const QString &)));
+ connect( mContainerBase, SIGNAL(mailClick(const QString &,const QString &)),
+ this, SLOT(sendEmailSlot(const QString &,const QString &)));
+ connect( mContainerBase, SIGNAL(mouseTrack(int, const QMouseEvent *)),
+ this, SLOT(mouseTrackSlot(int, const QMouseEvent *)));
+}
+
+
+void KAboutDialog::show( void )
+{
+ adjust();
+ if( mContainerBase ) { mContainerBase->show(); }
+ QDialog::show();
+}
+
+
+void KAboutDialog::show( QWidget * /*centerParent*/ )
+{
+ adjust();
+ if( mContainerBase ) { mContainerBase->show(); }
+ QDialog::show();
+}
+
+
+void KAboutDialog::adjust()
+{
+ if( !about ) { return; }
+ about->adjust();
+ //initializeGeometry();
+ resize( sizeHint() );
+}
+
+
+void KAboutDialog::setLogo(const QPixmap& i)
+{
+ if( !about ) { return; }
+ about->setLogo(i);
+}
+
+
+void KAboutDialog::setMaintainer(const QString &_name, const QString &_email,
+ const QString &_url, const QString &_w)
+{
+ // #################################################################
+ if( !about ) { return; }
+ about->setMaintainer(_name, _email, _url, _w);
+ // #################################################################
+}
+
+void KAboutDialog::setAuthor(const QString &_name, const QString &_email,
+ const QString &_url, const QString &_work)
+{
+ // #################################################################
+ if( !about ) { return; }
+ about->setAuthor(_name, _email, _url, _work);
+ // #################################################################
+}
+
+void KAboutDialog::addContributor(const QString &_name, const QString &_email,
+ const QString &_url, const QString &_w)
+{
+ // #################################################################
+ if( !about ) { return; }
+ about->addContributor(_name, _email, _url, _w);
+ // #################################################################
+}
+
+void KAboutDialog::setVersion(const QString &_name)
+{
+ // #################################################################
+ if( !about ) { return; }
+ about->setVersion(_name);
+ // #################################################################
+}
+
+void KAboutDialog::sendEmailSlot(const QString& /*name*/, const QString& email)
+{
+ if ( kapp )
+ kapp->invokeMailer( email, QString::null );
+ /*
+ kdDebug() << "KAboutDialog::sendEmailSlot: request to send an email to "
+ << name << ", " << email << endl;
+ emit(sendEmail(name, email));
+ */
+}
+
+void KAboutDialog::openURLSlot(const QString& url)
+{
+ if ( kapp )
+ kapp->invokeBrowser( url );
+ //kdDebug() << "KAboutDialog::openURLSlot: request to open URL " << url << endl;
+ //emit(openURL(url));
+}
+
+
+void KAboutDialog::mouseTrackSlot( int /*mode*/, const QMouseEvent * /*e*/ )
+{
+ // By default we do nothing. This method must be reimplemented.
+}
+
+
+QFrame *KAboutDialog::addTextPage( const QString &title, const QString &text,
+ bool richText, int numLines )
+{
+ if( !mContainerBase ) { return 0; }
+ return mContainerBase->addTextPage( title, text, richText, numLines );
+}
+
+QFrame *KAboutDialog::addLicensePage( const QString &title, const QString &text,
+ int numLines )
+{
+ if( !mContainerBase ) { return 0; }
+ return mContainerBase->addLicensePage( title, text, numLines );
+}
+
+
+KAboutContainer *KAboutDialog::addContainerPage( const QString &title,
+ int childAlignment, int innerAlignment )
+{
+ if( !mContainerBase ) { return 0; }
+ return mContainerBase->addContainerPage( title, childAlignment,
+ innerAlignment);
+}
+
+
+KAboutContainer *KAboutDialog::addScrolledContainerPage( const QString &title,
+ int childAlignment, int innerAlignment )
+{
+ if( !mContainerBase ) { return 0; }
+ return mContainerBase->addScrolledContainerPage( title, childAlignment,
+ innerAlignment);
+}
+
+
+
+QFrame *KAboutDialog::addPage( const QString &title )
+{
+ if( !mContainerBase ) { return 0; }
+ return mContainerBase->addEmptyPage( title );
+}
+
+
+KAboutContainer *KAboutDialog::addContainer( int childAlignment,
+ int innerAlignment )
+{
+ if( !mContainerBase ) { return 0; }
+ return mContainerBase->addContainer( childAlignment, innerAlignment );
+}
+
+
+void KAboutDialog::setTitle( const QString &title )
+{
+ if( !mContainerBase ) { return; }
+ mContainerBase->setTitle( title );
+}
+
+
+void KAboutDialog::setImage( const QString &fileName )
+{
+ if( !mContainerBase ) { return; }
+ mContainerBase->setImage( fileName );
+}
+
+// KDE4: remove
+void KAboutDialog::setIcon( const QString &fileName )
+{
+ if( !mContainerBase ) { return; }
+ mContainerBase->setProgramLogo( fileName );
+}
+
+void KAboutDialog::setProgramLogo( const QString &fileName )
+{
+ if( !mContainerBase ) { return; }
+ mContainerBase->setProgramLogo( fileName );
+}
+
+void KAboutDialog::setProgramLogo( const QPixmap &pixmap )
+{
+ if( !mContainerBase ) { return; }
+ mContainerBase->setProgramLogo( pixmap );
+}
+
+void KAboutDialog::setImageBackgroundColor( const QColor &color )
+{
+ if( !mContainerBase ) { return; }
+ mContainerBase->setImageBackgroundColor( color );
+}
+
+
+void KAboutDialog::setImageFrame( bool state )
+{
+ if( !mContainerBase ) { return; }
+ mContainerBase->setImageFrame( state );
+}
+
+
+void KAboutDialog::setProduct( const QString &appName, const QString &version,
+ const QString &author, const QString &year )
+{
+ if( !mContainerBase ) { return; }
+ mContainerBase->setProduct( appName, version, author, year );
+}
+
+
+
+void KAboutDialog::imageURL( QWidget *_parent, const QString &_caption,
+ const QString &_path, const QColor &_imageColor,
+ const QString &_url )
+{
+ KAboutDialog a( AbtImageOnly, QString::null, Close, Close, _parent, "image", true );
+ a.setPlainCaption( _caption );
+ a.setImage( _path );
+ a.setImageBackgroundColor( _imageColor );
+
+ KAboutContainer* const c = a.addContainer( AlignCenter, AlignCenter );
+ if( c )
+ {
+ c->addPerson( QString::null, QString::null, _url, QString::null );
+ }
+ a.exec();
+}
+
+
+
+
+//
+// A class that can can monitor mouse movements on the image
+//
+KImageTrackLabel::KImageTrackLabel( QWidget *_parent, const char *_name, WFlags f )
+ : QLabel( _parent, _name, f )
+{
+ setText( i18n("Image missing"));
+}
+
+void KImageTrackLabel::mousePressEvent( QMouseEvent *e )
+{
+ emit mouseTrack( MousePress, e );
+}
+
+void KImageTrackLabel::mouseReleaseEvent( QMouseEvent *e )
+{
+ emit mouseTrack( MouseRelease, e );
+}
+
+void KImageTrackLabel::mouseDoubleClickEvent( QMouseEvent *e )
+{
+ emit mouseTrack( MouseDoubleClick, e );
+}
+
+void KImageTrackLabel::mouseMoveEvent ( QMouseEvent *e )
+{
+ emit mouseTrack( MouseDoubleClick, e );
+}
+
+void KAboutDialog::virtual_hook( int id, void* data )
+{ KDialogBase::virtual_hook( id, data ); }
+
diff --git a/kdeui/kaboutdialog.h b/kdeui/kaboutdialog.h
new file mode 100644
index 000000000..25afc0a3b
--- /dev/null
+++ b/kdeui/kaboutdialog.h
@@ -0,0 +1,633 @@
+/*
+ * This file is part of the KDE Libraries
+ * Copyright (C) 1999-2001 Mirko Boehm (mirko@kde.org) and
+ * Espen Sand (espen@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This file declares a class for creating "About ..." dialogs
+ * in a general way. It provides geometry management and some
+ * options to connect for, like emailing the author or maintainer.
+ */
+
+
+#ifndef _KABOUTDIALOG_H_
+#define _KABOUTDIALOG_H_
+
+#include <kdialogbase.h>
+#include <qstring.h>
+
+class QFrame;
+class QLabel;
+class QVBoxLayout;
+class QTabWidget;
+class KURLLabel;
+class KAboutContainer;
+class KAboutContainerBase;
+
+class KAboutWidgetPrivate;
+
+class KAboutContainerPrivate;
+/**
+ * KAboutContainer can be used to make a application specific AboutDialog.
+ */
+class KDEUI_EXPORT KAboutContainer : public QFrame
+{
+ Q_OBJECT
+
+ public:
+ KAboutContainer( QWidget *parent=0, const char *name=0,
+ int margin=0, int spacing=0,
+ int childAlignment = AlignCenter,
+ int innerAlignment = AlignCenter );
+
+ void addWidget( QWidget *widget );
+ void addPerson( const QString &name, const QString &email,
+ const QString &url, const QString &task,
+ bool showHeader = false, bool showframe = false,
+ bool showBold = false );
+ void addTitle( const QString &title, int alignment=AlignLeft,
+ bool showframe = false, bool showBold = false );
+ void addImage( const QString &fileName, int alignment=AlignLeft );
+
+ virtual QSize sizeHint( void ) const;
+ virtual QSize minimumSizeHint( void ) const;
+
+ protected:
+ virtual void childEvent( QChildEvent *e );
+
+ signals:
+ void urlClick( const QString &url );
+ void mailClick( const QString &name, const QString &address );
+
+
+ private:
+ QVBoxLayout *mVbox;
+ int mAlignment;
+ KAboutContainerPrivate* const d;
+};
+
+class KAboutContributorPrivate;
+
+/**
+ * Used internally by KAboutWidget
+ * @internal
+ */
+class KDEUI_EXPORT KAboutContributor : public QFrame
+{
+ Q_OBJECT
+
+ public:
+ KAboutContributor( QWidget *parent=0, const char *name=0,
+ const QString &username=QString::null,
+ const QString &email=QString::null,
+ const QString &url=QString::null,
+ const QString &work=QString::null,
+ bool showHeader=false, bool showFrame=true,
+ bool showBold=false );
+
+ void setName( const QString &text, const QString &header=QString::null,
+ bool update = true );
+ void setEmail( const QString &text, const QString &header=QString::null,
+ bool update = true );
+ void setURL( const QString &text, const QString &header=QString::null,
+ bool update = true );
+ void setWork( const QString &text, const QString &header=QString::null,
+ bool update = true );
+ QString getName( void ) const;
+ QString getEmail( void ) const;
+ QString getURL( void ) const;
+ QString getWork( void ) const;
+
+ virtual QSize sizeHint( void ) const;
+
+ protected:
+ virtual void fontChange( const QFont &oldFont );
+
+ protected slots:
+ void urlClickedSlot( const QString& );
+ void emailClickedSlot( const QString& emailaddress );
+
+ private:
+ void updateLayout( void );
+
+ signals:
+ void sendEmail(const QString& name, const QString& email);
+ void openURL(const QString& url);
+
+ private:
+ QLabel *mLabel[4];
+ QLabel *mText[4];
+ bool mShowHeader;
+ bool mShowBold;
+
+ KAboutContributorPrivate* const d;
+
+ virtual void setName(const char *_name) { QFrame::setName(_name); }
+};
+
+/**
+ * KAboutWidget is the main widget for KAboutDialog.
+ *
+ * It has a minimum size set.
+ */
+class KDEUI_EXPORT KAboutWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ /**
+ * The Qt constructor.
+ */
+ KAboutWidget(QWidget* parent=0, const char* name=0 );
+
+ /**
+ * Adjust the minimum size (after setting the properties of the image and
+ * the labels.
+ */
+ void adjust();
+
+ /**
+ * Sets the image as the application logo.
+ */
+ void setLogo(const QPixmap&);
+ /**
+ * Sets the author's name and email address.
+ */
+ void setAuthor(const QString& name, const QString& email,
+ const QString& url, const QString& work);
+ /**
+ * Sets the maintainers name and email address.
+ */
+ void setMaintainer(const QString& name, const QString& email,
+ const QString& url, const QString& work);
+ /**
+ * Shows this person as one of the major contributors.
+ */
+ void addContributor(const QString& name, const QString& email,
+ const QString& url, const QString& work);
+ /**
+ * Sets the text describing the version.
+ */
+ void setVersion(const QString& name);
+ // -------------------------------------------------------------------------
+protected slots:
+ /**
+ * Catches the signals from the contributors elements.
+ */
+ void sendEmailSlot(const QString& name, const QString& email);
+ /**
+ * Catches the clicked URLs.
+ */
+ void openURLSlot(const QString& url);
+ // -------------------------------------------------------------------------
+signals:
+ /**
+ * An email address has been selected by the user.
+ */
+ void sendEmail(const QString& name, const QString& email);
+ /**
+ * An URL has been clicked.
+ */
+ void openURL(const QString& url);
+ // -------------------------------------------------------------------------
+protected:
+ // events:
+ /**
+ * The resize event.
+ */
+ void resizeEvent(QResizeEvent*);
+ /**
+ * The label showing the program version.
+ */
+ QLabel *version;
+ /**
+ * The label showing the text "Other contributors:".
+ */
+ QLabel *cont;
+ /**
+ * The frame showing the logo.
+ */
+ QLabel *logo;
+ /**
+ * The application developer.
+ */
+ KAboutContributor *author;
+ /**
+ * The application maintainer.
+ */
+ KAboutContributor *maintainer;
+ /**
+ * Show the maintainer?
+ */
+ bool showMaintainer;
+ /**
+ * A set of people who contributed to the application.
+ */
+ QPtrList<KAboutContributor> contributors;
+ // #########################################################################
+ //
+private:
+ KAboutWidgetPrivate* const d;
+};
+
+class KAboutDialogPrivate;
+/**
+ * A KDialogBase with predefined main widget.
+ *
+ * As a KDialogBase it uses your application wide settings
+ * for KDialogBase
+ * objects (base frame tiles, main frame tiles etc).
+ * To use it, simply create a KAboutDialog object, set all (or some) of its
+ * properties and show it. Do not derive it to create your own about dialog
+ * until you need some cool features that are unsupported and you have
+ * contacted me to add them.
+ *
+ * The dialog can be created using two different constructors. The
+ * difference between these constructors is the available components that
+ * can be used to build the contents of the dialog. The first (Constructor I)
+ * provides a number of easy to use methods. Basically it allows you
+ * to add the components of choice, and the components are placed in a
+ * predefined layout. You do not have to plan the layout. Everything is
+ * taken care of.
+ *
+ * The second constructor (Constructor II) works in quite the same manner
+ * as the first, but you have better control on where the components
+ * are postioned in the layout and you have access to an extended number
+ * of components you can install such as titles, product information,
+ * a tabbed pages (where you can display rich text with url links) and
+ * a person (developer) information field. The "About KDE" dialog box is
+ * created with Constructor II.
+ *
+ * For the derived features, see the basic class KDialogBase.
+ * @author Mirko Boehm (mirko@kde.org) and Espen Sand (espensa@online.no)
+ * @see KDialogBase
+ */
+class KDEUI_EXPORT KAboutDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Layout formats.
+ **/
+ enum LayoutType
+ {
+ AbtPlain = 0x0001,
+ AbtTabbed = 0x0002,
+ AbtTitle = 0x0004,
+ AbtImageLeft = 0x0008,
+ AbtImageRight = 0x0010,
+ AbtImageOnly = 0x0020,
+ AbtProduct = 0x0040,
+ AbtKDEStandard = AbtTabbed|AbtTitle|AbtImageLeft,
+ AbtAppStandard = AbtTabbed|AbtTitle|AbtProduct,
+ AbtImageAndTitle = AbtPlain|AbtTitle|AbtImageOnly
+ };
+
+ public:
+ /**
+ * The standard Qt constructor (Constructor I).
+ *
+ * Add components with the following methods:
+ * setLogo(), setAuthor(), setMaintainer(),
+ * addContributor(), or setVersion().
+ * The dialog will be laid out automatically.
+ */
+ KAboutDialog( QWidget *parent=0, const char *name=0, bool modal=true );
+
+ /**
+ * The extended constructor. (Constructor II).
+ *
+ * Add components with the methods:
+ * setTitle(), setImage(), setImageBackgroundColor(),
+ * setImageFrame(), setProduct(), addTextPage(),
+ * addContainerPage(), addContainer(), or addPage().
+ *
+ * @param dialogLayout Use a mask of LayoutType flags.
+ * @param caption The dialog caption. The text you specify is prepended
+ * by i18n("About").
+ * @param buttonMask Specifies what buttons will be visible.
+ * @param defaultButton Specifies what button will be marked as the default.
+ * @param parent Parent of the dialog.
+ * @param name Dialog name (for internal use only)
+ * @param modal Sets dialog modality. If false, the rest of the
+ * program interface (other dialogs, for example) is accessible while
+ * the dialog is open.
+ * @param separator If true, a separator line is drawn between the action
+ * buttons an the main widget.
+ * @param user1 User button1 text.
+ * @param user2 User button2 text.
+ * @param user3 User button3 text.
+ *
+ */
+ KAboutDialog( int dialogLayout, const QString &caption, int buttonMask,
+ ButtonCode defaultButton, QWidget *parent=0,
+ const char *name=0, bool modal=false, bool separator = false,
+ const QString &user1 = QString::null,
+ const QString &user2 = QString::null,
+ const QString &user3 = QString::null );
+
+ /**
+ * Adjusts the dialog.
+ *
+ * You can call this method after you have set up all
+ * the contents but it is not required. It is done automatically when
+ * show() is executed.
+ */
+ void adjust();
+
+ /**
+ * Makes a modeless (modal = false in constructor) dialog visible.
+ *
+ * If you reimplement this method make sure you run it
+ * in the new method (e.g., show()). Reimplemented
+ * from KDialogBase.
+ */
+ virtual void show( void );
+
+ /**
+ * Makes a modeless (modal = false in constructor) dialog visible.
+ *
+ * If you reimplmement this method make sure you run it
+ * in the new method (i.e., show( parent )).
+ *
+ * @param centerParent Center the dialog with respect to this widget.
+ */
+ virtual void show( QWidget *centerParent );
+
+ /**
+ * (Constructor II only)
+ * Sets a title (not caption) in the uppermost area of the dialog.
+ *
+ * @param title Title string.
+ */
+ void setTitle( const QString &title );
+
+ /**
+ * (Constructor II only)
+ * Define an image to be shown in the dialog. The position is dependent
+ * on the @p dialogLayout in the constructor
+ *
+ * @param fileName Path to image file.
+ */
+ void setImage( const QString &fileName );
+
+ /**
+ * (Constructor II only)
+ * Define the program logo to be shown in the dialog. Use this to override the
+ * default program logo. For example, use this function if the
+ * KAboutDialog is for a panel applet and you want to override the
+ * appletproxy logo with your own pixmap.
+ *
+ * @param fileName Path to file containing logo data in a format that
+ * can be loaded by QPixmap.
+ *
+ * @since 3.3
+ */
+ void setIcon( const QString &fileName ) KDE_DEPRECATED; // KDE4: remove
+
+ /**
+ * Overloaded version of setProgramLogo(const QPixmap& pixmap).
+ *
+ * @since 3.4
+ */
+ void setProgramLogo( const QString &fileName );
+
+ /**
+ * (Constructor II only)
+ * Define the program logo to be shown in the dialog. Use this to override the
+ * default program logo. For example, use this function if the
+ * KAboutDialog is for a panel applet and you want to override the
+ * appletproxy logo with your own pixmap.
+ *
+ * @param pixmap The logo pixmap.
+ *
+ * @since 3.4
+ */
+ void setProgramLogo( const QPixmap &pixmap );
+
+ /**
+ * (Constructor II only)
+ * The image has a minimum size, but is centered within an area if the
+ * dialog box is enlarged by the user. You set the background color
+ * of the area with this method.
+ *
+ * @param color Background color.
+ */
+ void setImageBackgroundColor( const QColor &color );
+
+ /**
+ * (Constructor II only)
+ * Enables or disables a frame around the image. The frame is, by default,
+ * enabled in the constructor
+ *
+ * @param state A value of @p true enables the frame
+ */
+ void setImageFrame( bool state );
+
+ /**
+ * (Constructor II only)
+ * Prints the application name, KDE version, author, a copyright sign
+ * and a year string. To the left of the text the standard application
+ * icon is displayed.
+ *
+ * @param appName The application name.
+ * @param version Application version.
+ * @param author One or more authors.
+ * @param year A string telling when the application was made.
+ */
+ void setProduct( const QString &appName, const QString &version,
+ const QString &author, const QString &year );
+
+ /**
+ * (Constructor II only)
+ * Adds a text page to a tab box. The text can be regular text or
+ * rich text. The rich text can contain URLs and mail links.
+ *
+ * @param title Tab name.
+ * @param text The text to display.
+ * @param richText Set this to @p true if 'text' is rich text.
+ * @param numLines The text area height will be adjusted so that this
+ * is the minimum number of lines of text that are visible.
+ * @return The frame that contains the page.
+ */
+ QFrame *addTextPage( const QString &title, const QString &text,
+ bool richText=false, int numLines=10 );
+
+ /**
+ * (Constructor II only)
+ * Adds a license page to a tab box.
+ *
+ * @param title Tab name.
+ * @param text The text to display.
+ * @param numLines The text area height will be adjusted so that this
+ * is the minimum number of lines of text that are visible.
+ * @return The frame that contains the page.
+ */
+ QFrame *addLicensePage( const QString &title, const QString &text,
+ int numLines=10 );
+
+ /**
+ * (Constructor II only)
+ * Adds a container to a tab box. You can add text and images to a
+ * container.
+ *
+ * @param title Tab name.
+ * @param childAlignment Specifies how the children of the container are
+ * aligned with respect to the container.
+ * @param innerAlignment Specifies how the children are aligned with
+ * respect to each other.
+ * @return The new container.
+ */
+ KAboutContainer *addContainerPage( const QString &title,
+ int childAlignment = AlignCenter, int innerAlignment = AlignCenter );
+
+ /**
+ * (Constructor II only)
+ * Adds a container inside a QScrollView to a tab box. You can add text
+ * and images to a container.
+ *
+ * @param title Tab name.
+ * @param childAlignment Specifies how the children of the container are
+ * aligned with respect to the container.
+ * @param innerAlignment Specifies how the children are aligned with
+ * respect to each other.
+ * @return The new container.
+ */
+ KAboutContainer *addScrolledContainerPage( const QString &title,
+ int childAlignment = AlignCenter, int innerAlignment = AlignCenter );
+
+ /**
+ * (Constructor II only)
+ * Adds a container. You can add text and images to a container.
+ *
+ * @param childAlignment Specifies how the children of the container are
+ * aligned with respect to the container.
+ * @param innerAlignment Specifies how the children are aligned with
+ * respect to each other.
+ * @return The new container.
+ */
+ KAboutContainer *addContainer( int childAlignment, int innerAlignment );
+
+ /**
+ * (Constructor II only)
+ * Adds an empty page to a tab box.
+ *
+ * @param title Tab name
+ * @return The new page.
+ */
+ QFrame *addPage( const QString &title );
+
+
+ /**
+ * (Constructor I only)
+ * Sets the image as the application logo.
+ */
+ void setLogo(const QPixmap&);
+
+ /**
+ * (Constructor I only)
+ * Sets the author's name and email address.
+ */
+ void setAuthor(const QString& name, const QString& email,
+ const QString& url, const QString& work);
+
+ /**
+ * (Constructor I only)
+ * Sets the maintainer's name and email address.
+ */
+ void setMaintainer(const QString& name, const QString& email,
+ const QString& url, const QString& work);
+
+ /**
+ * (Constructor I only)
+ * Show this person as one of the major contributors.
+ */
+ void addContributor(const QString& name, const QString& email,
+ const QString& url, const QString& work);
+
+ /**
+ * (Constructor I only)
+ * Sets the text describing the version.
+ */
+ void setVersion(const QString& name);
+
+ /**
+ * Create a modal dialog with an image in the upper area with a
+ * URL link below.
+ */
+ static void imageURL( QWidget *parent, const QString &caption,
+ const QString &path, const QColor &imageColor,
+ const QString &url );
+
+signals:
+ /**
+ * Send an email to this person.
+ *
+ * The application must provide the
+ * functionality.
+ */
+ void sendEmail(const QString& name, const QString& email);
+
+ /**
+ * Open the selected URL.
+ */
+ void openURL(const QString& url);
+ // ----------------------------------------------------------------------------
+protected:
+ /**
+ * The main widget (Constructor I)
+ */
+ KAboutWidget * about;
+
+ /**
+ * The main widget (Constructor II)
+ */
+ KAboutContainerBase *mContainerBase;
+
+ // -------------------------------------------------------------------------
+protected slots:
+
+ /**
+ * Connected to widget->sendEmail.
+ */
+ void sendEmailSlot(const QString& name, const QString& email);
+
+ /**
+ * Open this URL.
+ */
+ void openURLSlot(const QString& url);
+
+ /**
+ * (Constructor II only)
+ * Tells the position of the mouse cursor when the left mouse button
+ * is pressed above an image
+ */
+ virtual void mouseTrackSlot( int mode, const QMouseEvent *e );
+
+ // #########################################################################
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KAboutDialogPrivate* const d;
+};
+
+#endif // defined KABOUTDIALOG_H
diff --git a/kdeui/kaboutdialog_private.h b/kdeui/kaboutdialog_private.h
new file mode 100644
index 000000000..9546937af
--- /dev/null
+++ b/kdeui/kaboutdialog_private.h
@@ -0,0 +1,143 @@
+/*
+ * This file is part of the KDE Libraries
+ * Copyright (C) 1999-2001 Mirko Boehm (mirko@kde.org) and
+ * Espen Sand (espen@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef _KABOUTDIALOG_PRIVATE_H_
+#define _KABOUTDIALOG_PRIVATE_H_
+
+#include <qlabel.h>
+class QFrame;
+class QTabWidget;
+class QVBoxLayout;
+
+/**
+ * Used internally by KAboutContainerBase
+ * @internal
+ */
+class KImageTrackLabel : public QLabel
+{
+ Q_OBJECT
+
+ public:
+ enum MouseMode
+ {
+ MousePress = 1,
+ MouseRelease,
+ MouseDoubleClick,
+ MouseMove
+ };
+
+ public:
+ KImageTrackLabel( QWidget * parent, const char * name=0, WFlags f=0 );
+
+ signals:
+ void mouseTrack( int mode, const QMouseEvent *e );
+
+ protected:
+ virtual void mousePressEvent( QMouseEvent *e );
+ virtual void mouseReleaseEvent( QMouseEvent *e );
+ virtual void mouseDoubleClickEvent( QMouseEvent *e );
+ virtual void mouseMoveEvent ( QMouseEvent *e );
+};
+
+class KAboutContainer;
+
+class KAboutContainerBasePrivate;
+
+/**
+ * Used internally by KAboutDialog
+ * @internal
+ */
+class KAboutContainerBase : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ enum LayoutType
+ {
+ AbtPlain = 0x0001,
+ AbtTabbed = 0x0002,
+ AbtTitle = 0x0004,
+ AbtImageLeft = 0x0008,
+ AbtImageRight = 0x0010,
+ AbtImageOnly = 0x0020,
+ AbtProduct = 0x0040,
+ AbtKDEStandard = AbtTabbed|AbtTitle|AbtImageLeft,
+ AbtAppStandard = AbtTabbed|AbtTitle|AbtProduct,
+ AbtImageAndTitle = AbtPlain|AbtTitle|AbtImageOnly
+ };
+
+ public:
+ KAboutContainerBase( int layoutType, QWidget *parent = 0, char *name = 0 );
+ virtual void show( void );
+ virtual QSize sizeHint( void ) const;
+
+ void setTitle( const QString &title );
+ void setImage( const QString &fileName );
+ void setImageBackgroundColor( const QColor &color );
+ void setImageFrame( bool state );
+ void setProgramLogo( const QString &fileName );
+ void setProgramLogo( const QPixmap &pixmap );
+ void setProduct( const QString &appName, const QString &version,
+ const QString &author, const QString &year );
+
+ QFrame *addTextPage( const QString &title, const QString &text,
+ bool richText=false, int numLines=10 );
+ QFrame *addLicensePage( const QString &title, const QString &text,
+ int numLines=10 );
+ KAboutContainer *addContainerPage( const QString &title,
+ int childAlignment = AlignCenter, int innerAlignment = AlignCenter );
+ KAboutContainer *addScrolledContainerPage( const QString &title,
+ int childAlignment = AlignCenter, int innerAlignment = AlignCenter );
+
+ QFrame *addEmptyPage( const QString &title );
+
+ KAboutContainer *addContainer( int childAlignment, int innerAlignment );
+
+ public slots:
+ virtual void slotMouseTrack( int mode, const QMouseEvent *e );
+ virtual void slotUrlClick( const QString &url );
+ virtual void slotMailClick( const QString &name, const QString &address );
+
+ protected:
+ virtual void fontChange( const QFont &oldFont );
+
+ signals:
+ void mouseTrack( int mode, const QMouseEvent *e );
+ void urlClick( const QString &url );
+ void mailClick( const QString &name, const QString &address );
+
+ private:
+ QVBoxLayout *mTopLayout;
+ KImageTrackLabel *mImageLabel;
+ QLabel *mTitleLabel;
+ QLabel *mIconLabel;
+ QLabel *mVersionLabel;
+ QLabel *mAuthorLabel;
+ QFrame *mImageFrame;
+ QTabWidget *mPageTab;
+ QFrame *mPlainSpace;
+
+ KAboutContainerBasePrivate* const d;
+};
+
+
+#endif
diff --git a/kdeui/kaboutkde.cpp b/kdeui/kaboutkde.cpp
new file mode 100644
index 000000000..f6fe8cde9
--- /dev/null
+++ b/kdeui/kaboutkde.cpp
@@ -0,0 +1,89 @@
+/*
+ * This file is part of the KDE Libraries
+ * Copyright (C) 2000 Espen Sand (espen@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+// I (espen) prefer that header files are included alphabetically
+#include <kaboutkde.h>
+#include <kapplication.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+
+
+KAboutKDE::KAboutKDE( QWidget *parent, const char *name, bool modal )
+ :KAboutDialog( KAboutDialog::AbtKDEStandard, QString::fromLatin1("KDE"),
+ KDialogBase::Help|KDialogBase::Close, KDialogBase::Close,
+ parent, name, modal )
+{
+ const QString text1 = i18n(""
+ "The <b>K Desktop Environment</b> is written and maintained by the "
+ "KDE Team, a world-wide network of software engineers committed to "
+ "<a href=\"http://www.gnu.org/philosophy/free-sw.html\">Free Software</a> development.<br><br>"
+ "No single group, company or organization controls the KDE source "
+ "code. Everyone is welcome to contribute to KDE.<br><br>"
+ "Visit <A HREF=\"http://www.kde.org/\">http://www.kde.org</A> for "
+ "more information on the KDE project. ");
+
+ const QString text2 = i18n(""
+ "Software can always be improved, and the KDE Team is ready to "
+ "do so. However, you - the user - must tell us when "
+ "something does not work as expected or could be done better.<br><br>"
+ "The K Desktop Environment has a bug tracking system. Visit "
+ "<A HREF=\"http://bugs.kde.org/\">http://bugs.kde.org</A> or "
+ "use the \"Report Bug...\" dialog from the \"Help\" menu to report bugs.<br><br>"
+ "If you have a suggestion for improvement then you are welcome to use "
+ "the bug tracking system to register your wish. Make sure you use the "
+ "severity called \"Wishlist\"." );
+
+ const QString text3 = i18n(""
+ "You do not have to be a software developer to be a member of the "
+ "KDE team. You can join the national teams that translate "
+ "program interfaces. You can provide graphics, themes, sounds, and "
+ "improved documentation. You decide!"
+ "<br><br>"
+ "Visit "
+ "<A HREF=\"http://www.kde.org/jobs/\">http://www.kde.org/jobs/</A> "
+ "for information on some projects in which you can participate."
+ "<br><br>"
+ "If you need more information or documentation, then a visit to "
+ "<A HREF=\"http://developer.kde.org/\">http://developer.kde.org</A> "
+ "will provide you with what you need.");
+ const QString text4 = i18n(""
+ "KDE is available free of charge, but making it is not free.<br><br>"
+ "Thus, the KDE team formed the KDE e.V., a non-profit organization"
+ " legally founded in Tuebingen, Germany. The KDE e.V. represents"
+ " the KDE project in legal and financial matters."
+ " See <a href=\"http://www.kde-ev.org/\">http://www.kde-ev.org</a>"
+ " for information on the KDE e.V.<br><br>"
+ "The KDE team does need financial support. Most of the money is used to "
+ "reimburse members and others on expenses they experienced when "
+ "contributing to KDE. You are encouraged to support KDE through a financial "
+ "donation, using one of the ways described at "
+ "<a href=\"http://www.kde.org/support/\">http://www.kde.org/support/</a>."
+ "<br><br>Thank you very much in advance for your support.");
+ setHelp( QString::fromLatin1("khelpcenter/main.html"), QString::null );
+ setTitle(i18n("K Desktop Environment. Release %1").
+ arg(QString::fromLatin1(KDE_VERSION_STRING)) );
+ addTextPage( i18n("About KDE","&About"), text1, true );
+ addTextPage( i18n("&Report Bugs or Wishes"), text2, true );
+ addTextPage( i18n("&Join the KDE Team"), text3, true );
+ addTextPage( i18n("&Support KDE"), text4, true );
+ setImage( locate( "data", QString::fromLatin1("kdeui/pics/aboutkde.png")) );
+ setImageBackgroundColor( white );
+}
diff --git a/kdeui/kaboutkde.h b/kdeui/kaboutkde.h
new file mode 100644
index 000000000..357dc339a
--- /dev/null
+++ b/kdeui/kaboutkde.h
@@ -0,0 +1,62 @@
+/*
+ * This file is part of the KDE Libraries
+ * Copyright (C) 2000 Espen Sand (espen@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef _KABOUT_KDE_H_
+#define _KABOUT_KDE_H_
+
+#include <kaboutdialog.h>
+
+/**
+ * @short Standard "About KDE" dialog box,
+ *
+ * This class provides the standard "About KDE" dialog box that is used
+ * KHelpMenu Normally you should not use this class directly but
+ * rather the KHelpMenu class or even better just subclass your
+ * toplevel window from KMainWindow. If you do the latter, the help
+ * menu and thereby this dialog box is available through the
+ * KMainWindow::helpMenu() function.
+ *
+ * @author Espen Sand (espen@kde.org)
+ */
+
+class KDEUI_EXPORT KAboutKDE : public KAboutDialog
+{
+ public:
+ /**
+ * Constructor. Creates a fully featured "About KDE" dialog box.
+ * Note that this dialog is made modeless in the KHelpMenu class so
+ * the users may expect a modeless dialog.
+ *
+ * @param parent The parent of the dialog box. You should use the
+ * toplevel window so that the dialog becomes centered.
+ * @param name Internal name of the widget. This name in not used in the
+ * caption.
+ * @param modal If false, this widget will be modeless and must be
+ * made visible using QWidget::show(). Otherwise it will be
+ * modal and must be made visible using QWidget::exec()
+ */
+ KAboutKDE( QWidget *parent=0, const char *name=0, bool modal=true );
+};
+
+
+#endif
+
+
diff --git a/kdeui/kaccelgen.h b/kdeui/kaccelgen.h
new file mode 100644
index 000000000..2d5d69549
--- /dev/null
+++ b/kdeui/kaccelgen.h
@@ -0,0 +1,280 @@
+/* This file is part of the KDE project
+ Copyright (C) 2000 Keunwoo Lee <klee@cs.washington.edu>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KACCELGEN_H
+#define KACCELGEN_H
+
+#include <qmap.h>
+#include <qstring.h>
+#include <qstringlist.h>
+
+#include <kdelibs_export.h>
+
+/**
+ * Provides functions that, given a collection of QStrings, will
+ * automatically and intelligently assign menu accelerators to the
+ * QStrings in the collection.
+ *
+ * NOTE: When this file speaks of "accelerators", we really mean
+ * accelerators as defined by the KDE User Interface Guidelines. We
+ * do NOT mean "shortcuts", which are what's handled by most other KDE
+ * libraries with "accel" in the name.
+ *
+ * In the Qt library, the mechanism for adding a keyboard accelerator
+ * to a menu item is to insert an '&' before the letter. Since we
+ * usually don't want to disturb the original collection, the idiom in
+ * these functions is to populate a "target" QStringList parameter
+ * with the input collectin's QStrings, plus possibly some added '&'
+ * characters.
+ *
+ * That is the mechanism. Here is the policy, in order of decreasing
+ * importance (it may seem like these are implementation details, but
+ * IMHO the policy is an important part of the interface):
+ *
+ * 1. If the string already contains an '&' character, skip this
+ * string, because we consider such strings to be "user-specified"
+ * accelerators.
+ *
+ * 2. No accelerator may clash with a previously defined accelerator,
+ * including any legal (alphanumeric) user-specified accelerator
+ * anywhere in the collection
+ *
+ * 3. Prefer alphanumerics at the start of the string.
+ *
+ * 4. Otherwise, prefer alphanumerics at the start of a word.
+ *
+ * 5. Otherwise, choose any alphanumeric character not already
+ * taken. If no such character is available, give up & skip this
+ * string.
+ *
+ * A typical use of these functions would be to automatically assign
+ * accelerators to a dynamically populated popup menu. For example,
+ * the core code was written to automatically set accelerators for the
+ * "Load View Profile" popup menu for Konqueror. We quickly realized
+ * that it would be useful to make this facility more generally
+ * available, so I abstracted it out into a set of templates.
+ *
+ * TODO:
+ *
+ * + Add sugar functions for more collections.
+ *
+ * + Add more Deref classes so that we can access a wider variety of
+ * collections.
+ * */
+namespace KAccelGen
+{
+
+// HELPERS
+
+/**
+ * Static dereference class, for use as a template parameter.
+ */
+template <class Iter>
+class Deref
+{
+public:
+ static QString deref(Iter i) { return *i; }
+};
+
+/**
+ * Static dereference class that calls the key() method on its
+ * target; for use as a template parameter.
+ */
+template <class Iter>
+class Deref_Key
+{
+public:
+ static QString deref(Iter i) { return i.key(); }
+};
+
+/**
+ * Helper to determine if the given offset in the string could be a
+ * legal alphanumeric accelerator.
+ *
+ * @param str base string
+ * @param index offset to check
+ */
+inline bool
+isLegalAccelerator(const QString& str, uint index)
+{
+ return index < str.length()
+ && str[index].isLetterOrNumber();
+}
+
+/**
+ * Loads all legal predefined accelerators in the (implicitly
+ * specified) collection into the given QMap.
+ *
+ * @param begin start iterator
+ * @param end (last+1) iterator
+ * @param keys map to store output
+ */
+template <class Iter, class Deref>
+inline void
+loadPredefined(Iter begin, Iter end, QMap<QChar,bool>& keys)
+{
+ for (Iter i = begin; i != end; ++i) {
+ QString item = Deref::deref(i);
+ int user_ampersand = item.find(QChar('&'));
+ if( user_ampersand >= 0 ) {
+ // Sanity check. Note that we don't try to find an
+ // accelerator if the user shoots him/herself in the foot
+ // by adding a bad '&'.
+ if( isLegalAccelerator(item, user_ampersand+1) ) {
+ keys.insert(item[user_ampersand+1], true);
+ }
+ }
+ }
+}
+
+
+// ///////////////////////////////////////////////////////////////////
+// MAIN USER FUNCTIONS
+
+
+/**
+ * Main, maximally flexible template function that assigns
+ * accelerators to the elements of a collection of QStrings. Clients
+ * will seldom use this directly, as it's usually easier to use one of
+ * the wrapper functions that simply takes a collection (see below).
+ *
+ * The Deref template parameter is a class containing a static
+ * dereferencing function, modeled after the comparison class C in
+ * Stroustrup 13.4.
+ *
+ * @param begin (you know)
+ * @param end (you know)
+ * @param target collection to store generated strings
+ */
+template <class Iter, class Iter_Deref >
+void
+generate(Iter begin, Iter end, QStringList& target)
+{
+ // Will keep track of used accelerator chars
+ QMap<QChar,bool> used_accels;
+
+ // Prepass to detect manually user-coded accelerators
+ loadPredefined<Iter,Iter_Deref>(begin, end, used_accels);
+
+ // Main pass
+ for (Iter i = begin; i != end; ++i) {
+ QString item = Iter_Deref::deref(i);
+
+ // Attempt to find a good accelerator, but only if the user
+ // has not manually hardcoded one.
+ int user_ampersand = item.find(QChar('&'));
+ if( user_ampersand < 0 || item[user_ampersand+1] == '&') {
+ bool found = false;
+ uint found_idx;
+ uint j;
+
+ // Check word-starting letters first.
+ for( j=0; j < item.length(); ++j ) {
+ if( isLegalAccelerator(item, j)
+ && !used_accels.contains(item[j])
+ && (0 == j || (j > 0 && item[j-1].isSpace())) ) {
+ found = true;
+ found_idx = j;
+ break;
+ }
+ }
+
+ if( !found ) {
+ // No word-starting letter; search for any letter.
+ for( j=0; j < item.length(); ++j ) {
+ if( isLegalAccelerator(item, j)
+ && !used_accels.contains(item[j]) ) {
+ found = true;
+ found_idx = j;
+ break;
+ }
+ }
+ }
+
+ if( found ) {
+ // Both upper and lower case marked as used
+ used_accels.insert(item[j].upper(),true);
+ used_accels.insert(item[j].lower(),true);
+ item.insert(j,QChar('&'));
+ }
+ }
+
+ target.append( item );
+ }
+}
+
+/**
+ * Another convenience function; looks up the key instead of
+ * dereferencing directly for the given iterator.
+ *
+ * @param begin
+ * @param end
+ * @param target
+ */
+template <class Iter>
+inline void
+generateFromKeys(Iter begin, Iter end, QStringList& target)
+{
+ generate< Iter, Deref_Key<Iter> >(begin, end, target);
+}
+
+
+/**
+ * Convenience function; generates accelerators for all the items in
+ * a QStringList.
+ *
+ * @param source Strings for which to generate accelerators
+ * @param target Output for accelerator-added strings */
+inline void
+generate(const QStringList& source, QStringList& target)
+{
+ generate<QStringList::ConstIterator, Deref<QStringList::ConstIterator> >(source.begin(), source.end(), target);
+}
+
+/**
+ * Convenience function; generates accelerators for all the values in
+ * a QMap<T,QString>.
+ *
+ * @param source Map with input strings as VALUES.
+ * @param target Output for accelerator-added strings */
+template <class Key>
+inline void
+generateFromValues(const QMap<Key,QString>& source, QStringList& target)
+{
+ generate<QMapConstIterator<Key,QString>, Deref_Key<QMapConstIterator<Key,QString> > >(source.begin(), source.end(), target);
+}
+
+/**
+ * Convenience function; generates an accelerator mapping from all the
+ * keys in a QMap<QString,T>
+ *
+ * @param source Map with input strings as KEYS.
+ * @param target Output for accelerator-added strings */
+template <class Data>
+inline void
+generateFromKeys(const QMap<QString,Data>& source, QStringList& target)
+{
+ generateFromKeys(source.begin(), source.end(), target);
+}
+
+
+} // end namespace KAccelGen
+
+#endif
+
diff --git a/kdeui/kaction.cpp b/kdeui/kaction.cpp
new file mode 100644
index 000000000..2740763d9
--- /dev/null
+++ b/kdeui/kaction.cpp
@@ -0,0 +1,1278 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org>
+ (C) 1999 Simon Hausmann <hausmann@kde.org>
+ (C) 2000 Nicolas Hadacek <haadcek@kde.org>
+ (C) 2000 Kurt Granroth <granroth@kde.org>
+ (C) 2000 Michael Koch <koch@kde.org>
+ (C) 2001 Holger Freyther <freyther@kde.org>
+ (C) 2002 Ellis Whitehead <ellis@kde.org>
+ (C) 2002 Joseph Wenninger <jowenn@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kaction.h"
+
+#include <assert.h>
+
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+
+#include <kaccel.h>
+#include <kaccelbase.h>
+#include <kaccelprivate.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kguiitem.h>
+#include <kmainwindow.h>
+#include <kmenubar.h>
+#include <kpopupmenu.h>
+#include <ktoolbar.h>
+#include <ktoolbarbutton.h>
+
+/**
+* How it works.
+* KActionCollection is an organizing container for KActions.
+* KActionCollection keeps track of the information necessary to handle
+* configuration and shortcuts.
+*
+* Focus Widget pointer:
+* This is the widget which is the focus for action shortcuts.
+* It is set either by passing a QWidget* to the KActionCollection constructor
+* or by calling setWidget() if the widget wasn't known when the object was
+* initially constructed (as in KXMLGUIClient and KParts::PartBase)
+*
+* Shortcuts:
+* An action's shortcut will not not be connected unless a focus widget has
+* been specified in KActionCollection.
+*
+* XML Filename:
+* This is used to save user-modified settings back to the *ui.rc file.
+* It is set by KXMLGUIFactory.
+*/
+
+int KAction::getToolButtonID()
+{
+ static int toolbutton_no = -2;
+ return toolbutton_no--;
+}
+
+//---------------------------------------------------------------------
+// KAction::KActionPrivate
+//---------------------------------------------------------------------
+
+class KAction::KActionPrivate : public KGuiItem
+{
+public:
+ KActionPrivate() : KGuiItem()
+ {
+ m_kaccel = 0;
+ m_configurable = true;
+ }
+
+ KAccel *m_kaccel;
+ QValueList<KAccel*> m_kaccelList;
+
+ QString m_groupText;
+ QString m_group;
+
+ KShortcut m_cut;
+ KShortcut m_cutDefault;
+
+ bool m_configurable;
+
+ struct Container
+ {
+ Container() { m_container = 0; m_representative = 0; m_id = 0; }
+ Container( const Container& s ) { m_container = s.m_container;
+ m_id = s.m_id; m_representative = s.m_representative; }
+ QWidget* m_container;
+ int m_id;
+ QWidget* m_representative;
+ };
+
+ QValueList<Container> m_containers;
+};
+
+//---------------------------------------------------------------------
+// KAction
+//---------------------------------------------------------------------
+
+KAction::KAction( const QString& text, const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ KActionCollection* parent, const char* name )
+: QObject( parent, name ), d(new KActionPrivate)
+{
+ initPrivate( text, cut, receiver, slot );
+}
+
+KAction::KAction( const QString& text, const QString& sIconName, const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ KActionCollection* parent, const char* name )
+: QObject( parent, name ), d(new KActionPrivate)
+{
+ initPrivate( text, cut, receiver, slot );
+ d->setIconName( sIconName );
+}
+
+KAction::KAction( const QString& text, const QIconSet& pix, const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ KActionCollection* parent, const char* name )
+: QObject( parent, name ), d(new KActionPrivate)
+{
+ initPrivate( text, cut, receiver, slot );
+ d->setIconSet( pix );
+}
+
+KAction::KAction( const KGuiItem& item, const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ KActionCollection* parent, const char* name )
+: QObject( parent, name ), d(new KActionPrivate)
+{
+ initPrivate( item.text(), cut, receiver, slot );
+ if( item.hasIcon() )
+ setIcon( item.iconName() );
+ setToolTip( item.toolTip() );
+ setWhatsThis( item.whatsThis() );
+}
+
+#ifndef KDE_NO_COMPAT // KDE 4: remove
+KAction::KAction( const QString& text, const KShortcut& cut,
+ QObject* parent, const char* name )
+ : QObject( parent, name ), d(new KActionPrivate)
+{
+ initPrivate( text, cut, 0, 0 );
+}
+
+KAction::KAction( const QString& text, const KShortcut& cut,
+ const QObject* receiver,
+ const char* slot, QObject* parent, const char* name )
+ : QObject( parent, name ), d(new KActionPrivate)
+{
+ initPrivate( text, cut, receiver, slot );
+}
+
+KAction::KAction( const QString& text, const QIconSet& pix,
+ const KShortcut& cut,
+ QObject* parent, const char* name )
+ : QObject( parent, name ), d(new KActionPrivate)
+{
+ initPrivate( text, cut, 0, 0 );
+ setIconSet( pix );
+}
+
+KAction::KAction( const QString& text, const QString& pix,
+ const KShortcut& cut,
+ QObject* parent, const char* name )
+: QObject( parent, name ), d(new KActionPrivate)
+{
+ initPrivate( text, cut, 0, 0 );
+ d->setIconName( pix );
+}
+
+KAction::KAction( const QString& text, const QIconSet& pix,
+ const KShortcut& cut,
+ const QObject* receiver, const char* slot, QObject* parent,
+ const char* name )
+ : QObject( parent, name ), d(new KActionPrivate)
+{
+ initPrivate( text, cut, receiver, slot );
+ setIconSet( pix );
+}
+
+KAction::KAction( const QString& text, const QString& pix,
+ const KShortcut& cut,
+ const QObject* receiver, const char* slot, QObject* parent,
+ const char* name )
+ : QObject( parent, name ), d(new KActionPrivate)
+{
+ initPrivate( text, cut, receiver, slot );
+ d->setIconName(pix);
+}
+
+KAction::KAction( QObject* parent, const char* name )
+ : QObject( parent, name ), d(new KActionPrivate)
+{
+ initPrivate( QString::null, KShortcut(), 0, 0 );
+}
+#endif // KDE 4: remove end
+
+KAction::~KAction()
+{
+ kdDebug(129) << "KAction::~KAction( this = \"" << name() << "\" )" << endl; // -- ellis
+#ifndef KDE_NO_COMPAT
+ if (d->m_kaccel)
+ unplugAccel();
+#endif
+
+ // If actionCollection hasn't already been destructed,
+ if ( m_parentCollection ) {
+ m_parentCollection->take( this );
+
+ const QValueList<KAccel*> & accelList = d->m_kaccelList;
+ QValueList<KAccel*>::const_iterator itr = accelList.constBegin();
+ const QValueList<KAccel*>::const_iterator itrEnd = accelList.constEnd();
+
+ const char * const namePtr = name();
+ for (; itr != itrEnd; ++itr )
+ (*itr)->remove(namePtr);
+
+ }
+
+ // Do not call unplugAll from here, as tempting as it sounds.
+ // KAction is designed around the idea that you need to plug
+ // _and_ to unplug it "manually". Unplugging leads to an important
+ // slowdown when e.g. closing the window, in which case we simply
+ // want to destroy everything asap, not to remove actions one by one
+ // from the GUI.
+
+ delete d;
+}
+
+void KAction::initPrivate( const QString& text, const KShortcut& cut,
+ const QObject* receiver, const char* slot )
+{
+ d->m_cutDefault = cut;
+
+ m_parentCollection = dynamic_cast<KActionCollection *>( parent() );
+ kdDebug(129) << "KAction::initPrivate(): this = " << this << " name = \"" << name() << "\" cut = " << cut.toStringInternal() << " m_parentCollection = " << m_parentCollection << endl;
+ if ( m_parentCollection )
+ m_parentCollection->insert( this );
+
+ if ( receiver && slot )
+ connect( this, SIGNAL( activated() ), receiver, slot );
+
+ if( !cut.isNull() && !qstrcmp( name(), "unnamed" ) )
+ kdWarning(129) << "KAction::initPrivate(): trying to assign a shortcut (" << cut.toStringInternal() << ") to an unnamed action." << endl;
+ d->setText( text );
+ initShortcut( cut );
+}
+
+bool KAction::isPlugged() const
+{
+ return (!d->m_containers.empty()) || d->m_kaccel;
+}
+
+bool KAction::isPlugged( const QWidget *container ) const
+{
+ return findContainer( container ) > -1;
+}
+
+bool KAction::isPlugged( const QWidget *container, int id ) const
+{
+ int i = findContainer( container );
+ return ( i > -1 && itemId( i ) == id );
+}
+
+bool KAction::isPlugged( const QWidget *container, const QWidget *_representative ) const
+{
+ int i = findContainer( container );
+ return ( i > -1 && representative( i ) == _representative );
+}
+
+
+/*
+Three actionCollection conditions:
+ 1) Scope is known on creation and KAccel object is created (e.g. KMainWindow)
+ 2) Scope is unknown and no KAccel object is available (e.g. KXMLGUIClient)
+ a) addClient() will be called on object
+ b) we just want to add the actions to another KXMLGUIClient object
+
+The question is how to do we incorporate #2b into the XMLGUI framework?
+
+
+We have a KCommandHistory object with undo and redo actions in a passed actionCollection
+We have a KoDoc object which holds a KCommandHistory object and the actionCollection
+We have two KoView objects which both point to the same KoDoc object
+Undo and Redo should be available in both KoView objects, and
+ calling the undo->setEnabled() should affect both KoViews
+
+When addClient is called, it needs to be able to find the undo and redo actions
+When it calls plug() on them, they need to be inserted into the KAccel object of the appropriate KoView
+
+In this case, the actionCollection belongs to KoDoc and we need to let it know that its shortcuts
+have the same scope as the KoView actionCollection
+
+KXMLGUIClient::addSubActionCollection
+
+Document:
+ create document actions
+
+View
+ create view actions
+ add document actionCollection as sub-collection
+
+A parentCollection is created
+Scenario 1: parentCollection has a focus widget set (e.g. via KMainWindow)
+ A KAccel object is created in the parentCollection
+ A KAction is created with parent=parentCollection
+ The shortcut is inserted into this actionCollection
+ Scenario 1a: xml isn't used
+ done
+ Scenario 1b: KXMLGUIBuilder::addClient() called
+ setWidget is called -- ignore
+ shortcuts are set
+Scenario 2: parentCollection has no focus widget (e.g., KParts)
+ A KAction is created with parent=parentCollection
+ Scenario 2a: xml isn't used
+ no shortcuts
+ Scenario 2b: KXMLGUIBuilder::addClient() called
+ setWidget is called
+ shortcuts are inserted into current KAccel
+ shortcuts are set in all other KAccels, if the action is present in the other KAccels
+*/
+
+/*
+shortcut may be set:
+ - on construction
+ - on plug
+ - on reading XML
+ - on plugAccel (deprecated)
+
+On Construction: [via initShortcut()]
+ insert into KAccel of m_parentCollection,
+ if kaccel() && isAutoConnectShortcuts() exists
+
+On Plug: [via plug() -> plugShortcut()]
+ insert into KAccel of m_parentCollection, if exists and not already inserted into
+
+On Read XML: [via setShortcut()]
+ set in all current KAccels
+ insert into KAccel of m_parentCollection, if exists and not already inserted into
+*/
+
+KAccel* KAction::kaccelCurrent()
+{
+ if( m_parentCollection && m_parentCollection->builderKAccel() )
+ return m_parentCollection->builderKAccel();
+ else if( m_parentCollection && m_parentCollection->kaccel() )
+ return m_parentCollection->kaccel();
+ else
+ return 0L;
+}
+
+// Only to be called from initPrivate()
+bool KAction::initShortcut( const KShortcut& cut )
+{
+ d->m_cut = cut;
+
+ // Only insert action into KAccel if it has a valid name,
+ if( qstrcmp( name(), "unnamed" ) &&
+ m_parentCollection &&
+ m_parentCollection->isAutoConnectShortcuts() &&
+ m_parentCollection->kaccel() )
+ {
+ insertKAccel( m_parentCollection->kaccel() );
+ return true;
+ }
+ return false;
+ }
+
+// Only to be called from plug()
+void KAction::plugShortcut()
+{
+ KAccel* const kaccel = kaccelCurrent();
+
+ //kdDebug(129) << "KAction::plugShortcut(): this = " << this << " kaccel() = " << (m_parentCollection ? m_parentCollection->kaccel() : 0) << endl;
+ if( kaccel && qstrcmp( name(), "unnamed" ) ) {
+ // Check if already plugged into current KAccel object
+ const QValueList<KAccel*> & accelList = d->m_kaccelList;
+ QValueList<KAccel*>::const_iterator itr = accelList.constBegin();
+ const QValueList<KAccel*>::const_iterator itrEnd = accelList.constEnd();
+
+ for( ; itr != itrEnd; ++itr) {
+ if( (*itr) == kaccel )
+ return;
+ }
+
+ insertKAccel( kaccel );
+ }
+}
+
+bool KAction::setShortcut( const KShortcut& cut )
+{
+ bool bChanged = (d->m_cut != cut);
+ d->m_cut = cut;
+
+ KAccel* const kaccel = kaccelCurrent();
+ bool bInsertRequired = true;
+ // Apply new shortcut to all existing KAccel objects
+
+ const QValueList<KAccel*> & accelList = d->m_kaccelList;
+ QValueList<KAccel*>::const_iterator itr = accelList.constBegin();
+ const QValueList<KAccel*>::const_iterator itrEnd = accelList.constEnd();
+
+ for( ; itr != itrEnd; ++itr) {
+ // Check whether shortcut has already been plugged into
+ // the current kaccel object.
+ if( (*itr) == kaccel )
+ bInsertRequired = false;
+ if( bChanged )
+ updateKAccelShortcut( *itr );
+ }
+
+ // Only insert action into KAccel if it has a valid name,
+ if( kaccel && bInsertRequired && qstrcmp( name(), "unnamed" ) )
+ insertKAccel( kaccel );
+
+ if( bChanged ) {
+#ifndef KDE_NO_COMPAT // KDE 4: remove
+ if ( d->m_kaccel )
+ d->m_kaccel->setShortcut( name(), cut );
+#endif // KDE 4: remove end
+ int len = containerCount();
+ for( int i = 0; i < len; ++i )
+ updateShortcut( i );
+ }
+ return true;
+}
+
+bool KAction::updateKAccelShortcut( KAccel* kaccel )
+{
+ // Check if action is permitted
+ if (kapp && !kapp->authorizeKAction(name()))
+ return false;
+
+ bool b = true;
+
+ if ( !kaccel->actions().actionPtr( name() ) ) {
+ if(!d->m_cut.isNull() ) {
+ kdDebug(129) << "Inserting " << name() << ", " << d->text() << ", " << d->plainText() << endl;
+ b = kaccel->insert( name(), d->plainText(), QString::null,
+ d->m_cut,
+ this, SLOT(slotActivated()),
+ isShortcutConfigurable(), isEnabled() );
+ }
+ }
+ else
+ b = kaccel->setShortcut( name(), d->m_cut );
+
+ return b;
+}
+
+void KAction::insertKAccel( KAccel* kaccel )
+{
+ //kdDebug(129) << "KAction::insertKAccel( " << kaccel << " ): this = " << this << endl;
+ if ( !kaccel->actions().actionPtr( name() ) ) {
+ if( updateKAccelShortcut( kaccel ) ) {
+ d->m_kaccelList.append( kaccel );
+ connect( kaccel, SIGNAL(destroyed()), this, SLOT(slotDestroyed()) );
+ }
+ }
+ else
+ kdWarning(129) << "KAction::insertKAccel( kaccel = " << kaccel << " ): KAccel object already contains an action name \"" << name() << "\"" << endl; // -- ellis
+}
+
+void KAction::removeKAccel( KAccel* kaccel )
+{
+ //kdDebug(129) << "KAction::removeKAccel( " << i << " ): this = " << this << endl;
+ QValueList<KAccel*> & accelList = d->m_kaccelList;
+ QValueList<KAccel*>::iterator itr = accelList.begin();
+ const QValueList<KAccel*>::iterator itrEnd = accelList.end();
+
+ for( ; itr != itrEnd; ++itr) {
+ if( (*itr) == kaccel ) {
+ kaccel->remove( name() );
+ accelList.remove( itr );
+ disconnect( kaccel, SIGNAL(destroyed()), this, SLOT(slotDestroyed()) );
+ break;
+ }
+ }
+}
+
+#ifndef KDE_NO_COMPAT
+// KDE 4: remove
+void KAction::setAccel( int keyQt )
+{
+ setShortcut( KShortcut(keyQt) );
+}
+#endif // KDE 4: remove end
+
+void KAction::updateShortcut( int i )
+{
+ int id = itemId( i );
+
+ QWidget* w = container( i );
+ if ( ::qt_cast<QPopupMenu *>( w ) ) {
+ QPopupMenu* menu = static_cast<QPopupMenu*>(w);
+ updateShortcut( menu, id );
+ }
+ else if ( ::qt_cast<QMenuBar *>( w ) )
+ static_cast<QMenuBar*>(w)->setAccel( d->m_cut.keyCodeQt(), id );
+}
+
+void KAction::updateShortcut( QPopupMenu* menu, int id )
+{
+ //kdDebug(129) << "KAction::updateShortcut(): this = " << this << " d->m_kaccelList.count() = " << d->m_kaccelList.count() << endl;
+ // If the action has a KAccel object,
+ // show the string representation of its shortcut.
+ if ( d->m_kaccel || d->m_kaccelList.count() ) {
+ QString s = menu->text( id );
+ int i = s.find( '\t' );
+ if ( i >= 0 )
+ s.replace( i+1, s.length()-i, d->m_cut.seq(0).toString() );
+ else
+ s += "\t" + d->m_cut.seq(0).toString();
+
+ menu->changeItem( id, s );
+ }
+ // Otherwise insert the shortcut itself into the popup menu.
+ else {
+ // This is a fall-hack in case the KAction is missing a proper parent collection.
+ // It should be removed eventually. --ellis
+ menu->setAccel( d->m_cut.keyCodeQt(), id );
+ kdDebug(129) << "KAction::updateShortcut(): name = \"" << name() << "\", cut = " << d->m_cut.toStringInternal() << "; No KAccel, probably missing a parent collection." << endl;
+ }
+}
+
+const KShortcut& KAction::shortcut() const
+{
+ return d->m_cut;
+}
+
+const KShortcut& KAction::shortcutDefault() const
+{
+ return d->m_cutDefault;
+}
+
+QString KAction::shortcutText() const
+{
+ return d->m_cut.toStringInternal();
+}
+
+void KAction::setShortcutText( const QString& s )
+{
+ setShortcut( KShortcut(s) );
+}
+
+#ifndef KDE_NO_COMPAT // Remove in KDE 4
+int KAction::accel() const
+{
+ return d->m_cut.keyCodeQt();
+}
+#endif
+
+void KAction::setGroup( const QString& grp )
+{
+ d->m_group = grp;
+
+ int len = containerCount();
+ for( int i = 0; i < len; ++i )
+ updateGroup( i );
+}
+
+void KAction::updateGroup( int )
+{
+ // DO SOMETHING
+}
+
+QString KAction::group() const
+{
+ return d->m_group;
+}
+
+bool KAction::isEnabled() const
+{
+ return d->isEnabled();
+}
+
+bool KAction::isShortcutConfigurable() const
+{
+ return d->m_configurable;
+}
+
+void KAction::setToolTip( const QString& tt )
+{
+ d->setToolTip( tt );
+
+ int len = containerCount();
+ for( int i = 0; i < len; ++i )
+ updateToolTip( i );
+}
+
+void KAction::updateToolTip( int i )
+{
+ QWidget *w = container( i );
+
+ if ( ::qt_cast<KToolBar *>( w ) )
+ QToolTip::add( static_cast<KToolBar*>(w)->getWidget( itemId( i ) ), d->toolTip() );
+}
+
+QString KAction::toolTip() const
+{
+ return d->toolTip();
+}
+
+int KAction::plug( QWidget *w, int index )
+{
+ //kdDebug(129) << "KAction::plug( " << w << ", " << index << " )" << endl;
+ if (!w ) {
+ kdWarning(129) << "KAction::plug called with 0 argument\n";
+ return -1;
+ }
+
+ // Ellis: print warning if there is a shortcut, but no KAccel available (often due to no widget available in the actioncollection)
+ // David: Well, it doesn't matter much, things still work (e.g. Undo in koffice) via QAccel.
+ // We should probably re-enable the warning for things that only KAccel can do, though - e.g. WIN key (mapped to Meta).
+#if 0 //ndef NDEBUG
+ KAccel* kaccel = kaccelCurrent();
+ if( !d->m_cut.isNull() && !kaccel ) {
+ kdDebug(129) << "KAction::plug(): has no KAccel object; this = " << this << " name = " << name() << " parentCollection = " << m_parentCollection << endl; // ellis
+ }
+#endif
+
+ // Check if action is permitted
+ if (kapp && !kapp->authorizeKAction(name()))
+ return -1;
+
+ plugShortcut();
+
+ if ( ::qt_cast<QPopupMenu *>( w ) )
+ {
+ QPopupMenu* menu = static_cast<QPopupMenu*>( w );
+ int id;
+ // Don't insert shortcut into menu if it's already in a KAccel object.
+ int keyQt = (d->m_kaccelList.count() || d->m_kaccel) ? 0 : d->m_cut.keyCodeQt();
+
+ if ( d->hasIcon() )
+ {
+ KInstance *instance;
+ if ( m_parentCollection )
+ instance = m_parentCollection->instance();
+ else
+ instance = KGlobal::instance();
+ id = menu->insertItem( d->iconSet( KIcon::Small, 0, instance ), d->text(), this,//dsweet
+ SLOT( slotPopupActivated() ), keyQt,
+ -1, index );
+ }
+ else
+ id = menu->insertItem( d->text(), this,
+ SLOT( slotPopupActivated() ),
+ keyQt, -1, index );
+
+ // If the shortcut is already in a KAccel object, then
+ // we need to set the menu item's shortcut text.
+ if ( d->m_kaccelList.count() || d->m_kaccel )
+ updateShortcut( menu, id );
+
+ // call setItemEnabled only if the item really should be disabled,
+ // because that method is slow and the item is per default enabled
+ if ( !d->isEnabled() )
+ menu->setItemEnabled( id, false );
+
+ if ( !d->whatsThis().isEmpty() )
+ menu->setWhatsThis( id, whatsThisWithIcon() );
+
+ addContainer( menu, id );
+ connect( menu, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) );
+
+ if ( m_parentCollection )
+ m_parentCollection->connectHighlight( menu, this );
+
+ return d->m_containers.count() - 1;
+ }
+ else if ( ::qt_cast<KToolBar *>( w ) )
+ {
+ KToolBar *bar = static_cast<KToolBar *>( w );
+
+ int id_ = getToolButtonID();
+ KInstance *instance;
+ if ( m_parentCollection )
+ instance = m_parentCollection->instance();
+ else
+ instance = KGlobal::instance();
+
+ if ( icon().isEmpty() && !iconSet().pixmap().isNull() ) // old code using QIconSet directly
+ {
+ bar->insertButton( iconSet().pixmap(), id_, SIGNAL( buttonClicked(int, Qt::ButtonState) ), this,
+ SLOT( slotButtonClicked(int, Qt::ButtonState) ),
+ d->isEnabled(), d->plainText(), index );
+ }
+ else
+ {
+ QString icon = d->iconName();
+ if ( icon.isEmpty() )
+ icon = "unknown";
+ bar->insertButton( icon, id_, SIGNAL( buttonClicked(int, Qt::ButtonState) ), this,
+ SLOT( slotButtonClicked(int, Qt::ButtonState) ),
+ d->isEnabled(), d->plainText(), index, instance );
+ }
+
+ KToolBarButton* ktb = bar->getButton(id_);
+ ktb->setName( QCString("toolbutton_")+name() );
+
+ if ( !d->whatsThis().isEmpty() )
+ QWhatsThis::add( bar->getButton(id_), whatsThisWithIcon() );
+
+ if ( !d->toolTip().isEmpty() )
+ QToolTip::add( bar->getButton(id_), d->toolTip() );
+
+ addContainer( bar, id_ );
+
+ connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) );
+
+ if ( m_parentCollection )
+ m_parentCollection->connectHighlight( bar, this );
+
+ return containerCount() - 1;
+ }
+
+ return -1;
+}
+
+void KAction::unplug( QWidget *w )
+{
+ int i = findContainer( w );
+ if ( i == -1 )
+ return;
+ int id = itemId( i );
+
+ if ( ::qt_cast<QPopupMenu *>( w ) )
+ {
+ QPopupMenu *menu = static_cast<QPopupMenu *>( w );
+ menu->removeItem( id );
+ }
+ else if ( ::qt_cast<KToolBar *>( w ) )
+ {
+ KToolBar *bar = static_cast<KToolBar *>( w );
+ bar->removeItemDelayed( id );
+ }
+ else if ( ::qt_cast<QMenuBar *>( w ) )
+ {
+ QMenuBar *bar = static_cast<QMenuBar *>( w );
+ bar->removeItem( id );
+ }
+
+ removeContainer( i );
+ if ( m_parentCollection )
+ m_parentCollection->disconnectHighlight( w, this );
+}
+
+void KAction::plugAccel(KAccel *kacc, bool configurable)
+{
+ kdWarning(129) << "KAction::plugAccel(): call to deprecated action." << endl;
+ kdDebug(129) << kdBacktrace() << endl;
+ //kdDebug(129) << "KAction::plugAccel( kacc = " << kacc << " ): name \"" << name() << "\"" << endl;
+ if ( d->m_kaccel )
+ unplugAccel();
+
+ // If the parent collection's accel ptr isn't set yet
+ //if ( m_parentCollection && !m_parentCollection->accel() )
+ // m_parentCollection->setAccel( kacc );
+
+ // We can only plug this action into the given KAccel object
+ // if it does not already contain an action with the same name.
+ if ( !kacc->actions().actionPtr(name()) )
+ {
+ d->m_kaccel = kacc;
+ d->m_kaccel->insert(name(), d->plainText(), QString::null,
+ KShortcut(d->m_cut),
+ this, SLOT(slotActivated()),
+ configurable, isEnabled());
+ connect(d->m_kaccel, SIGNAL(destroyed()), this, SLOT(slotDestroyed()));
+ //connect(d->m_kaccel, SIGNAL(keycodeChanged()), this, SLOT(slotKeycodeChanged()));
+ }
+ else
+ kdWarning(129) << "KAction::plugAccel( kacc = " << kacc << " ): KAccel object already contains an action name \"" << name() << "\"" << endl; // -- ellis
+}
+
+void KAction::unplugAccel()
+{
+ //kdDebug(129) << "KAction::unplugAccel() " << this << " " << name() << endl;
+ if ( d->m_kaccel )
+ {
+ d->m_kaccel->remove(name());
+ d->m_kaccel = 0;
+ }
+}
+
+void KAction::plugMainWindowAccel( QWidget *w )
+{
+ // Note: topLevelWidget() stops too early, we can't use it.
+ QWidget * tl = w;
+ QWidget * n;
+ while ( !tl->isDialog() && ( n = tl->parentWidget() ) ) // lookup parent and store
+ tl = n;
+
+ KMainWindow * mw = dynamic_cast<KMainWindow *>(tl); // try to see if it's a kmainwindow
+ if (mw)
+ plugAccel( mw->accel() );
+ else
+ kdDebug(129) << "KAction::plugMainWindowAccel: Toplevel widget isn't a KMainWindow, can't plug accel. " << tl << endl;
+}
+
+void KAction::setEnabled(bool enable)
+{
+ //kdDebug(129) << "KAction::setEnabled( " << enable << " ): this = " << this << " d->m_kaccelList.count() = " << d->m_kaccelList.count() << endl;
+ if ( enable == d->isEnabled() )
+ return;
+
+#ifndef KDE_NO_COMPAT
+ // KDE 4: remove
+ if (d->m_kaccel)
+ d->m_kaccel->setEnabled(name(), enable);
+#endif // KDE 4: remove end
+
+ const QValueList<KAccel*> & accelList = d->m_kaccelList;
+ QValueList<KAccel*>::const_iterator itr = accelList.constBegin();
+ const QValueList<KAccel*>::const_iterator itrEnd = accelList.constEnd();
+
+ const char * const namePtr = name();
+
+ for ( ; itr != itrEnd; ++itr )
+ (*itr)->setEnabled( namePtr, enable );
+
+ d->setEnabled( enable );
+
+ int len = containerCount();
+ for( int i = 0; i < len; ++i )
+ updateEnabled( i );
+
+ emit enabled( d->isEnabled() );
+}
+
+void KAction::updateEnabled( int i )
+{
+ QWidget *w = container( i );
+
+ if ( ::qt_cast<QPopupMenu *>( w ) )
+ static_cast<QPopupMenu*>(w)->setItemEnabled( itemId( i ), d->isEnabled() );
+ else if ( ::qt_cast<QMenuBar *>( w ) )
+ static_cast<QMenuBar*>(w)->setItemEnabled( itemId( i ), d->isEnabled() );
+ else if ( ::qt_cast<KToolBar *>( w ) )
+ static_cast<KToolBar*>(w)->setItemEnabled( itemId( i ), d->isEnabled() );
+}
+
+void KAction::setShortcutConfigurable( bool b )
+{
+ d->m_configurable = b;
+}
+
+void KAction::setText( const QString& text )
+{
+#ifndef KDE_NO_COMPAT
+ // KDE 4: remove
+ if (d->m_kaccel) {
+ KAccelAction* pAction = d->m_kaccel->actions().actionPtr(name());
+ if (pAction)
+ pAction->setLabel( text );
+ }
+#endif // KDE 4: remove end
+ const QValueList<KAccel*> & accelList = d->m_kaccelList;
+ QValueList<KAccel*>::const_iterator itr = accelList.constBegin();
+ const QValueList<KAccel*>::const_iterator itrEnd = accelList.constEnd();
+
+ const char * const namePtr = name();
+
+ for( ; itr != itrEnd; ++itr ) {
+ KAccelAction* const pAction = (*itr)->actions().actionPtr(namePtr);
+ if (pAction)
+ pAction->setLabel( text );
+ }
+
+ d->setText( text );
+
+ int len = containerCount();
+ for( int i = 0; i < len; ++i )
+ updateText( i );
+}
+
+void KAction::updateText( int i )
+{
+ QWidget *w = container( i );
+
+ if ( ::qt_cast<QPopupMenu *>( w ) ) {
+ int id = itemId( i );
+ static_cast<QPopupMenu*>(w)->changeItem( id, d->text() );
+ if (!d->m_cut.isNull())
+ updateShortcut( static_cast<QPopupMenu*>(w), id );
+ }
+ else if ( ::qt_cast<QMenuBar *>( w ) )
+ static_cast<QMenuBar*>(w)->changeItem( itemId( i ), d->text() );
+ else if ( ::qt_cast<KToolBar *>( w ) )
+ {
+ QWidget *button = static_cast<KToolBar *>(w)->getWidget( itemId( i ) );
+ if ( ::qt_cast<KToolBarButton *>( button ) )
+ static_cast<KToolBarButton *>(button)->setText( d->plainText() );
+ }
+}
+
+QString KAction::text() const
+{
+ return d->text();
+}
+
+QString KAction::plainText() const
+{
+ return d->plainText( );
+}
+
+void KAction::setIcon( const QString &icon )
+{
+ d->setIconName( icon );
+
+ // now handle any toolbars
+ int len = containerCount();
+ for ( int i = 0; i < len; ++i )
+ updateIcon( i );
+}
+
+void KAction::updateIcon( int id )
+{
+ QWidget* w = container( id );
+
+ if ( ::qt_cast<QPopupMenu *>( w ) ) {
+ int itemId_ = itemId( id );
+ static_cast<QPopupMenu*>(w)->changeItem( itemId_, d->iconSet( KIcon::Small ), d->text() );
+ if (!d->m_cut.isNull())
+ updateShortcut( static_cast<QPopupMenu*>(w), itemId_ );
+ }
+ else if ( ::qt_cast<QMenuBar *>( w ) )
+ static_cast<QMenuBar*>(w)->changeItem( itemId( id ), d->iconSet( KIcon::Small ), d->text() );
+ else if ( ::qt_cast<KToolBar *>( w ) )
+ static_cast<KToolBar *>(w)->setButtonIcon( itemId( id ), d->iconName() );
+}
+
+QString KAction::icon() const
+{
+ return d->iconName( );
+}
+
+void KAction::setIconSet( const QIconSet &iconset )
+{
+ d->setIconSet( iconset );
+
+ int len = containerCount();
+ for( int i = 0; i < len; ++i )
+ updateIconSet( i );
+}
+
+
+void KAction::updateIconSet( int id )
+{
+ QWidget *w = container( id );
+
+ if ( ::qt_cast<QPopupMenu *>( w ) )
+ {
+ int itemId_ = itemId( id );
+ static_cast<QPopupMenu*>(w)->changeItem( itemId_, d->iconSet(), d->text() );
+ if (!d->m_cut.isNull())
+ updateShortcut( static_cast<QPopupMenu*>(w), itemId_ );
+ }
+ else if ( ::qt_cast<QMenuBar *>( w ) )
+ static_cast<QMenuBar*>(w)->changeItem( itemId( id ), d->iconSet(), d->text() );
+ else if ( ::qt_cast<KToolBar *>( w ) )
+ {
+ if ( icon().isEmpty() && d->hasIcon() ) // only if there is no named icon ( scales better )
+ static_cast<KToolBar *>(w)->setButtonIconSet( itemId( id ), d->iconSet() );
+ else
+ static_cast<KToolBar *>(w)->setButtonIconSet( itemId( id ), d->iconSet( KIcon::Small ) );
+ }
+}
+
+QIconSet KAction::iconSet( KIcon::Group group, int size ) const
+{
+ return d->iconSet( group, size );
+}
+
+bool KAction::hasIcon() const
+{
+ return d->hasIcon();
+}
+
+void KAction::setWhatsThis( const QString& text )
+{
+ d->setWhatsThis( text );
+
+ int len = containerCount();
+ for( int i = 0; i < len; ++i )
+ updateWhatsThis( i );
+}
+
+void KAction::updateWhatsThis( int i )
+{
+ QPopupMenu* pm = popupMenu( i );
+ if ( pm )
+ {
+ pm->setWhatsThis( itemId( i ), d->whatsThis() );
+ return;
+ }
+
+ KToolBar *tb = toolBar( i );
+ if ( tb )
+ {
+ QWidget *w = tb->getButton( itemId( i ) );
+ QWhatsThis::remove( w );
+ QWhatsThis::add( w, d->whatsThis() );
+ return;
+ }
+}
+
+QString KAction::whatsThis() const
+{
+ return d->whatsThis();
+}
+
+QString KAction::whatsThisWithIcon() const
+{
+ QString text = whatsThis();
+ if (!d->iconName().isEmpty())
+ return QString::fromLatin1("<img source=\"small|%1\"> %2").arg(d->iconName() ).arg(text);
+ return text;
+}
+
+QWidget* KAction::container( int index ) const
+{
+ assert( index < containerCount() );
+ return d->m_containers[ index ].m_container;
+}
+
+KToolBar* KAction::toolBar( int index ) const
+{
+ return dynamic_cast<KToolBar *>( d->m_containers[ index ].m_container );
+}
+
+QPopupMenu* KAction::popupMenu( int index ) const
+{
+ return dynamic_cast<QPopupMenu *>( d->m_containers[ index ].m_container );
+}
+
+QWidget* KAction::representative( int index ) const
+{
+ return d->m_containers[ index ].m_representative;
+}
+
+int KAction::itemId( int index ) const
+{
+ return d->m_containers[ index ].m_id;
+}
+
+int KAction::containerCount() const
+{
+ return d->m_containers.count();
+}
+
+uint KAction::kaccelCount() const
+{
+ return d->m_kaccelList.count();
+}
+
+void KAction::addContainer( QWidget* c, int id )
+{
+ KActionPrivate::Container p;
+ p.m_container = c;
+ p.m_id = id;
+ d->m_containers.append( p );
+}
+
+void KAction::addContainer( QWidget* c, QWidget* w )
+{
+ KActionPrivate::Container p;
+ p.m_container = c;
+ p.m_representative = w;
+ d->m_containers.append( p );
+}
+
+void KAction::activate()
+{
+ emit activated( KAction::EmulatedActivation, Qt::NoButton );
+ slotActivated();
+}
+
+void KAction::slotActivated()
+{
+ const QObject *senderObj = sender();
+ if ( senderObj )
+ {
+ if ( ::qt_cast<KAccelPrivate *>( senderObj ) )
+ emit activated( KAction::AccelActivation, Qt::NoButton );
+ }
+ emit activated();
+}
+
+// This catches signals emitted by KActions inserted into QPopupMenu
+// We do crude things inside it, because we need to know which
+// QPopupMenu emitted the signal. We need to be sure that it is
+// only called by QPopupMenus, we plugged us in.
+void KAction::slotPopupActivated()
+{
+ if( ::qt_cast<QSignal *>(sender()))
+ {
+ int id = dynamic_cast<const QSignal *>(sender())->value().toInt();
+ int pos = findContainer(id);
+ if(pos != -1)
+ {
+ QPopupMenu* qpm = dynamic_cast<QPopupMenu *>( container(pos) );
+ if(qpm)
+ {
+ KPopupMenu* kpm = dynamic_cast<KPopupMenu *>( qpm );
+ Qt::ButtonState state;
+ if ( kpm ) // KPopupMenu? Nice, it stores the state.
+ state = kpm->state();
+ else { // just a QPopupMenu? We'll ask for the state now then (small race condition?)
+ kdDebug(129) << "KAction::slotPopupActivated not a KPopupMenu -> using keyboardMouseState()" << endl;
+ state = KApplication::keyboardMouseState();
+ }
+ emit activated( KAction::PopupMenuActivation, state );
+ slotActivated();
+ return;
+ }
+ }
+ }
+
+ kdWarning(129)<<"Don't connect KAction::slotPopupActivated() to anything, expect into QPopupMenus which are in containers. Use slotActivated instead."<<endl;
+ emit activated( KAction::PopupMenuActivation, Qt::NoButton );
+ slotActivated();
+}
+
+void KAction::slotButtonClicked( int, Qt::ButtonState state )
+{
+ kdDebug(129) << "slotButtonClicked() state=" << state << endl;
+ emit activated( KAction::ToolBarActivation, state );
+
+ // RightButton isn't really an activation
+ if ( ( state & LeftButton ) || ( state & MidButton ) )
+ slotActivated();
+}
+
+
+void KAction::slotDestroyed()
+{
+ kdDebug(129) << "KAction::slotDestroyed(): this = " << this << ", name = \"" << name() << "\", sender = " << sender() << endl;
+ const QObject* const o = sender();
+
+#ifndef KDE_NO_COMPAT // KDE 4: remove
+ if ( o == d->m_kaccel )
+ {
+ d->m_kaccel = 0;
+ return;
+ }
+#endif // KDE 4: remove end
+ QValueList<KAccel*> & accelList = d->m_kaccelList;
+ QValueList<KAccel*>::iterator itr = accelList.begin();
+ const QValueList<KAccel*>::iterator itrEnd = accelList.end();
+
+ for( ; itr != itrEnd; ++itr)
+ {
+ if ( o == *itr )
+ {
+ disconnect( *itr, SIGNAL(destroyed()), this, SLOT(slotDestroyed()) );
+ accelList.remove(itr);
+ return;
+ }
+ }
+
+ int i;
+ do
+ {
+ i = findContainer( static_cast<const QWidget*>( o ) );
+ if ( i != -1 )
+ removeContainer( i );
+ } while ( i != -1 );
+}
+
+int KAction::findContainer( const QWidget* widget ) const
+{
+ int pos = 0;
+
+ const QValueList<KActionPrivate::Container> & containers = d->m_containers;
+
+ QValueList<KActionPrivate::Container>::ConstIterator it = containers.constBegin();
+ const QValueList<KActionPrivate::Container>::ConstIterator itEnd = containers.constEnd();
+
+ while( it != itEnd )
+ {
+ if ( (*it).m_representative == widget || (*it).m_container == widget )
+ return pos;
+ ++it;
+ ++pos;
+ }
+
+ return -1;
+}
+
+int KAction::findContainer( const int id ) const
+{
+ int pos = 0;
+
+ const QValueList<KActionPrivate::Container> & containers = d->m_containers;
+
+ QValueList<KActionPrivate::Container>::ConstIterator it = containers.constBegin();
+ const QValueList<KActionPrivate::Container>::ConstIterator itEnd = containers.constEnd();
+
+ while( it != itEnd )
+ {
+ if ( (*it).m_id == id )
+ return pos;
+ ++it;
+ ++pos;
+ }
+
+ return -1;
+}
+
+void KAction::removeContainer( int index )
+{
+ int i = 0;
+
+ QValueList<KActionPrivate::Container> & containers = d->m_containers;
+
+ QValueList<KActionPrivate::Container>::Iterator it = containers.begin();
+ const QValueList<KActionPrivate::Container>::Iterator itEnd = containers.end();
+
+ while( it != itEnd )
+ {
+ if ( i == index )
+ {
+ containers.remove( it );
+ return;
+ }
+ ++it;
+ ++i;
+ }
+}
+
+// FIXME: Remove this (ellis)
+void KAction::slotKeycodeChanged()
+{
+ kdDebug(129) << "KAction::slotKeycodeChanged()" << endl; // -- ellis
+ KAccelAction* pAction = d->m_kaccel->actions().actionPtr(name());
+ if( pAction )
+ setShortcut(pAction->shortcut());
+}
+
+KActionCollection *KAction::parentCollection() const
+{
+ return m_parentCollection;
+}
+
+void KAction::unplugAll()
+{
+ while ( containerCount() != 0 )
+ unplug( container( 0 ) );
+}
+
+const KGuiItem& KAction::guiItem() const
+{
+ return *d;
+}
+
+void KAction::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+/* vim: et sw=2 ts=2
+ */
+
+#include "kaction.moc"
diff --git a/kdeui/kaction.h b/kdeui/kaction.h
new file mode 100644
index 000000000..1217ce1e7
--- /dev/null
+++ b/kdeui/kaction.h
@@ -0,0 +1,676 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org>
+ (C) 1999 Simon Hausmann <hausmann@kde.org>
+ (C) 2000 Nicolas Hadacek <haadcek@kde.org>
+ (C) 2000 Kurt Granroth <granroth@kde.org>
+ (C) 2000 Michael Koch <koch@kde.org>
+ (C) 2001 Holger Freyther <freyther@kde.org>
+ (C) 2002 Ellis Whitehead <ellis@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+//$Id$
+
+#ifndef __kaction_h__
+#define __kaction_h__
+
+#include <qkeysequence.h>
+#include <qobject.h>
+#include <qvaluelist.h>
+#include <qguardedptr.h>
+#include <kguiitem.h>
+#include <kshortcut.h>
+#include <kstdaction.h>
+#include <kicontheme.h>
+
+class QMenuBar;
+class QPopupMenu;
+class QComboBox;
+class QPoint;
+class QIconSet;
+class QString;
+class KToolBar;
+
+class KAccel;
+class KAccelActions;
+class KConfig;
+class KConfigBase;
+class KURL;
+class KInstance;
+class KToolBar;
+class KActionCollection;
+class KPopupMenu;
+class KMainWindow;
+
+/**
+ * @short Class to encapsulate user-driven action or event
+ *
+ * The KAction class (and derived and super classes) provides a way to
+ * easily encapsulate a "real" user-selected action or event in your
+ * program.
+ *
+ * For instance, a user may want to @p paste the contents of
+ * the clipboard or @p scroll @p down a document or @p quit the
+ * application. These are all @p actions -- events that the
+ * user causes to happen. The KAction class allows the developer to
+ * deal with these actions in an easy and intuitive manner.
+ *
+ * Specifically, the KAction class encapsulated the various attributes
+ * to an event/action. For instance, an action might have an icon
+ * that goes along with it (a clipboard for a "paste" action or
+ * scissors for a "cut" action). The action might have some text to
+ * describe the action. It will certainly have a method or function
+ * that actually @p executes the action! All these attributes
+ * are contained within the KAction object.
+ *
+ * The advantage of dealing with Actions is that you can manipulate
+ * the Action without regard to the GUI representation of it. For
+ * instance, in the "normal" way of dealing with actions like "cut",
+ * you would manually insert a item for Cut into a menu and a button
+ * into a toolbar. If you want to disable the cut action for a moment
+ * (maybe nothing is selected), you would have to hunt down the pointer
+ * to the menu item and the toolbar button and disable both
+ * individually. Setting the menu item and toolbar item up uses very
+ * similar code - but has to be done twice!
+ *
+ * With the Action concept, you simply "plug" the Action into whatever
+ * GUI element you want. The KAction class will then take care of
+ * correctly defining the menu item (with icons, accelerators, text,
+ * etc) or toolbar button.. or whatever. From then on, if you
+ * manipulate the Action at all, the effect will propogate through all
+ * GUI representations of it. Back to the "cut" example: if you want
+ * to disable the Cut Action, you would simply do
+ * 'cutAction->setEnabled(false)' and the menuitem and button would
+ * instantly be disabled!
+ *
+ * This is the biggest advantage to the Action concept -- there is a
+ * one-to-one relationship between the "real" action and @p all
+ * GUI representations of it.
+ *
+ * KAction emits the activated() signal if the user activated the
+ * corresponding GUI element ( menu item, toolbar button, etc. )
+ *
+ * If you are in the situation of wanting to map the activated()
+ * signal of multiple action objects to one slot, with a special
+ * argument bound to each action, then you might consider using
+ * QSignalMapper . A tiny example:
+ *
+ * \code
+ * QSignalMapper *desktopNumberMapper = new QSignalMapper( this );
+ * connect( desktopNumberMapper, SIGNAL( mapped( int ) ),
+ * this, SLOT( moveWindowToDesktop( int ) ) );
+ *
+ * for ( uint i = 0; i < numberOfDesktops; ++i ) {
+ * KAction *desktopAction = new KAction( i18n( "Move Window to Desktop %i" ).arg( i ), ... );
+ * connect( desktopAction, SIGNAL( activated() ), desktopNumberMapper, SLOT( map() ) );
+ * desktopNumberMapper->setMapping( desktopAction, i );
+ * }
+ * \endcode
+ *
+ * <b>General Usage:</b>\n
+ *
+ * The steps to using actions are roughly as follows
+ *
+ * @li Decide which attributes you want to associate with a given
+ * action (icons, text, keyboard shortcut, etc)
+ * @li Create the action using KAction (or derived or super class).
+ * @li "Plug" the Action into whatever GUI element you want. Typically,
+ * this will be a menu or toolbar.
+ *
+ * <b>Detailed Example:</b>\n
+ *
+ * Here is an example of enabling a "New [document]" action
+ * \code
+ * KAction *newAct = new KAction(i18n("&New"), "filenew",
+ * KStdAccel::shortcut(KStdAccel::New),
+ * this, SLOT(fileNew()),
+ * actionCollection(), "new");
+ * \endcode
+ * This line creates our action. It says that wherever this action is
+ * displayed, it will use "&New" as the text, the standard icon, and
+ * the standard shortcut. It further says that whenever this action
+ * is invoked, it will use the fileNew() slot to execute it.
+ *
+ * \code
+ * QPopupMenu *file = new QPopupMenu;
+ * newAct->plug(file);
+ * \endcode
+ * That just inserted the action into the File menu. The point is, it's not
+ * important in which menu it is: all manipulation of the item is
+ * done through the newAct object.
+ *
+ * \code
+ * newAct->plug(toolBar());
+ * \endcode
+ * And this inserted the Action into the main toolbar as a button.
+ *
+ * That's it!
+ *
+ * If you want to disable that action sometime later, you can do so
+ * with
+ * \code
+ * newAct->setEnabled(false)
+ * \endcode
+ * and both the menuitem in File and the toolbar button will instantly
+ * be disabled.
+ *
+ * Do not delete a KAction object without unplugging it from all its
+ * containers. The simplest way to do that is to use the unplugAll()
+ * as in the following example:
+ * \code
+ * newAct->unplugAll();
+ * delete newAct;
+ * \endcode
+ * Normally you will not need to do this as KActionCollection manages
+ * everything for you.
+ *
+ * Note: if you are using a "standard" action like "new", "paste",
+ * "quit", or any other action described in the KDE UI Standards,
+ * please use the methods in the KStdAction class rather than
+ * defining your own.
+ *
+ * <b>Usage Within the XML Framework:</b>\n
+ *
+ * If you are using KAction within the context of the XML menu and
+ * toolbar building framework, then there are a few tiny changes. The
+ * first is that you must insert your new action into an action
+ * collection. The action collection (a KActionCollection) is,
+ * logically enough, a central collection of all of the actions
+ * defined in your application. The XML UI framework code in KXMLGUI
+ * classes needs access to this collection in order to build up the
+ * GUI (it's how the builder code knows which actions are valid and
+ * which aren't).
+ *
+ * Also, if you use the XML builder framework, then you do not ever
+ * have to plug your actions into containers manually. The framework
+ * does that for you.
+ *
+ * @see KStdAction
+ */
+class KDEUI_EXPORT KAction : public QObject
+{
+ friend class KActionCollection;
+ Q_OBJECT
+ Q_PROPERTY( int containerCount READ containerCount )
+ Q_PROPERTY( QString plainText READ plainText )
+ Q_PROPERTY( QString text READ text WRITE setText )
+ Q_PROPERTY( QString shortcut READ shortcutText WRITE setShortcutText )
+ Q_PROPERTY( bool enabled READ isEnabled WRITE setEnabled )
+ Q_PROPERTY( QString group READ group WRITE setGroup )
+ Q_PROPERTY( QString whatsThis READ whatsThis WRITE setWhatsThis )
+ Q_PROPERTY( QString toolTip READ toolTip WRITE setToolTip )
+ Q_PROPERTY( QString icon READ icon WRITE setIcon )
+public:
+ /**
+ * Constructs an action with text, potential keyboard
+ * shortcut, and a SLOT to call when this action is invoked by
+ * the user.
+ *
+ * If you do not want or have a keyboard shortcut,
+ * set the @p cut param to 0.
+ *
+ * This is the most common KAction used when you do not have a
+ * corresponding icon (note that it won't appear in the current version
+ * of the "Edit ToolBar" dialog, because an action needs an icon to be
+ * plugged in a toolbar...).
+ *
+ * @param text The text that will be displayed.
+ * @param cut The corresponding keyboard shortcut.
+ * @param receiver The SLOT's parent.
+ * @param slot The SLOT to invoke to execute this action.
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KAction( const QString& text, const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ KActionCollection* parent, const char* name );
+
+ /**
+ * Constructs an action with text, icon, potential keyboard
+ * shortcut, and a SLOT to call when this action is invoked by
+ * the user.
+ *
+ * If you do not want or have a keyboard shortcut, set the
+ * @p cut param to 0.
+ *
+ * This is the other common KAction used. Use it when you
+ * @p do have a corresponding icon.
+ *
+ * @param text The text that will be displayed.
+ * @param pix The icon to display.
+ * @param cut The corresponding keyboard shortcut.
+ * @param receiver The SLOT's parent.
+ * @param slot The SLOT to invoke to execute this action.
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KAction( const QString& text, const QIconSet& pix, const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ KActionCollection* parent, const char* name );
+
+ /**
+ * Constructs an action with text, icon, potential keyboard
+ * shortcut, and a SLOT to call when this action is invoked by
+ * the user. The icon is loaded on demand later based on where it
+ * is plugged in.
+ *
+ * If you do not want or have a keyboard shortcut, set the
+ * @p cut param to 0.
+ *
+ * This is the other common KAction used. Use it when you
+ * @p do have a corresponding icon.
+ *
+ * @param text The text that will be displayed.
+ * @param pix The icon to display.
+ * @param cut The corresponding keyboard shortcut (shortcut).
+ * @param receiver The SLOT's parent.
+ * @param slot The SLOT to invoke to execute this action.
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KAction( const QString& text, const QString& pix, const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ KActionCollection* parent, const char* name );
+
+ /**
+ * The same as the above constructor, but with a KGuiItem providing
+ * the text and icon.
+ *
+ * @param item The KGuiItem with the label and (optional) icon.
+ * @param cut The corresponding keyboard shortcut (shortcut).
+ * @param receiver The SLOT's parent.
+ * @param slot The SLOT to invoke to execute this action.
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KAction( const KGuiItem& item, const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ KActionCollection* parent, const char* name );
+
+ /**
+ * @obsolete
+ */
+ KAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0, const char* name = 0 );
+ /**
+ * @obsolete
+ */
+ KAction( const QString& text, const KShortcut& cut,
+ const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 );
+ /**
+ * @obsolete
+ */
+ KAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(),
+ QObject* parent = 0, const char* name = 0 );
+ /**
+ * @obsolete
+ */
+ KAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(),
+ QObject* parent = 0, const char* name = 0 );
+ /**
+ * @obsolete
+ */
+ KAction( const QString& text, const QIconSet& pix, const KShortcut& cut,
+ const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 );
+ /**
+ * @obsolete
+ */
+ KAction( const QString& text, const QString& pix, const KShortcut& cut,
+ const QObject* receiver, const char* slot, QObject* parent,
+ const char* name = 0 );
+ /**
+ * @obsolete
+ */
+ KAction( QObject* parent = 0, const char* name = 0 );
+
+ /**
+ * Standard destructor
+ */
+ virtual ~KAction();
+
+ /**
+ * "Plug" or insert this action into a given widget.
+ *
+ * This will
+ * typically be a menu or a toolbar. From this point on, you will
+ * never need to directly manipulate the item in the menu or
+ * toolbar. You do all enabling/disabling/manipulation directly
+ * with your KAction object.
+ *
+ * @param widget The GUI element to display this action
+ * @param index The position into which the action is plugged. If
+ * this is negative, the action is inserted at the end.
+ */
+ virtual int plug( QWidget *widget, int index = -1 );
+
+ /**
+ * @deprecated. Shouldn't be used. No substitute available.
+ *
+ * "Plug" or insert this action into a given KAccel.
+ *
+ * @param accel The KAccel collection which holds this accel
+ * @param configurable If the shortcut is configurable via
+ * the KAccel configuration dialog (this is somehow deprecated since
+ * there is now a KAction key configuration dialog).
+ */
+ virtual void plugAccel(KAccel *accel, bool configurable = true) KDE_DEPRECATED;
+
+ /**
+ * "Unplug" or remove this action from a given widget.
+ *
+ * This will typically be a menu or a toolbar. This is rarely
+ * used in "normal" application. Typically, it would be used if
+ * your application has several views or modes, each with a
+ * completely different menu structure. If you simply want to
+ * disable an action for a given period, use setEnabled()
+ * instead.
+ *
+ * @param w Remove the action from this GUI element.
+ */
+ virtual void unplug( QWidget *w );
+
+ /**
+ * @deprecated. Complement method to plugAccel().
+ * Disconnect this action from the KAccel.
+ */
+ virtual void unplugAccel() KDE_DEPRECATED;
+
+ /**
+ * returns whether the action is plugged into any container widget or not.
+ * @since 3.1
+ */
+ virtual bool isPlugged() const;
+
+ /**
+ * returns whether the action is plugged into the given container
+ */
+ bool isPlugged( const QWidget *container ) const;
+
+ /**
+ * returns whether the action is plugged into the given container with the given, container specific, id (often
+ * menu or toolbar id ) .
+ */
+ virtual bool isPlugged( const QWidget *container, int id ) const;
+
+ /**
+ * returns whether the action is plugged into the given container with the given, container specific, representative
+ * container widget item.
+ */
+ virtual bool isPlugged( const QWidget *container, const QWidget *_representative ) const;
+
+ QWidget* container( int index ) const;
+ int itemId( int index ) const;
+ QWidget* representative( int index ) const;
+ int containerCount() const;
+ /// @since 3.1
+ uint kaccelCount() const;
+
+ virtual bool hasIcon() const;
+#ifndef KDE_NO_COMPAT
+ bool hasIconSet() const { return hasIcon(); }
+#endif
+ virtual QString plainText() const;
+
+ /**
+ * Get the text associated with this action.
+ */
+ virtual QString text() const;
+
+ /**
+ * Get the keyboard shortcut associated with this action.
+ */
+ virtual const KShortcut& shortcut() const;
+ /**
+ * Get the default shortcut for this action.
+ */
+ virtual const KShortcut& shortcutDefault() const;
+
+ // These two methods are for Q_PROPERTY
+ QString shortcutText() const;
+ void setShortcutText( const QString& );
+
+ /**
+ * Returns true if this action is enabled.
+ */
+ virtual bool isEnabled() const;
+
+ /**
+ * Returns true if this action's shortcut is configurable.
+ */
+ virtual bool isShortcutConfigurable() const;
+
+ virtual QString group() const;
+
+ /**
+ * Get the What's this text for the action.
+ */
+ virtual QString whatsThis() const;
+
+ /**
+ * Get the tooltip text for the action.
+ */
+ virtual QString toolTip() const;
+
+ /**
+ * Get the QIconSet from which the icons used to display this action will
+ * be chosen.
+ *
+ * In KDE4 set group default to KIcon::Small while removing the other
+ * iconSet() function.
+ */
+ virtual QIconSet iconSet( KIcon::Group group, int size=0 ) const;
+ /**
+ * Remove in KDE4
+ */
+ QIconSet iconSet() const { return iconSet( KIcon::Small ); }
+
+ virtual QString icon() const;
+
+ KActionCollection *parentCollection() const;
+
+ /**
+ * @internal
+ * Generate a toolbar button id. Made public for reimplementations.
+ */
+ static int getToolButtonID();
+
+
+ void unplugAll();
+
+ /**
+ * @since 3.4
+ */
+ enum ActivationReason { UnknownActivation, EmulatedActivation, AccelActivation, PopupMenuActivation, ToolBarActivation };
+
+public slots:
+ /**
+ * Sets the text associated with this action. The text is used for menu
+ * and toolbar labels etc.
+ */
+ virtual void setText(const QString &text);
+
+ /**
+ * Sets the keyboard shortcut associated with this action.
+ */
+ virtual bool setShortcut( const KShortcut& );
+
+ virtual void setGroup( const QString& );
+
+ /**
+ * Sets the What's this text for the action. This text will be displayed when
+ * a widget that has been created by plugging this action into a container
+ * is clicked on in What's this mode.
+ *
+ * The What's this text can include QML markup as well as raw text.
+ */
+ virtual void setWhatsThis( const QString& text );
+
+ /**
+ * Sets the tooltip text for the action.
+ * This will be used as a tooltip for a toolbar button, as a
+ * statusbar help-text for a menu item, and it also appears
+ * in the toolbar editor, to describe the action.
+ *
+ * For the tooltip to show up on the statusbar you will need to connect
+ * a couple of the actionclass signals to the toolbar.
+ * The easiest way of doing this is in your main window class, when you create
+ * a statusbar. See the KActionCollection class for more details.
+ *
+ * @see KActionCollection
+ *
+ */
+ virtual void setToolTip( const QString& );
+
+ /**
+ * Sets the QIconSet from which the icons used to display this action will
+ * be chosen.
+ */
+ virtual void setIconSet( const QIconSet &iconSet );
+
+ virtual void setIcon( const QString& icon );
+
+ /**
+ * Enables or disables this action. All uses of this action (eg. in menus
+ * or toolbars) will be updated to reflect the state of the action.
+ */
+ virtual void setEnabled(bool enable);
+
+ /**
+ * Calls setEnabled( !disable ).
+ * @since 3.5
+ */
+ void setDisabled(bool disable) { return setEnabled(!disable); }
+
+ /**
+ * Indicate whether the user may configure the action's shortcut.
+ */
+ virtual void setShortcutConfigurable( bool );
+
+ /**
+ * Emulate user's interaction programmatically, by activating the action.
+ * The implementation simply emits activated().
+ */
+ virtual void activate();
+
+protected slots:
+ virtual void slotDestroyed();
+ virtual void slotKeycodeChanged();
+ virtual void slotActivated();
+ /// @since 3.4
+ void slotPopupActivated(); // KDE4: make virtual
+ /// @since 3.4
+ void slotButtonClicked( int, Qt::ButtonState state ); // KDE4: make virtual
+
+protected:
+ KToolBar* toolBar( int index ) const;
+ QPopupMenu* popupMenu( int index ) const;
+ void removeContainer( int index );
+ int findContainer( const QWidget* widget ) const;
+ int findContainer( int id ) const;
+ void plugMainWindowAccel( QWidget *w );
+
+ void addContainer( QWidget* parent, int id );
+ void addContainer( QWidget* parent, QWidget* representative );
+
+ virtual void updateShortcut( int i );
+ virtual void updateShortcut( QPopupMenu* menu, int id );
+ virtual void updateGroup( int id );
+ virtual void updateText(int i );
+ virtual void updateEnabled(int i);
+ virtual void updateIconSet(int i);
+ virtual void updateIcon( int i);
+ virtual void updateToolTip( int id );
+ virtual void updateWhatsThis( int i );
+
+ KActionCollection *m_parentCollection;
+ QString whatsThisWithIcon() const;
+ /**
+ * Return the underlying KGuiItem
+ * @since 3.3
+ */
+ const KGuiItem& guiItem() const;
+
+signals:
+ /**
+ * Emitted when this action is activated
+ */
+ void activated();
+ /**
+ * This signal allows to know the reason why an action was activated:
+ * whether it was due to a toolbar button, popupmenu, keyboard accel, or programmatically.
+ * In the first two cases, it also allows to know which mouse button was
+ * used (Left or Middle), and whether keyboard modifiers were pressed (e.g. CTRL).
+ *
+ * Note that this signal is emitted before the normal activated() signal.
+ * Yes, BOTH signals are always emitted, so that connecting to activated() still works.
+ * Applications which care about reason and state can either ignore the activated()
+ * signal for a given action and react to this one instead, or store the
+ * reason and state until the activated() signal is emitted.
+ *
+ * @since 3.4
+ */
+ void activated( KAction::ActivationReason reason, Qt::ButtonState state );
+ void enabled( bool );
+
+private:
+ void initPrivate( const QString& text, const KShortcut& cut,
+ const QObject* receiver, const char* slot );
+ KAccel* kaccelCurrent();
+ bool initShortcut( const KShortcut& );
+ void plugShortcut();
+ bool updateKAccelShortcut( KAccel* kaccel );
+ void insertKAccel( KAccel* );
+ /** @internal To be used exclusively by KActionCollection::removeWidget(). */
+ void removeKAccel( KAccel* );
+
+#ifndef KDE_NO_COMPAT
+public:
+ /**
+ * @deprecated. Use shortcut().
+ * Get the keyboard accelerator associated with this action.
+ */
+ int accel() const KDE_DEPRECATED;
+
+ QString statusText() const
+ { return toolTip(); }
+
+ /**
+ * @deprecated. Use setShortcut().
+ * Sets the keyboard accelerator associated with this action.
+ */
+ void setAccel( int key ) KDE_DEPRECATED;
+
+ /**
+ * @deprecated. Use setToolTip instead (they do the same thing now).
+ */
+ void setStatusText( const QString &text )
+ { setToolTip( text ); }
+
+ /**
+ * @deprecated. for backwards compatibility. Use itemId()
+ */
+ int menuId( int i ) { return itemId( i ); }
+#endif // !KDE_NO_COMPAT
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KActionPrivate;
+ KActionPrivate* const d;
+};
+
+#include <kactioncollection.h>
+#include <kactionclasses.h>
+
+#endif
diff --git a/kdeui/kactionclasses.cpp b/kdeui/kactionclasses.cpp
new file mode 100644
index 000000000..08ec02201
--- /dev/null
+++ b/kdeui/kactionclasses.cpp
@@ -0,0 +1,2401 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org>
+ (C) 1999 Simon Hausmann <hausmann@kde.org>
+ (C) 2000 Nicolas Hadacek <haadcek@kde.org>
+ (C) 2000 Kurt Granroth <granroth@kde.org>
+ (C) 2000 Michael Koch <koch@kde.org>
+ (C) 2001 Holger Freyther <freyther@kde.org>
+ (C) 2002 Ellis Whitehead <ellis@kde.org>
+ (C) 2002 Joseph Wenninger <jowenn@kde.org>
+ (C) 2003 Andras Mantia <amantia@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kactionclasses.h"
+
+#include <assert.h>
+
+#include <qcursor.h>
+#include <qclipboard.h>
+#include <qfontdatabase.h>
+#include <qobjectlist.h>
+#include <qwhatsthis.h>
+#include <qtimer.h>
+#include <qfile.h>
+
+#include <dcopclient.h>
+#include <dcopref.h>
+#include <kaccel.h>
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kfontcombo.h>
+#include <kfontdialog.h>
+#include <klocale.h>
+#include <kmainwindow.h>
+#include <kmenubar.h>
+#include <kpopupmenu.h>
+#include <ktoolbar.h>
+#include <ktoolbarbutton.h>
+#include <kurl.h>
+#include <kstandarddirs.h>
+#include <kstringhandler.h>
+
+class KToggleAction::KToggleActionPrivate
+{
+public:
+ KToggleActionPrivate()
+ {
+ m_checked = false;
+ m_checkedGuiItem = 0;
+ }
+
+ bool m_checked;
+ QString m_exclusiveGroup;
+ KGuiItem* m_checkedGuiItem;
+};
+
+KToggleAction::KToggleAction( const QString& text, const KShortcut& cut,
+ QObject* parent,
+ const char* name )
+ : KAction( text, cut, parent, name )
+{
+ d = new KToggleActionPrivate;
+}
+
+KToggleAction::KToggleAction( const QString& text, const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ QObject* parent, const char* name )
+ : KAction( text, cut, receiver, slot, parent, name )
+{
+ d = new KToggleActionPrivate;
+}
+
+KToggleAction::KToggleAction( const QString& text, const QIconSet& pix,
+ const KShortcut& cut,
+ QObject* parent, const char* name )
+ : KAction( text, pix, cut, parent, name )
+{
+ d = new KToggleActionPrivate;
+}
+
+KToggleAction::KToggleAction( const QString& text, const QString& pix,
+ const KShortcut& cut,
+ QObject* parent, const char* name )
+ : KAction( text, pix, cut, parent, name )
+{
+ d = new KToggleActionPrivate;
+}
+
+KToggleAction::KToggleAction( const QString& text, const QIconSet& pix,
+ const KShortcut& cut,
+ const QObject* receiver,
+ const char* slot, QObject* parent,
+ const char* name )
+ : KAction( text, pix, cut, receiver, slot, parent, name )
+{
+ d = new KToggleActionPrivate;
+}
+
+KToggleAction::KToggleAction( const QString& text, const QString& pix,
+ const KShortcut& cut,
+ const QObject* receiver,
+ const char* slot, QObject* parent,
+ const char* name )
+ : KAction( text, pix, cut, receiver, slot, parent, name )
+{
+ d = new KToggleActionPrivate;
+}
+
+KToggleAction::KToggleAction( QObject* parent, const char* name )
+ : KAction( parent, name )
+{
+ d = new KToggleActionPrivate;
+}
+
+KToggleAction::~KToggleAction()
+{
+ delete d->m_checkedGuiItem;
+ delete d;
+}
+
+int KToggleAction::plug( QWidget* widget, int index )
+{
+ if ( !::qt_cast<QPopupMenu *>( widget ) && !::qt_cast<KToolBar *>( widget ) )
+ {
+ kdWarning() << "Can not plug KToggleAction in " << widget->className() << endl;
+ return -1;
+ }
+ if (kapp && !kapp->authorizeKAction(name()))
+ return -1;
+
+ int _index = KAction::plug( widget, index );
+ if ( _index == -1 )
+ return _index;
+
+ if ( ::qt_cast<KToolBar *>( widget ) ) {
+ KToolBar *bar = static_cast<KToolBar *>( widget );
+
+ bar->setToggle( itemId( _index ), true );
+ bar->setButton( itemId( _index ), isChecked() );
+ }
+
+ if ( d->m_checked )
+ updateChecked( _index );
+
+ return _index;
+}
+
+void KToggleAction::setChecked( bool c )
+{
+ if ( c == d->m_checked )
+ return;
+ //kdDebug(129) << "KToggleAction::setChecked(" << c << ") " << this << " " << name() << endl;
+
+ d->m_checked = c;
+
+ int len = containerCount();
+
+ for( int i = 0; i < len; ++i )
+ updateChecked( i );
+
+ if ( c && parent() && !exclusiveGroup().isEmpty() ) {
+ const QObjectList *list = parent()->children();
+ if ( list ) {
+ QObjectListIt it( *list );
+ for( ; it.current(); ++it ) {
+ if ( ::qt_cast<KToggleAction *>( it.current() ) && it.current() != this &&
+ static_cast<KToggleAction*>(it.current())->exclusiveGroup() == exclusiveGroup() ) {
+ KToggleAction *a = static_cast<KToggleAction*>(it.current());
+ if( a->isChecked() ) {
+ a->setChecked( false );
+ emit a->toggled( false );
+ }
+ }
+ }
+ }
+ }
+}
+
+void KToggleAction::updateChecked( int id )
+{
+ QWidget *w = container( id );
+
+ if ( ::qt_cast<QPopupMenu *>( w ) ) {
+ QPopupMenu* pm = static_cast<QPopupMenu*>(w);
+ int itemId_ = itemId( id );
+ if ( !d->m_checkedGuiItem )
+ pm->setItemChecked( itemId_, d->m_checked );
+ else {
+ const KGuiItem* gui = d->m_checked ? d->m_checkedGuiItem : &guiItem();
+ if ( d->m_checkedGuiItem->hasIcon() )
+ pm->changeItem( itemId_, gui->iconSet( KIcon::Small ), gui->text() );
+ else
+ pm->changeItem( itemId_, gui->text() );
+
+ // If the text doesn't change, then set the icon to be "pressed", otherwise
+ // there is too little difference between checked and unchecked.
+ if ( d->m_checkedGuiItem->text() == guiItem().text() )
+ pm->setItemChecked( itemId_, d->m_checked );
+
+ if ( !d->m_checkedGuiItem->whatsThis().isEmpty() ) // if empty, we keep the initial one
+ pm->setWhatsThis( itemId_, gui->whatsThis() );
+ updateShortcut( pm, itemId_ );
+ }
+ }
+ else if ( ::qt_cast<QMenuBar *>( w ) ) // not handled in plug...
+ static_cast<QMenuBar*>(w)->setItemChecked( itemId( id ), d->m_checked );
+ else if ( ::qt_cast<KToolBar *>( w ) )
+ {
+ QWidget* r = static_cast<KToolBar*>( w )->getButton( itemId( id ) );
+ if ( r && ::qt_cast<KToolBarButton *>( r ) ) {
+ static_cast<KToolBar*>( w )->setButton( itemId( id ), d->m_checked );
+ if ( d->m_checkedGuiItem && d->m_checkedGuiItem->hasIcon() ) {
+ const KGuiItem* gui = d->m_checked ? d->m_checkedGuiItem : &guiItem();
+ static_cast<KToolBar*>( w )->setButtonIconSet( itemId( id ), gui->iconSet( KIcon::Toolbar ) );
+ }
+ }
+ }
+}
+
+void KToggleAction::slotActivated()
+{
+ setChecked( !isChecked() );
+ KAction::slotActivated();
+ emit toggled( isChecked() );
+}
+
+bool KToggleAction::isChecked() const
+{
+ return d->m_checked;
+}
+
+void KToggleAction::setExclusiveGroup( const QString& name )
+{
+ d->m_exclusiveGroup = name;
+}
+
+QString KToggleAction::exclusiveGroup() const
+{
+ return d->m_exclusiveGroup;
+}
+
+void KToggleAction::setCheckedState( const KGuiItem& checkedItem )
+{
+ delete d->m_checkedGuiItem;
+ d->m_checkedGuiItem = new KGuiItem( checkedItem );
+}
+
+QString KToggleAction::toolTip() const
+{
+ if ( d->m_checkedGuiItem && d->m_checked )
+ return d->m_checkedGuiItem->toolTip();
+ else
+ return KAction::toolTip();
+}
+
+KRadioAction::KRadioAction( const QString& text, const KShortcut& cut,
+ QObject* parent, const char* name )
+: KToggleAction( text, cut, parent, name )
+{
+}
+
+KRadioAction::KRadioAction( const QString& text, const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ QObject* parent, const char* name )
+: KToggleAction( text, cut, receiver, slot, parent, name )
+{
+}
+
+KRadioAction::KRadioAction( const QString& text, const QIconSet& pix,
+ const KShortcut& cut,
+ QObject* parent, const char* name )
+: KToggleAction( text, pix, cut, parent, name )
+{
+}
+
+KRadioAction::KRadioAction( const QString& text, const QString& pix,
+ const KShortcut& cut,
+ QObject* parent, const char* name )
+: KToggleAction( text, pix, cut, parent, name )
+{
+}
+
+KRadioAction::KRadioAction( const QString& text, const QIconSet& pix,
+ const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ QObject* parent, const char* name )
+: KToggleAction( text, pix, cut, receiver, slot, parent, name )
+{
+}
+
+KRadioAction::KRadioAction( const QString& text, const QString& pix,
+ const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ QObject* parent, const char* name )
+: KToggleAction( text, pix, cut, receiver, slot, parent, name )
+{
+}
+
+KRadioAction::KRadioAction( QObject* parent, const char* name )
+: KToggleAction( parent, name )
+{
+}
+
+void KRadioAction::slotActivated()
+{
+ if ( isChecked() )
+ {
+ const QObject *senderObj = sender();
+
+ if ( !senderObj || !::qt_cast<const KToolBarButton *>( senderObj ) )
+ return;
+
+ const_cast<KToolBarButton *>( static_cast<const KToolBarButton *>( senderObj ) )->on( true );
+
+ return;
+ }
+
+ KToggleAction::slotActivated();
+}
+
+class KSelectAction::KSelectActionPrivate
+{
+public:
+ KSelectActionPrivate()
+ {
+ m_edit = false;
+ m_menuAccelsEnabled = true;
+ m_menu = 0;
+ m_current = -1;
+ m_comboWidth = -1;
+ m_maxComboViewCount = -1;
+ }
+ bool m_edit;
+ bool m_menuAccelsEnabled;
+ QPopupMenu *m_menu;
+ int m_current;
+ int m_comboWidth;
+ QStringList m_list;
+ int m_maxComboViewCount;
+
+ QString makeMenuText( const QString &_text )
+ {
+ if ( m_menuAccelsEnabled )
+ return _text;
+ QString text = _text;
+ uint i = 0;
+ while ( i < text.length() ) {
+ if ( text[ i ] == '&' ) {
+ text.insert( i, '&' );
+ i += 2;
+ }
+ else
+ ++i;
+ }
+ return text;
+ }
+};
+
+KSelectAction::KSelectAction( const QString& text, const KShortcut& cut,
+ QObject* parent, const char* name )
+ : KAction( text, cut, parent, name )
+{
+ d = new KSelectActionPrivate;
+}
+
+KSelectAction::KSelectAction( const QString& text, const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ QObject* parent, const char* name )
+ : KAction( text, cut, receiver, slot, parent, name )
+{
+ d = new KSelectActionPrivate;
+}
+
+KSelectAction::KSelectAction( const QString& text, const QIconSet& pix,
+ const KShortcut& cut,
+ QObject* parent, const char* name )
+ : KAction( text, pix, cut, parent, name )
+{
+ d = new KSelectActionPrivate;
+}
+
+KSelectAction::KSelectAction( const QString& text, const QString& pix,
+ const KShortcut& cut,
+ QObject* parent, const char* name )
+ : KAction( text, pix, cut, parent, name )
+{
+ d = new KSelectActionPrivate;
+}
+
+KSelectAction::KSelectAction( const QString& text, const QIconSet& pix,
+ const KShortcut& cut,
+ const QObject* receiver,
+ const char* slot, QObject* parent,
+ const char* name )
+ : KAction( text, pix, cut, receiver, slot, parent, name )
+{
+ d = new KSelectActionPrivate;
+}
+
+KSelectAction::KSelectAction( const QString& text, const QString& pix,
+ const KShortcut& cut,
+ const QObject* receiver,
+ const char* slot, QObject* parent,
+ const char* name )
+ : KAction( text, pix, cut, receiver, slot, parent, name )
+{
+ d = new KSelectActionPrivate;
+}
+
+KSelectAction::KSelectAction( QObject* parent, const char* name )
+ : KAction( parent, name )
+{
+ d = new KSelectActionPrivate;
+}
+
+KSelectAction::~KSelectAction()
+{
+ assert(d);
+ delete d->m_menu;
+ delete d; d = 0;
+}
+
+void KSelectAction::setCurrentItem( int id )
+{
+ if ( id >= (int)d->m_list.count() ) {
+ Q_ASSERT(id < (int)d->m_list.count());
+ return;
+ }
+
+ if ( d->m_menu )
+ {
+ if ( d->m_current >= 0 )
+ d->m_menu->setItemChecked( d->m_current, false );
+ if ( id >= 0 )
+ d->m_menu->setItemChecked( id, true );
+ }
+
+ d->m_current = id;
+
+ int len = containerCount();
+
+ for( int i = 0; i < len; ++i )
+ updateCurrentItem( i );
+
+ // emit KAction::activated();
+ // emit activated( currentItem() );
+ // emit activated( currentText() );
+}
+
+void KSelectAction::setComboWidth( int width )
+{
+ if ( width < 0 )
+ return;
+
+ d->m_comboWidth=width;
+
+ int len = containerCount();
+
+ for( int i = 0; i < len; ++i )
+ updateComboWidth( i );
+
+}
+
+void KSelectAction::setMaxComboViewCount( int n )
+{
+ d->m_maxComboViewCount = n;
+}
+
+QPopupMenu* KSelectAction::popupMenu() const
+{
+ kdDebug(129) << "KAction::popupMenu()" << endl; // remove -- ellis
+ if ( !d->m_menu )
+ {
+ d->m_menu = new KPopupMenu(0L, "KSelectAction::popupMenu()");
+ setupMenu();
+ if ( d->m_current >= 0 )
+ d->m_menu->setItemChecked( d->m_current, true );
+ }
+
+ return d->m_menu;
+}
+
+void KSelectAction::setupMenu() const
+{
+ if ( !d->m_menu )
+ return;
+ d->m_menu->clear();
+
+ QStringList::ConstIterator it = d->m_list.begin();
+ for( uint id = 0; it != d->m_list.end(); ++it, ++id ) {
+ QString text = *it;
+ if ( !text.isEmpty() )
+ d->m_menu->insertItem( d->makeMenuText( text ), this, SLOT( slotActivated( int ) ), 0, id );
+ else
+ d->m_menu->insertSeparator();
+ }
+}
+
+void KSelectAction::changeItem( int index, const QString& text )
+{
+ if ( index < 0 || index >= (int)d->m_list.count() )
+ {
+ kdWarning() << "KSelectAction::changeItem Index out of scope" << endl;
+ return;
+ }
+
+ d->m_list[ index ] = text;
+
+ if ( d->m_menu )
+ d->m_menu->changeItem( index, d->makeMenuText( text ) );
+
+ int len = containerCount();
+ for( int i = 0; i < len; ++i )
+ changeItem( i, index, text );
+}
+
+void KSelectAction::changeItem( int id, int index, const QString& text)
+{
+ if ( index < 0 )
+ return;
+
+ QWidget* w = container( id );
+ if ( ::qt_cast<KToolBar *>( w ) )
+ {
+ QWidget* r = (static_cast<KToolBar*>( w ))->getWidget( itemId( id ) );
+ if ( ::qt_cast<QComboBox *>( r ) )
+ {
+ QComboBox *b = static_cast<QComboBox*>( r );
+ b->changeItem(text, index );
+ }
+ }
+}
+
+void KSelectAction::setItems( const QStringList &lst )
+{
+ d->m_list = lst;
+ d->m_current = -1;
+
+ setupMenu();
+
+ int len = containerCount();
+ for( int i = 0; i < len; ++i )
+ updateItems( i );
+
+ // Disable if empty and not editable
+ setEnabled ( lst.count() > 0 || d->m_edit );
+}
+
+QStringList KSelectAction::items() const
+{
+ return d->m_list;
+}
+
+QString KSelectAction::currentText() const
+{
+ if ( currentItem() < 0 )
+ return QString::null;
+
+ return d->m_list[ currentItem() ];
+}
+
+int KSelectAction::currentItem() const
+{
+ return d->m_current;
+}
+
+void KSelectAction::updateCurrentItem( int id )
+{
+ if ( d->m_current < 0 )
+ return;
+
+ QWidget* w = container( id );
+ if ( ::qt_cast<KToolBar *>( w ) ) {
+ QWidget* r = static_cast<KToolBar*>( w )->getWidget( itemId( id ) );
+ if ( ::qt_cast<QComboBox *>( r ) ) {
+ QComboBox *b = static_cast<QComboBox*>( r );
+ b->setCurrentItem( d->m_current );
+ }
+ }
+}
+
+int KSelectAction::comboWidth() const
+{
+ return d->m_comboWidth;
+}
+
+void KSelectAction::updateComboWidth( int id )
+{
+ QWidget* w = container( id );
+ if ( ::qt_cast<KToolBar *>( w ) ) {
+ QWidget* r = static_cast<KToolBar*>( w )->getWidget( itemId( id ) );
+ if ( ::qt_cast<QComboBox *>( r ) ) {
+ QComboBox *cb = static_cast<QComboBox*>( r );
+ cb->setMinimumWidth( d->m_comboWidth );
+ cb->setMaximumWidth( d->m_comboWidth );
+ }
+ }
+}
+
+void KSelectAction::updateItems( int id )
+{
+ kdDebug(129) << "KAction::updateItems( " << id << ", lst )" << endl; // remove -- ellis
+ QWidget* w = container( id );
+ if ( ::qt_cast<KToolBar *>( w ) ) {
+ QWidget* r = static_cast<KToolBar*>( w )->getWidget( itemId( id ) );
+ if ( ::qt_cast<QComboBox *>( r ) ) {
+ QComboBox *cb = static_cast<QComboBox*>( r );
+ cb->clear();
+ QStringList lst = comboItems();
+ QStringList::ConstIterator it = lst.begin();
+ for( ; it != lst.end(); ++it )
+ cb->insertItem( *it );
+ // qt caches and never recalculates the sizeHint()
+ // qcombobox.cpp recommends calling setFont to invalidate the sizeHint
+ // setFont sets own_font = True, so we're a bit mean and calll
+ // unsetFont which calls setFont and then overwrites the own_font
+ cb->unsetFont();
+ }
+ }
+}
+
+int KSelectAction::plug( QWidget *widget, int index )
+{
+ if (kapp && !kapp->authorizeKAction(name()))
+ return -1;
+ kdDebug(129) << "KSelectAction::plug( " << widget << ", " << index << " )" << endl; // remove -- ellis
+ if ( ::qt_cast<QPopupMenu *>( widget) )
+ {
+ // Create the PopupMenu and store it in m_menu
+ (void)popupMenu();
+
+ QPopupMenu* menu = static_cast<QPopupMenu*>( widget );
+ int id;
+ if ( hasIcon() )
+ id = menu->insertItem( iconSet(), text(), d->m_menu, -1, index );
+ else
+ id = menu->insertItem( text(), d->m_menu, -1, index );
+
+ if ( !isEnabled() )
+ menu->setItemEnabled( id, false );
+
+ QString wth = whatsThis();
+ if ( !wth.isEmpty() )
+ menu->setWhatsThis( id, wth );
+
+ addContainer( menu, id );
+ connect( menu, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) );
+
+ return containerCount() - 1;
+ }
+ else if ( ::qt_cast<KToolBar *>( widget ) )
+ {
+ KToolBar* bar = static_cast<KToolBar*>( widget );
+ int id_ = KAction::getToolButtonID();
+ bar->insertCombo( comboItems(), id_, isEditable(),
+ SIGNAL( activated( const QString & ) ), this,
+ SLOT( slotActivated( const QString & ) ), isEnabled(),
+ toolTip(), -1, index );
+
+ QComboBox *cb = bar->getCombo( id_ );
+ if ( cb )
+ {
+ if (!isEditable()) cb->setFocusPolicy(QWidget::NoFocus);
+ cb->setMinimumWidth( cb->sizeHint().width() );
+ if ( d->m_comboWidth > 0 )
+ {
+ cb->setMinimumWidth( d->m_comboWidth );
+ cb->setMaximumWidth( d->m_comboWidth );
+ }
+ cb->setInsertionPolicy( QComboBox::NoInsertion );
+ QWhatsThis::add( cb, whatsThis() );
+ if ( d->m_maxComboViewCount != -1 ) cb->setSizeLimit( d->m_maxComboViewCount );
+ }
+
+ addContainer( bar, id_ );
+
+ connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) );
+
+ updateCurrentItem( containerCount() - 1 );
+
+ return containerCount() - 1;
+ }
+ else if ( ::qt_cast<QMenuBar *>( widget ) )
+ {
+ // Create the PopupMenu and store it in m_menu
+ (void)popupMenu();
+
+ QMenuBar* menu = static_cast<QMenuBar*>( widget );
+ int id = menu->insertItem( text(), d->m_menu, -1, index );
+
+ if ( !isEnabled() )
+ menu->setItemEnabled( id, false );
+
+ QString wth = whatsThis();
+ if ( !wth.isEmpty() )
+ menu->setWhatsThis( id, wth );
+
+ addContainer( menu, id );
+ connect( menu, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) );
+
+ return containerCount() - 1;
+ }
+
+ kdWarning() << "Can not plug KAction in " << widget->className() << endl;
+ return -1;
+}
+
+QStringList KSelectAction::comboItems() const
+{
+ if( d->m_menuAccelsEnabled ) {
+ QStringList lst;
+ QStringList::ConstIterator it = d->m_list.begin();
+ for( ; it != d->m_list.end(); ++it )
+ {
+ QString item = *it;
+ int i = item.find( '&' );
+ if ( i > -1 )
+ item = item.remove( i, 1 );
+ lst.append( item );
+ }
+ return lst;
+ }
+ else
+ return d->m_list;
+}
+
+void KSelectAction::clear()
+{
+ if ( d->m_menu )
+ d->m_menu->clear();
+
+ int len = containerCount();
+ for( int i = 0; i < len; ++i )
+ updateClear( i );
+}
+
+void KSelectAction::updateClear( int id )
+{
+ QWidget* w = container( id );
+ if ( ::qt_cast<KToolBar *>( w ) ) {
+ QWidget* r = static_cast<KToolBar*>( w )->getWidget( itemId( id ) );
+ if ( ::qt_cast<QComboBox *>( r ) ) {
+ QComboBox *b = static_cast<QComboBox*>( r );
+ b->clear();
+ }
+ }
+}
+
+void KSelectAction::slotActivated( int id )
+{
+ if ( d->m_current == id )
+ return;
+
+ setCurrentItem( id );
+ // Delay this. Especially useful when the slot connected to activated() will re-create
+ // the menu, e.g. in the recent files action. This prevents a crash.
+ QTimer::singleShot( 0, this, SLOT( slotActivated() ) );
+}
+
+void KSelectAction::slotActivated( const QString &text )
+{
+ if ( isEditable() )
+ {
+ QStringList lst = d->m_list;
+ if(!lst.contains(text))
+ {
+ lst.append( text );
+ setItems( lst );
+ }
+ }
+
+ int i = d->m_list.findIndex( text );
+ if ( i > -1 )
+ setCurrentItem( i );
+ else
+ setCurrentItem( comboItems().findIndex( text ) );
+ // Delay this. Especially useful when the slot connected to activated() will re-create
+ // the menu, e.g. in the recent files action. This prevents a crash.
+ QTimer::singleShot( 0, this, SLOT( slotActivated() ) );
+}
+
+void KSelectAction::slotActivated()
+{
+ KAction::slotActivated();
+ kdDebug(129) << "KSelectAction::slotActivated currentItem=" << currentItem() << " currentText=" << currentText() << endl;
+ emit activated( currentItem() );
+ emit activated( currentText() );
+}
+
+void KSelectAction::setEditable( bool edit )
+{
+ d->m_edit = edit;
+}
+
+bool KSelectAction::isEditable() const
+{
+ return d->m_edit;
+}
+
+void KSelectAction::setRemoveAmpersandsInCombo( bool b )
+{
+ setMenuAccelsEnabled( b );
+}
+
+bool KSelectAction::removeAmpersandsInCombo() const
+{
+ return menuAccelsEnabled( );
+}
+
+void KSelectAction::setMenuAccelsEnabled( bool b )
+{
+ d->m_menuAccelsEnabled = b;
+}
+
+bool KSelectAction::menuAccelsEnabled() const
+{
+ return d->m_menuAccelsEnabled;
+}
+
+class KListAction::KListActionPrivate
+{
+public:
+ KListActionPrivate()
+ {
+ m_current = 0;
+ }
+ int m_current;
+};
+
+KListAction::KListAction( const QString& text, const KShortcut& cut,
+ QObject* parent, const char* name )
+ : KSelectAction( text, cut, parent, name )
+{
+ d = new KListActionPrivate;
+}
+
+KListAction::KListAction( const QString& text, const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ QObject* parent, const char* name )
+ : KSelectAction( text, cut, parent, name )
+{
+ d = new KListActionPrivate;
+ if ( receiver )
+ connect( this, SIGNAL( activated( int ) ), receiver, slot );
+}
+
+KListAction::KListAction( const QString& text, const QIconSet& pix,
+ const KShortcut& cut,
+ QObject* parent, const char* name )
+ : KSelectAction( text, pix, cut, parent, name )
+{
+ d = new KListActionPrivate;
+}
+
+KListAction::KListAction( const QString& text, const QString& pix,
+ const KShortcut& cut,
+ QObject* parent, const char* name )
+ : KSelectAction( text, pix, cut, parent, name )
+{
+ d = new KListActionPrivate;
+}
+
+KListAction::KListAction( const QString& text, const QIconSet& pix,
+ const KShortcut& cut, const QObject* receiver,
+ const char* slot, QObject* parent,
+ const char* name )
+ : KSelectAction( text, pix, cut, parent, name )
+{
+ d = new KListActionPrivate;
+ if ( receiver )
+ connect( this, SIGNAL( activated( int ) ), receiver, slot );
+}
+
+KListAction::KListAction( const QString& text, const QString& pix,
+ const KShortcut& cut, const QObject* receiver,
+ const char* slot, QObject* parent,
+ const char* name )
+ : KSelectAction( text, pix, cut, parent, name )
+{
+ d = new KListActionPrivate;
+ if ( receiver )
+ connect( this, SIGNAL( activated( int ) ), receiver, slot );
+}
+
+KListAction::KListAction( QObject* parent, const char* name )
+ : KSelectAction( parent, name )
+{
+ d = new KListActionPrivate;
+}
+
+KListAction::~KListAction()
+{
+ delete d; d = 0;
+}
+
+void KListAction::setCurrentItem( int index )
+{
+ KSelectAction::setCurrentItem( index );
+ d->m_current = index;
+
+ // emit KAction::activated();
+ // emit activated( currentItem() );
+ // emit activated( currentText() );
+}
+
+QString KListAction::currentText() const
+{
+ return KSelectAction::currentText();
+}
+
+int KListAction::currentItem() const
+{
+ return d->m_current;
+}
+
+class KRecentFilesAction::KRecentFilesActionPrivate
+{
+public:
+ KRecentFilesActionPrivate()
+ {
+ m_maxItems = 0;
+ m_popup = 0;
+ }
+ uint m_maxItems;
+ KPopupMenu *m_popup;
+ QMap<QString, QString> m_shortNames;
+ QMap<QString, KURL> m_urls;
+};
+
+KRecentFilesAction::KRecentFilesAction( const QString& text,
+ const KShortcut& cut,
+ QObject* parent, const char* name,
+ uint maxItems )
+ : KListAction( text, cut, parent, name)
+{
+ d = new KRecentFilesActionPrivate;
+ d->m_maxItems = maxItems;
+
+ init();
+}
+
+KRecentFilesAction::KRecentFilesAction( const QString& text,
+ const KShortcut& cut,
+ const QObject* receiver,
+ const char* slot,
+ QObject* parent, const char* name,
+ uint maxItems )
+ : KListAction( text, cut, parent, name)
+{
+ d = new KRecentFilesActionPrivate;
+ d->m_maxItems = maxItems;
+
+ init();
+
+ if ( receiver )
+ connect( this, SIGNAL(urlSelected(const KURL&)),
+ receiver, slot );
+}
+
+KRecentFilesAction::KRecentFilesAction( const QString& text,
+ const QIconSet& pix,
+ const KShortcut& cut,
+ QObject* parent, const char* name,
+ uint maxItems )
+ : KListAction( text, pix, cut, parent, name)
+{
+ d = new KRecentFilesActionPrivate;
+ d->m_maxItems = maxItems;
+
+ init();
+}
+
+KRecentFilesAction::KRecentFilesAction( const QString& text,
+ const QString& pix,
+ const KShortcut& cut,
+ QObject* parent, const char* name,
+ uint maxItems )
+ : KListAction( text, pix, cut, parent, name)
+{
+ d = new KRecentFilesActionPrivate;
+ d->m_maxItems = maxItems;
+
+ init();
+}
+
+KRecentFilesAction::KRecentFilesAction( const QString& text,
+ const QIconSet& pix,
+ const KShortcut& cut,
+ const QObject* receiver,
+ const char* slot,
+ QObject* parent, const char* name,
+ uint maxItems )
+ : KListAction( text, pix, cut, parent, name)
+{
+ d = new KRecentFilesActionPrivate;
+ d->m_maxItems = maxItems;
+
+ init();
+
+ if ( receiver )
+ connect( this, SIGNAL(urlSelected(const KURL&)),
+ receiver, slot );
+}
+
+KRecentFilesAction::KRecentFilesAction( const QString& text,
+ const QString& pix,
+ const KShortcut& cut,
+ const QObject* receiver,
+ const char* slot,
+ QObject* parent, const char* name,
+ uint maxItems )
+ : KListAction( text, pix, cut, parent, name)
+{
+ d = new KRecentFilesActionPrivate;
+ d->m_maxItems = maxItems;
+
+ init();
+
+ if ( receiver )
+ connect( this, SIGNAL(urlSelected(const KURL&)),
+ receiver, slot );
+}
+
+KRecentFilesAction::KRecentFilesAction( QObject* parent, const char* name,
+ uint maxItems )
+ : KListAction( parent, name )
+{
+ d = new KRecentFilesActionPrivate;
+ d->m_maxItems = maxItems;
+
+ init();
+}
+
+void KRecentFilesAction::init()
+{
+ KRecentFilesAction *that = const_cast<KRecentFilesAction*>(this);
+ that->d->m_popup = new KPopupMenu;
+ connect(d->m_popup, SIGNAL(aboutToShow()), this, SLOT(menuAboutToShow()));
+ connect(d->m_popup, SIGNAL(activated(int)), this, SLOT(menuItemActivated(int)));
+ connect( this, SIGNAL( activated( const QString& ) ),
+ this, SLOT( itemSelected( const QString& ) ) );
+
+ setMenuAccelsEnabled( false );
+}
+
+KRecentFilesAction::~KRecentFilesAction()
+{
+ delete d->m_popup;
+ delete d; d = 0;
+}
+
+uint KRecentFilesAction::maxItems() const
+{
+ return d->m_maxItems;
+}
+
+void KRecentFilesAction::setMaxItems( uint maxItems )
+{
+ QStringList lst = KSelectAction::items();
+ uint oldCount = lst.count();
+
+ // set new maxItems
+ d->m_maxItems = maxItems;
+
+ // remove all items that are too much
+ while( lst.count() > maxItems )
+ {
+ // remove last item
+ QString lastItem = lst.last();
+ d->m_shortNames.erase( lastItem );
+ d->m_urls.erase( lastItem );
+ lst.remove( lastItem );
+ }
+
+ // set new list if changed
+ if( lst.count() != oldCount )
+ setItems( lst );
+}
+
+void KRecentFilesAction::addURL( const KURL& url )
+{
+ addURL( url, url.fileName() );
+}
+
+void KRecentFilesAction::addURL( const KURL& url, const QString& name )
+{
+ if ( url.isLocalFile() && !KGlobal::dirs()->relativeLocation("tmp", url.path()).startsWith("/"))
+ return;
+ const QString file = url.pathOrURL();
+ QStringList lst = KSelectAction::items();
+
+ // remove file if already in list
+ const QStringList::Iterator end = lst.end();
+ for ( QStringList::Iterator it = lst.begin(); it != end; ++it )
+ {
+ QString title = (*it);
+ if ( title.endsWith( file + "]" ) )
+ {
+ lst.remove( it );
+ d->m_urls.erase( title );
+ d->m_shortNames.erase( title );
+ break;
+ }
+ }
+ // remove last item if already maxitems in list
+ if( lst.count() == d->m_maxItems )
+ {
+ // remove last item
+ const QString lastItem = lst.last();
+ d->m_shortNames.erase( lastItem );
+ d->m_urls.erase( lastItem );
+ lst.remove( lastItem );
+ }
+
+ // add file to list
+ const QString title = name + " [" + file + "]";
+ d->m_shortNames.insert( title, name );
+ d->m_urls.insert( title, url );
+ lst.prepend( title );
+ setItems( lst );
+}
+
+void KRecentFilesAction::removeURL( const KURL& url )
+{
+ QStringList lst = KSelectAction::items();
+ QString file = url.pathOrURL();
+
+ // remove url
+ QStringList::Iterator end = lst.end();
+ for ( QStringList::Iterator it = lst.begin(); it != end; ++it )
+ {
+ if ( (*it).endsWith( file + "]" ))
+ {
+ d->m_shortNames.erase( (*it) );
+ d->m_urls.erase( (*it) );
+ lst.remove( it );
+ setItems( lst );
+ break;
+ }
+ }
+}
+
+void KRecentFilesAction::clearURLList()
+{
+ clear();
+ d->m_shortNames.clear();
+ d->m_urls.clear();
+}
+
+void KRecentFilesAction::loadEntries( KConfig* config, QString groupname)
+{
+ QString key;
+ QString value;
+ QString nameKey;
+ QString nameValue;
+ QString title;
+ QString oldGroup;
+ QStringList lst;
+ KURL url;
+
+ oldGroup = config->group();
+
+ if (groupname.isEmpty())
+ groupname = "RecentFiles";
+ config->setGroup( groupname );
+
+ // read file list
+ for( unsigned int i = 1 ; i <= d->m_maxItems ; i++ )
+ {
+ key = QString( "File%1" ).arg( i );
+ value = config->readPathEntry( key );
+ url = KURL::fromPathOrURL( value );
+
+ // Don't restore if file doesn't exist anymore
+ if (url.isLocalFile() && !QFile::exists(url.path()))
+ continue;
+
+ nameKey = QString( "Name%1" ).arg( i );
+ nameValue = config->readPathEntry( nameKey, url.fileName() );
+ title = nameValue + " [" + value + "]";
+ if (!value.isNull())
+ {
+ lst.append( title );
+ d->m_shortNames.insert( title, nameValue );
+ d->m_urls.insert( title, url );
+ }
+ }
+
+ // set file
+ setItems( lst );
+
+ config->setGroup( oldGroup );
+}
+
+void KRecentFilesAction::saveEntries( KConfig* config, QString groupname )
+{
+ QString key;
+ QString value;
+ QString oldGroup;
+ QStringList lst = KSelectAction::items();
+
+ oldGroup = config->group();
+
+ if (groupname.isEmpty())
+ groupname = "RecentFiles";
+ config->deleteGroup( groupname, true );
+ config->setGroup( groupname );
+
+ // write file list
+ for( unsigned int i = 1 ; i <= lst.count() ; i++ )
+ {
+ //kdDebug(129) << "Entry for " << lst[i-1] << d->m_urls[ lst[ i - 1 ] ] << endl;
+ key = QString( "File%1" ).arg( i );
+ value = d->m_urls[ lst[ i - 1 ] ].pathOrURL();
+ config->writePathEntry( key, value );
+ key = QString( "Name%1" ).arg( i );
+ value = d->m_shortNames[ lst[ i - 1 ] ];
+ config->writePathEntry( key, value );
+ }
+
+ config->setGroup( oldGroup );
+}
+
+void KRecentFilesAction::itemSelected( const QString& text )
+{
+ //return a copy of the URL since the slot where it is connected might call
+ //addURL or removeURL where the d->m_urls.erase( title ) could destroy the
+ //d->m_urls[ text ] and the emitted URL will be invalid in the rest of the slot
+ emit urlSelected( KURL(d->m_urls[ text ]) );
+}
+
+void KRecentFilesAction::menuItemActivated( int id )
+{
+ QString text = d->m_popup->text(id);
+ //return a copy of the URL since the slot where it is connected might call
+ //addURL or removeURL where the d->m_urls.erase( title ) could destroy the
+ //d->m_urls[ text ] and the emitted URL will be invalid in the rest of the slot
+ emit urlSelected( KURL(d->m_urls[ text ]) );
+}
+
+void KRecentFilesAction::menuAboutToShow()
+{
+ KPopupMenu *menu = d->m_popup;
+ menu->clear();
+ QStringList list = KSelectAction::items();
+ for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it )
+ {
+ menu->insertItem(*it);
+ }
+}
+
+int KRecentFilesAction::plug( QWidget *widget, int index )
+{
+ if (kapp && !kapp->authorizeKAction(name()))
+ return -1;
+ // This is very related to KActionMenu::plug.
+ // In fact this class could be an interesting base class for KActionMenu
+ if ( ::qt_cast<KToolBar *>( widget ) )
+ {
+ KToolBar *bar = (KToolBar *)widget;
+
+ int id_ = KAction::getToolButtonID();
+
+ KInstance * instance;
+ if ( m_parentCollection )
+ instance = m_parentCollection->instance();
+ else
+ instance = KGlobal::instance();
+
+ bar->insertButton( icon(), id_, SIGNAL( clicked() ), this,
+ SLOT( slotClicked() ), isEnabled(), plainText(),
+ index, instance );
+
+ addContainer( bar, id_ );
+
+ connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) );
+
+ bar->setDelayedPopup( id_, d->m_popup, true);
+
+ if ( !whatsThis().isEmpty() )
+ QWhatsThis::add( bar->getButton( id_ ), whatsThisWithIcon() );
+
+ return containerCount() - 1;
+ }
+
+ return KListAction::plug( widget, index );
+}
+
+void KRecentFilesAction::slotClicked()
+{
+ KAction::slotActivated();
+}
+
+void KRecentFilesAction::slotActivated(const QString& text)
+{
+ KListAction::slotActivated(text);
+}
+
+
+void KRecentFilesAction::slotActivated(int id)
+{
+ KListAction::slotActivated(id);
+}
+
+
+void KRecentFilesAction::slotActivated()
+{
+ emit activated( currentItem() );
+ emit activated( currentText() );
+}
+
+//KDE4: rename to urls() and return a KURL::List
+QStringList KRecentFilesAction::items() const
+{
+ QStringList lst = KSelectAction::items();
+ QStringList result;
+
+ for( unsigned int i = 1 ; i <= lst.count() ; i++ )
+ {
+ result += d->m_urls[ lst[ i - 1 ] ].prettyURL(0, KURL::StripFileProtocol);
+ }
+
+ return result;
+}
+
+//KDE4: remove
+QStringList KRecentFilesAction::completeItems() const
+{
+ return KSelectAction::items();
+}
+
+
+class KFontAction::KFontActionPrivate
+{
+public:
+ KFontActionPrivate()
+ {
+ }
+ QStringList m_fonts;
+};
+
+KFontAction::KFontAction( const QString& text,
+ const KShortcut& cut, QObject* parent,
+ const char* name )
+ : KSelectAction( text, cut, parent, name )
+{
+ d = new KFontActionPrivate;
+ KFontChooser::getFontList( d->m_fonts, 0 );
+ KSelectAction::setItems( d->m_fonts );
+ setEditable( true );
+}
+
+KFontAction::KFontAction( const QString& text, const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ QObject* parent, const char* name )
+ : KSelectAction( text, cut, receiver, slot, parent, name )
+{
+ d = new KFontActionPrivate;
+ KFontChooser::getFontList( d->m_fonts, 0 );
+ KSelectAction::setItems( d->m_fonts );
+ setEditable( true );
+}
+
+KFontAction::KFontAction( const QString& text, const QIconSet& pix,
+ const KShortcut& cut,
+ QObject* parent, const char* name )
+ : KSelectAction( text, pix, cut, parent, name )
+{
+ d = new KFontActionPrivate;
+ KFontChooser::getFontList( d->m_fonts, 0 );
+ KSelectAction::setItems( d->m_fonts );
+ setEditable( true );
+}
+
+KFontAction::KFontAction( const QString& text, const QString& pix,
+ const KShortcut& cut,
+ QObject* parent, const char* name )
+ : KSelectAction( text, pix, cut, parent, name )
+{
+ d = new KFontActionPrivate;
+ KFontChooser::getFontList( d->m_fonts, 0 );
+ KSelectAction::setItems( d->m_fonts );
+ setEditable( true );
+}
+
+KFontAction::KFontAction( const QString& text, const QIconSet& pix,
+ const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ QObject* parent, const char* name )
+ : KSelectAction( text, pix, cut, receiver, slot, parent, name )
+{
+ d = new KFontActionPrivate;
+ KFontChooser::getFontList( d->m_fonts, 0 );
+ KSelectAction::setItems( d->m_fonts );
+ setEditable( true );
+}
+
+KFontAction::KFontAction( const QString& text, const QString& pix,
+ const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ QObject* parent, const char* name )
+ : KSelectAction( text, pix, cut, receiver, slot, parent, name )
+{
+ d = new KFontActionPrivate;
+ KFontChooser::getFontList( d->m_fonts, 0 );
+ KSelectAction::setItems( d->m_fonts );
+ setEditable( true );
+}
+
+KFontAction::KFontAction( uint fontListCriteria, const QString& text,
+ const KShortcut& cut, QObject* parent,
+ const char* name )
+ : KSelectAction( text, cut, parent, name )
+{
+ d = new KFontActionPrivate;
+ KFontChooser::getFontList( d->m_fonts, fontListCriteria );
+ KSelectAction::setItems( d->m_fonts );
+ setEditable( true );
+}
+
+KFontAction::KFontAction( uint fontListCriteria, const QString& text, const QString& pix,
+ const KShortcut& cut,
+ QObject* parent, const char* name )
+ : KSelectAction( text, pix, cut, parent, name )
+{
+ d = new KFontActionPrivate;
+ KFontChooser::getFontList( d->m_fonts, fontListCriteria );
+ KSelectAction::setItems( d->m_fonts );
+ setEditable( true );
+}
+
+KFontAction::KFontAction( QObject* parent, const char* name )
+ : KSelectAction( parent, name )
+{
+ d = new KFontActionPrivate;
+ KFontChooser::getFontList( d->m_fonts, 0 );
+ KSelectAction::setItems( d->m_fonts );
+ setEditable( true );
+}
+
+KFontAction::~KFontAction()
+{
+ delete d;
+ d = 0;
+}
+
+/*
+ * Maintenance note: Keep in sync with KFontCombo::setCurrentFont()
+ */
+void KFontAction::setFont( const QString &family )
+{
+ QString lowerName = family.lower();
+ int i = 0;
+ for ( QStringList::Iterator it = d->m_fonts.begin(); it != d->m_fonts.end(); ++it, ++i )
+ {
+ if ((*it).lower() == lowerName)
+ {
+ setCurrentItem(i);
+ return;
+ }
+ }
+ i = lowerName.find(" [");
+ if (i>-1)
+ {
+ lowerName = lowerName.left(i);
+ i = 0;
+ for ( QStringList::Iterator it = d->m_fonts.begin(); it != d->m_fonts.end(); ++it, ++i )
+ {
+ if ((*it).lower() == lowerName)
+ {
+ setCurrentItem(i);
+ return;
+ }
+ }
+ }
+
+ lowerName += " [";
+ i = 0;
+ for ( QStringList::Iterator it = d->m_fonts.begin(); it != d->m_fonts.end(); ++it, ++i )
+ {
+ if ((*it).lower().startsWith(lowerName))
+ {
+ setCurrentItem(i);
+ return;
+ }
+ }
+ kdDebug(129) << "Font not found " << family.lower() << endl;
+}
+
+int KFontAction::plug( QWidget *w, int index )
+{
+ if (kapp && !kapp->authorizeKAction(name()))
+ return -1;
+ if ( ::qt_cast<KToolBar *>( w ) )
+ {
+ KToolBar* bar = static_cast<KToolBar*>( w );
+ int id_ = KAction::getToolButtonID();
+ KFontCombo *cb = new KFontCombo( items(), bar );
+ connect( cb, SIGNAL( activated( const QString & ) ),
+ SLOT( slotActivated( const QString & ) ) );
+ cb->setEnabled( isEnabled() );
+ bar->insertWidget( id_, comboWidth(), cb, index );
+ cb->setMinimumWidth( cb->sizeHint().width() );
+
+ addContainer( bar, id_ );
+
+ connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) );
+
+ updateCurrentItem( containerCount() - 1 );
+
+ return containerCount() - 1;
+ }
+ else return KSelectAction::plug( w, index );
+}
+
+class KFontSizeAction::KFontSizeActionPrivate
+{
+public:
+ KFontSizeActionPrivate()
+ {
+ }
+};
+
+KFontSizeAction::KFontSizeAction( const QString& text,
+ const KShortcut& cut,
+ QObject* parent, const char* name )
+ : KSelectAction( text, cut, parent, name )
+{
+ init();
+}
+
+KFontSizeAction::KFontSizeAction( const QString& text,
+ const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ QObject* parent, const char* name )
+ : KSelectAction( text, cut, receiver, slot, parent, name )
+{
+ init();
+}
+
+KFontSizeAction::KFontSizeAction( const QString& text, const QIconSet& pix,
+ const KShortcut& cut,
+ QObject* parent, const char* name )
+ : KSelectAction( text, pix, cut, parent, name )
+{
+ init();
+}
+
+KFontSizeAction::KFontSizeAction( const QString& text, const QString& pix,
+ const KShortcut& cut,
+ QObject* parent, const char* name )
+ : KSelectAction( text, pix, cut, parent, name )
+{
+ init();
+}
+
+KFontSizeAction::KFontSizeAction( const QString& text, const QIconSet& pix,
+ const KShortcut& cut,
+ const QObject* receiver,
+ const char* slot, QObject* parent,
+ const char* name )
+ : KSelectAction( text, pix, cut, receiver, slot, parent, name )
+{
+ init();
+}
+
+KFontSizeAction::KFontSizeAction( const QString& text, const QString& pix,
+ const KShortcut& cut,
+ const QObject* receiver,
+ const char* slot, QObject* parent,
+ const char* name )
+ : KSelectAction( text, pix, cut, receiver, slot, parent, name )
+{
+ init();
+}
+
+KFontSizeAction::KFontSizeAction( QObject* parent, const char* name )
+ : KSelectAction( parent, name )
+{
+ init();
+}
+
+KFontSizeAction::~KFontSizeAction()
+{
+ delete d;
+ d = 0;
+}
+
+void KFontSizeAction::init()
+{
+ d = new KFontSizeActionPrivate;
+
+ setEditable( true );
+ QFontDatabase fontDB;
+ QValueList<int> sizes = fontDB.standardSizes();
+ QStringList lst;
+ for ( QValueList<int>::Iterator it = sizes.begin(); it != sizes.end(); ++it )
+ lst.append( QString::number( *it ) );
+
+ setItems( lst );
+}
+
+void KFontSizeAction::setFontSize( int size )
+{
+ if ( size == fontSize() ) {
+ setCurrentItem( items().findIndex( QString::number( size ) ) );
+ return;
+ }
+
+ if ( size < 1 ) {
+ kdWarning() << "KFontSizeAction: Size " << size << " is out of range" << endl;
+ return;
+ }
+
+ int index = items().findIndex( QString::number( size ) );
+ if ( index == -1 ) {
+ // Insert at the correct position in the list (to keep sorting)
+ QValueList<int> lst;
+ // Convert to list of ints
+ QStringList itemsList = items();
+ for (QStringList::Iterator it = itemsList.begin() ; it != itemsList.end() ; ++it)
+ lst.append( (*it).toInt() );
+ // New size
+ lst.append( size );
+ // Sort the list
+ qHeapSort( lst );
+ // Convert back to string list
+ QStringList strLst;
+ for (QValueList<int>::Iterator it = lst.begin() ; it != lst.end() ; ++it)
+ strLst.append( QString::number(*it) );
+ KSelectAction::setItems( strLst );
+ // Find new current item
+ index = lst.findIndex( size );
+ setCurrentItem( index );
+ }
+ else
+ setCurrentItem( index );
+
+
+ //emit KAction::activated();
+ //emit activated( index );
+ //emit activated( QString::number( size ) );
+ //emit fontSizeChanged( size );
+}
+
+int KFontSizeAction::fontSize() const
+{
+ return currentText().toInt();
+}
+
+void KFontSizeAction::slotActivated( int index )
+{
+ KSelectAction::slotActivated( index );
+
+ emit fontSizeChanged( items()[ index ].toInt() );
+}
+
+void KFontSizeAction::slotActivated( const QString& size )
+{
+ setFontSize( size.toInt() ); // insert sorted first
+ KSelectAction::slotActivated( size );
+ emit fontSizeChanged( size.toInt() );
+}
+
+class KActionMenu::KActionMenuPrivate
+{
+public:
+ KActionMenuPrivate()
+ {
+ m_popup = new KPopupMenu(0L,"KActionMenu::KActionMenuPrivate");
+ m_delayed = true;
+ m_stickyMenu = true;
+ }
+ ~KActionMenuPrivate()
+ {
+ delete m_popup; m_popup = 0;
+ }
+ KPopupMenu *m_popup;
+ bool m_delayed;
+ bool m_stickyMenu;
+};
+
+KActionMenu::KActionMenu( QObject* parent, const char* name )
+ : KAction( parent, name )
+{
+ d = new KActionMenuPrivate;
+ setShortcutConfigurable( false );
+}
+
+KActionMenu::KActionMenu( const QString& text, QObject* parent,
+ const char* name )
+ : KAction( text, 0, parent, name )
+{
+ d = new KActionMenuPrivate;
+ setShortcutConfigurable( false );
+}
+
+KActionMenu::KActionMenu( const QString& text, const QIconSet& icon,
+ QObject* parent, const char* name )
+ : KAction( text, icon, 0, parent, name )
+{
+ d = new KActionMenuPrivate;
+ setShortcutConfigurable( false );
+}
+
+KActionMenu::KActionMenu( const QString& text, const QString& icon,
+ QObject* parent, const char* name )
+ : KAction( text, icon, 0, parent, name )
+{
+ d = new KActionMenuPrivate;
+ setShortcutConfigurable( false );
+}
+
+KActionMenu::~KActionMenu()
+{
+ unplugAll();
+ kdDebug(129) << "KActionMenu::~KActionMenu()" << endl; // ellis
+ delete d; d = 0;
+}
+
+void KActionMenu::popup( const QPoint& global )
+{
+ popupMenu()->popup( global );
+}
+
+KPopupMenu* KActionMenu::popupMenu() const
+{
+ return d->m_popup;
+}
+
+void KActionMenu::insert( KAction* cmd, int index )
+{
+ if ( cmd )
+ cmd->plug( d->m_popup, index );
+}
+
+void KActionMenu::remove( KAction* cmd )
+{
+ if ( cmd )
+ cmd->unplug( d->m_popup );
+}
+
+bool KActionMenu::delayed() const {
+ return d->m_delayed;
+}
+
+void KActionMenu::setDelayed(bool _delayed) {
+ d->m_delayed = _delayed;
+}
+
+bool KActionMenu::stickyMenu() const {
+ return d->m_stickyMenu;
+}
+
+void KActionMenu::setStickyMenu(bool sticky) {
+ d->m_stickyMenu = sticky;
+}
+
+int KActionMenu::plug( QWidget* widget, int index )
+{
+ if (kapp && !kapp->authorizeKAction(name()))
+ return -1;
+ kdDebug(129) << "KActionMenu::plug( " << widget << ", " << index << " )" << endl; // remove -- ellis
+ if ( ::qt_cast<QPopupMenu *>( widget ) )
+ {
+ QPopupMenu* menu = static_cast<QPopupMenu*>( widget );
+ int id;
+ if ( hasIcon() )
+ id = menu->insertItem( iconSet(), text(), d->m_popup, -1, index );
+ else
+ id = menu->insertItem( text(), d->m_popup, -1, index );
+
+ if ( !isEnabled() )
+ menu->setItemEnabled( id, false );
+
+ addContainer( menu, id );
+ connect( menu, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) );
+
+ if ( m_parentCollection )
+ m_parentCollection->connectHighlight( menu, this );
+
+ return containerCount() - 1;
+ }
+ else if ( ::qt_cast<KToolBar *>( widget ) )
+ {
+ KToolBar *bar = static_cast<KToolBar *>( widget );
+
+ int id_ = KAction::getToolButtonID();
+
+ if ( icon().isEmpty() && !iconSet().isNull() )
+ bar->insertButton( iconSet().pixmap(), id_, SIGNAL( clicked() ), this,
+ SLOT( slotActivated() ), isEnabled(), plainText(),
+ index );
+ else
+ {
+ KInstance *instance;
+
+ if ( m_parentCollection )
+ instance = m_parentCollection->instance();
+ else
+ instance = KGlobal::instance();
+
+ bar->insertButton( icon(), id_, SIGNAL( clicked() ), this,
+ SLOT( slotActivated() ), isEnabled(), plainText(),
+ index, instance );
+ }
+
+ addContainer( bar, id_ );
+
+ if (!whatsThis().isEmpty())
+ QWhatsThis::add( bar->getButton(id_), whatsThis() );
+
+ connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) );
+
+ if (delayed()) {
+ bar->setDelayedPopup( id_, popupMenu(), stickyMenu() );
+ } else {
+ bar->getButton(id_)->setPopup(popupMenu(), stickyMenu() );
+ }
+
+ if ( m_parentCollection )
+ m_parentCollection->connectHighlight( bar, this );
+
+ return containerCount() - 1;
+ }
+ else if ( ::qt_cast<QMenuBar *>( widget ) )
+ {
+ QMenuBar *bar = static_cast<QMenuBar *>( widget );
+
+ int id;
+
+ id = bar->insertItem( text(), popupMenu(), -1, index );
+
+ if ( !isEnabled() )
+ bar->setItemEnabled( id, false );
+
+ addContainer( bar, id );
+ connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) );
+
+ return containerCount() - 1;
+ }
+
+ return -1;
+}
+
+////////
+
+KToolBarPopupAction::KToolBarPopupAction( const QString& text,
+ const QString& icon,
+ const KShortcut& cut,
+ QObject* parent, const char* name )
+ : KAction( text, icon, cut, parent, name )
+{
+ m_popup = 0;
+ m_delayed = true;
+ m_stickyMenu = true;
+}
+
+KToolBarPopupAction::KToolBarPopupAction( const QString& text,
+ const QString& icon,
+ const KShortcut& cut,
+ const QObject* receiver,
+ const char* slot, QObject* parent,
+ const char* name )
+ : KAction( text, icon, cut, receiver, slot, parent, name )
+{
+ m_popup = 0;
+ m_delayed = true;
+ m_stickyMenu = true;
+}
+
+KToolBarPopupAction::KToolBarPopupAction( const KGuiItem& item,
+ const KShortcut& cut,
+ const QObject* receiver,
+ const char* slot, KActionCollection* parent,
+ const char* name )
+ : KAction( item, cut, receiver, slot, parent, name )
+{
+ m_popup = 0;
+ m_delayed = true;
+ m_stickyMenu = true;
+}
+
+KToolBarPopupAction::~KToolBarPopupAction()
+{
+ delete m_popup;
+}
+
+bool KToolBarPopupAction::delayed() const {
+ return m_delayed;
+}
+
+void KToolBarPopupAction::setDelayed(bool delayed) {
+ m_delayed = delayed;
+}
+
+bool KToolBarPopupAction::stickyMenu() const {
+ return m_stickyMenu;
+}
+
+void KToolBarPopupAction::setStickyMenu(bool sticky) {
+ m_stickyMenu = sticky;
+}
+
+int KToolBarPopupAction::plug( QWidget *widget, int index )
+{
+ if (kapp && !kapp->authorizeKAction(name()))
+ return -1;
+ // This is very related to KActionMenu::plug.
+ // In fact this class could be an interesting base class for KActionMenu
+ if ( ::qt_cast<KToolBar *>( widget ) )
+ {
+ KToolBar *bar = (KToolBar *)widget;
+
+ int id_ = KAction::getToolButtonID();
+
+ if ( icon().isEmpty() && !iconSet().isNull() ) {
+ bar->insertButton( iconSet().pixmap(), id_, SIGNAL( buttonClicked(int, Qt::ButtonState) ), this,
+ SLOT( slotButtonClicked(int, Qt::ButtonState) ),
+ isEnabled(), plainText(),
+ index );
+ } else {
+ KInstance * instance;
+ if ( m_parentCollection )
+ instance = m_parentCollection->instance();
+ else
+ instance = KGlobal::instance();
+
+ bar->insertButton( icon(), id_, SIGNAL( buttonClicked(int, Qt::ButtonState) ), this,
+ SLOT( slotButtonClicked(int, Qt::ButtonState) ),
+ isEnabled(), plainText(),
+ index, instance );
+ }
+
+ addContainer( bar, id_ );
+
+ connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) );
+
+ if (delayed()) {
+ bar->setDelayedPopup( id_, popupMenu(), stickyMenu() );
+ } else {
+ bar->getButton(id_)->setPopup(popupMenu(), stickyMenu());
+ }
+
+ if ( !whatsThis().isEmpty() )
+ QWhatsThis::add( bar->getButton( id_ ), whatsThisWithIcon() );
+
+ return containerCount() - 1;
+ }
+
+ return KAction::plug( widget, index );
+}
+
+KPopupMenu *KToolBarPopupAction::popupMenu() const
+{
+ if ( !m_popup ) {
+ KToolBarPopupAction *that = const_cast<KToolBarPopupAction*>(this);
+ that->m_popup = new KPopupMenu;
+ }
+ return m_popup;
+}
+
+////////
+
+KToggleToolBarAction::KToggleToolBarAction( const char* toolBarName,
+ const QString& text, KActionCollection* parent, const char* name )
+ : KToggleAction( text, KShortcut(), parent, name )
+ , m_toolBarName( toolBarName )
+ , m_toolBar( 0L )
+{
+}
+
+KToggleToolBarAction::KToggleToolBarAction( KToolBar *toolBar, const QString &text,
+ KActionCollection *parent, const char *name )
+ : KToggleAction( text, KShortcut(), parent, name )
+ , m_toolBarName( 0 ), m_toolBar( toolBar )
+{
+}
+
+KToggleToolBarAction::~KToggleToolBarAction()
+{
+}
+
+int KToggleToolBarAction::plug( QWidget* w, int index )
+{
+ if (kapp && !kapp->authorizeKAction(name()))
+ return -1;
+
+ if ( !m_toolBar ) {
+ // Note: topLevelWidget() stops too early, we can't use it.
+ QWidget * tl = w;
+ QWidget * n;
+ while ( !tl->isDialog() && ( n = tl->parentWidget() ) ) // lookup parent and store
+ tl = n;
+
+ KMainWindow * mw = dynamic_cast<KMainWindow *>(tl); // try to see if it's a kmainwindow
+
+ if ( mw )
+ m_toolBar = mw->toolBar( m_toolBarName );
+ }
+
+ if( m_toolBar ) {
+ setChecked( m_toolBar->isVisible() );
+ connect( m_toolBar, SIGNAL(visibilityChanged(bool)), this, SLOT(setChecked(bool)) );
+ // Also emit toggled when the toolbar's visibility changes (see comment in header)
+ connect( m_toolBar, SIGNAL(visibilityChanged(bool)), this, SIGNAL(toggled(bool)) );
+ } else {
+ setEnabled( false );
+ }
+
+ return KToggleAction::plug( w, index );
+}
+
+void KToggleToolBarAction::setChecked( bool c )
+{
+ if( m_toolBar && c != m_toolBar->isVisible() ) {
+ if( c ) {
+ m_toolBar->show();
+ } else {
+ m_toolBar->hide();
+ }
+ QMainWindow* mw = m_toolBar->mainWindow();
+ if ( mw && ::qt_cast<KMainWindow *>( mw ) )
+ static_cast<KMainWindow *>( mw )->setSettingsDirty();
+ }
+ KToggleAction::setChecked( c );
+}
+
+////////
+
+KToggleFullScreenAction::KToggleFullScreenAction( const KShortcut &cut,
+ const QObject* receiver, const char* slot,
+ QObject* parent, QWidget* window,
+ const char* name )
+ : KToggleAction( QString::null, cut, receiver, slot, parent, name ),
+ window( NULL )
+{
+ setWindow( window );
+}
+
+KToggleFullScreenAction::~KToggleFullScreenAction()
+{
+}
+
+void KToggleFullScreenAction::setWindow( QWidget* w )
+{
+ if( window )
+ window->removeEventFilter( this );
+ window = w;
+ if( window )
+ window->installEventFilter( this );
+}
+
+void KToggleFullScreenAction::setChecked( bool c )
+{
+ if (c)
+ {
+ setText(i18n("Exit F&ull Screen Mode"));
+ setIcon("window_nofullscreen");
+ }
+ else
+ {
+ setText(i18n("F&ull Screen Mode"));
+ setIcon("window_fullscreen");
+ }
+ KToggleAction::setChecked( c );
+}
+
+bool KToggleFullScreenAction::eventFilter( QObject* o, QEvent* e )
+{
+ if( o == window )
+ if( e->type() == QEvent::WindowStateChange )
+ {
+ if( window->isFullScreen() != isChecked())
+ slotActivated(); // setChecked( window->isFullScreen()) wouldn't emit signals
+ }
+ return false;
+}
+
+////////
+
+KWidgetAction::KWidgetAction( QWidget* widget,
+ const QString& text, const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ KActionCollection* parent, const char* name )
+ : KAction( text, cut, receiver, slot, parent, name )
+ , m_widget( widget )
+ , m_autoSized( false )
+{
+ connect( this, SIGNAL(enabled(bool)), widget, SLOT(setEnabled(bool)) );
+}
+
+KWidgetAction::~KWidgetAction()
+{
+}
+
+void KWidgetAction::setAutoSized( bool autoSized )
+{
+ if( m_autoSized == autoSized )
+ return;
+
+ m_autoSized = autoSized;
+
+ if( !m_widget || !isPlugged() )
+ return;
+
+ KToolBar* toolBar = (KToolBar*)m_widget->parent();
+ int i = findContainer( toolBar );
+ if ( i == -1 )
+ return;
+ int id = itemId( i );
+
+ toolBar->setItemAutoSized( id, m_autoSized );
+}
+
+int KWidgetAction::plug( QWidget* w, int index )
+{
+ if (kapp && !kapp->authorizeKAction(name()))
+ return -1;
+
+ if ( !::qt_cast<KToolBar *>( w ) ) {
+ kdError() << "KWidgetAction::plug: KWidgetAction must be plugged into KToolBar." << endl;
+ return -1;
+ }
+ if ( !m_widget ) {
+ kdError() << "KWidgetAction::plug: Widget was deleted or null!" << endl;
+ return -1;
+ }
+
+ KToolBar* toolBar = static_cast<KToolBar*>( w );
+
+ int id = KAction::getToolButtonID();
+
+ m_widget->reparent( toolBar, QPoint() );
+ toolBar->insertWidget( id, 0, m_widget, index );
+ toolBar->setItemAutoSized( id, m_autoSized );
+
+ QWhatsThis::add( m_widget, whatsThis() );
+ addContainer( toolBar, id );
+
+ connect( toolBar, SIGNAL( toolbarDestroyed() ), this, SLOT( slotToolbarDestroyed() ) );
+ connect( toolBar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) );
+
+ return containerCount() - 1;
+}
+
+void KWidgetAction::unplug( QWidget *w )
+{
+ if( !m_widget || !isPlugged() )
+ return;
+
+ KToolBar* toolBar = (KToolBar*)m_widget->parent();
+ if ( toolBar == w )
+ {
+ disconnect( toolBar, SIGNAL( toolbarDestroyed() ), this, SLOT( slotToolbarDestroyed() ) );
+ m_widget->reparent( 0L, QPoint(), false /*showIt*/ );
+ }
+ KAction::unplug( w );
+}
+
+void KWidgetAction::slotToolbarDestroyed()
+{
+ //Q_ASSERT( m_widget ); // When exiting the app the widget could be destroyed before the toolbar.
+ Q_ASSERT( isPlugged() );
+ if( !m_widget || !isPlugged() )
+ return;
+
+ // Don't let a toolbar being destroyed, delete my widget.
+ m_widget->reparent( 0L, QPoint(), false /*showIt*/ );
+}
+
+////////
+
+KActionSeparator::KActionSeparator( QObject *parent, const char *name )
+ : KAction( parent, name )
+{
+}
+
+KActionSeparator::~KActionSeparator()
+{
+}
+
+int KActionSeparator::plug( QWidget *widget, int index )
+{
+ if ( ::qt_cast<QPopupMenu *>( widget) )
+ {
+ QPopupMenu* menu = static_cast<QPopupMenu*>( widget );
+
+ int id = menu->insertSeparator( index );
+
+ addContainer( menu, id );
+ connect( menu, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) );
+
+ return containerCount() - 1;
+ }
+ else if ( ::qt_cast<QMenuBar *>( widget ) )
+ {
+ QMenuBar *menuBar = static_cast<QMenuBar *>( widget );
+
+ int id = menuBar->insertSeparator( index );
+
+ addContainer( menuBar, id );
+
+ connect( menuBar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) );
+
+ return containerCount() - 1;
+ }
+ else if ( ::qt_cast<KToolBar *>( widget ) )
+ {
+ KToolBar *toolBar = static_cast<KToolBar *>( widget );
+
+ int id = toolBar->insertSeparator( index );
+
+ addContainer( toolBar, id );
+
+ connect( toolBar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) );
+
+ return containerCount() - 1;
+ }
+
+ return -1;
+}
+
+KPasteTextAction::KPasteTextAction( const QString& text,
+ const QString& icon,
+ const KShortcut& cut,
+ const QObject* receiver,
+ const char* slot, QObject* parent,
+ const char* name)
+ : KAction( text, icon, cut, receiver, slot, parent, name )
+{
+ m_popup = new KPopupMenu;
+ connect(m_popup, SIGNAL(aboutToShow()), this, SLOT(menuAboutToShow()));
+ connect(m_popup, SIGNAL(activated(int)), this, SLOT(menuItemActivated(int)));
+ m_popup->setCheckable(true);
+ m_mixedMode = true;
+}
+
+KPasteTextAction::~KPasteTextAction()
+{
+ delete m_popup;
+}
+
+void KPasteTextAction::setMixedMode(bool mode)
+{
+ m_mixedMode = mode;
+}
+
+int KPasteTextAction::plug( QWidget *widget, int index )
+{
+ if (kapp && !kapp->authorizeKAction(name()))
+ return -1;
+ if ( ::qt_cast<KToolBar *>( widget ) )
+ {
+ KToolBar *bar = (KToolBar *)widget;
+
+ int id_ = KAction::getToolButtonID();
+
+ KInstance * instance;
+ if ( m_parentCollection )
+ instance = m_parentCollection->instance();
+ else
+ instance = KGlobal::instance();
+
+ bar->insertButton( icon(), id_, SIGNAL( clicked() ), this,
+ SLOT( slotActivated() ), isEnabled(), plainText(),
+ index, instance );
+
+ addContainer( bar, id_ );
+
+ connect( bar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) );
+
+ bar->setDelayedPopup( id_, m_popup, true );
+
+ if ( !whatsThis().isEmpty() )
+ QWhatsThis::add( bar->getButton( id_ ), whatsThisWithIcon() );
+
+ return containerCount() - 1;
+ }
+
+ return KAction::plug( widget, index );
+}
+
+void KPasteTextAction::menuAboutToShow()
+{
+ m_popup->clear();
+ QStringList list;
+ DCOPClient *client = kapp->dcopClient();
+ if (client->isAttached() && client->isApplicationRegistered("klipper")) {
+ DCOPRef klipper("klipper","klipper");
+ DCOPReply reply = klipper.call("getClipboardHistoryMenu");
+ if (reply.isValid())
+ list = reply;
+ }
+ QString clipboardText = qApp->clipboard()->text(QClipboard::Clipboard);
+ if (list.isEmpty())
+ list << clipboardText;
+ bool found = false;
+ for ( QStringList::ConstIterator it = list.begin(); it != list.end(); ++it )
+ {
+ QString text = KStringHandler::cEmSqueeze((*it).simplifyWhiteSpace(), m_popup->fontMetrics(), 20);
+ text.replace("&", "&&");
+ int id = m_popup->insertItem(text);
+ if (!found && *it == clipboardText)
+ {
+ m_popup->setItemChecked(id, true);
+ found = true;
+ }
+ }
+}
+
+void KPasteTextAction::menuItemActivated( int id)
+{
+ DCOPClient *client = kapp->dcopClient();
+ if (client->isAttached() && client->isApplicationRegistered("klipper")) {
+ DCOPRef klipper("klipper","klipper");
+ DCOPReply reply = klipper.call("getClipboardHistoryItem(int)", m_popup->indexOf(id));
+ if (!reply.isValid())
+ return;
+ QString clipboardText = reply;
+ reply = klipper.call("setClipboardContents(QString)", clipboardText);
+ if (reply.isValid())
+ kdDebug(129) << "Clipboard: " << qApp->clipboard()->text(QClipboard::Clipboard) << endl;
+ }
+ QTimer::singleShot(20, this, SLOT(slotActivated()));
+}
+
+void KPasteTextAction::slotActivated()
+{
+ if (!m_mixedMode) {
+ QWidget *w = qApp->widgetAt(QCursor::pos(), true);
+ QMimeSource *data = QApplication::clipboard()->data();
+ if (!data->provides("text/plain") && w) {
+ m_popup->popup(w->mapToGlobal(QPoint(0, w->height())));
+ } else
+ KAction::slotActivated();
+ } else
+ KAction::slotActivated();
+}
+
+
+void KToggleAction::virtual_hook( int id, void* data )
+{ KAction::virtual_hook( id, data ); }
+
+void KRadioAction::virtual_hook( int id, void* data )
+{ KToggleAction::virtual_hook( id, data ); }
+
+void KSelectAction::virtual_hook( int id, void* data )
+{ KAction::virtual_hook( id, data ); }
+
+void KListAction::virtual_hook( int id, void* data )
+{ KSelectAction::virtual_hook( id, data ); }
+
+void KRecentFilesAction::virtual_hook( int id, void* data )
+{ KListAction::virtual_hook( id, data ); }
+
+void KFontAction::virtual_hook( int id, void* data )
+{ KSelectAction::virtual_hook( id, data ); }
+
+void KFontSizeAction::virtual_hook( int id, void* data )
+{ KSelectAction::virtual_hook( id, data ); }
+
+void KActionMenu::virtual_hook( int id, void* data )
+{ KAction::virtual_hook( id, data ); }
+
+void KToolBarPopupAction::virtual_hook( int id, void* data )
+{ KAction::virtual_hook( id, data ); }
+
+void KToggleToolBarAction::virtual_hook( int id, void* data )
+{ KToggleAction::virtual_hook( id, data ); }
+
+void KToggleFullScreenAction::virtual_hook( int id, void* data )
+{ KToggleAction::virtual_hook( id, data ); }
+
+void KWidgetAction::virtual_hook( int id, void* data )
+{ KAction::virtual_hook( id, data ); }
+
+void KActionSeparator::virtual_hook( int id, void* data )
+{ KAction::virtual_hook( id, data ); }
+
+void KPasteTextAction::virtual_hook( int id, void* data )
+{ KAction::virtual_hook( id, data ); }
+
+/* vim: et sw=2 ts=2
+ */
+
+#include "kactionclasses.moc"
diff --git a/kdeui/kactionclasses.h b/kdeui/kactionclasses.h
new file mode 100644
index 000000000..6c6fe5ca8
--- /dev/null
+++ b/kdeui/kactionclasses.h
@@ -0,0 +1,1422 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org>
+ (C) 1999 Simon Hausmann <hausmann@kde.org>
+ (C) 2000 Nicolas Hadacek <haadcek@kde.org>
+ (C) 2000 Kurt Granroth <granroth@kde.org>
+ (C) 2000 Michael Koch <koch@kde.org>
+ (C) 2001 Holger Freyther <freyther@kde.org>
+ (C) 2002 Ellis Whitehead <ellis@kde.org>
+ (C) 2003 Andras Mantia <amantia@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+//$Id$
+
+#ifndef __kactionclasses_h__
+#define __kactionclasses_h__
+
+#include <kaction.h>
+
+#include <qkeysequence.h>
+#include <qobject.h>
+#include <qvaluelist.h>
+#include <qguardedptr.h>
+#include <kguiitem.h>
+#include <kshortcut.h>
+#include <kstdaction.h>
+#include <kicontheme.h>
+
+class QMenuBar;
+class QPopupMenu;
+class QComboBox;
+class QPoint;
+class QIconSet;
+class QString;
+class KToolBar;
+
+class KAccel;
+class KAccelActions;
+class KConfig;
+class KConfigBase;
+class KURL;
+class KInstance;
+class KToolBar;
+class KActionCollection;
+class KPopupMenu;
+class KMainWindow;
+
+/**
+ * @short Checkbox like action.
+ *
+ * Checkbox like action.
+ *
+ * This action provides two states: checked or not.
+ *
+ */
+class KDEUI_EXPORT KToggleAction : public KAction
+{
+ Q_OBJECT
+ Q_PROPERTY( bool checked READ isChecked WRITE setChecked )
+ Q_PROPERTY( QString exclusiveGroup READ exclusiveGroup WRITE setExclusiveGroup )
+public:
+
+ /**
+ * Constructs a toggle action with text and potential keyboard
+ * accelerator but nothing else. Use this only if you really
+ * know what you are doing.
+ *
+ * @param text The text that will be displayed.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KToggleAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0, const char* name = 0 );
+
+ /**
+ * @param text The text that will be displayed.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param receiver The SLOT's parent.
+ * @param slot The SLOT to invoke to execute this action.
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KToggleAction( const QString& text, const KShortcut& cut,
+ const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 );
+
+ /**
+ * @param text The text that will be displayed.
+ * @param pix The icons that go with this action.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KToggleAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(),
+ QObject* parent = 0, const char* name = 0 );
+
+ /**
+ * @param text The text that will be displayed.
+ * @param pix The dynamically loaded icon that goes with this action.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KToggleAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(),
+ QObject* parent = 0, const char* name = 0 );
+
+ /**
+ * @param text The text that will be displayed.
+ * @param pix The icons that go with this action.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param receiver The SLOT's parent.
+ * @param slot The SLOT to invoke to execute this action.
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KToggleAction( const QString& text, const QIconSet& pix, const KShortcut& cut,
+ const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 );
+
+ /**
+ * @param text The text that will be displayed.
+ * @param pix The dynamically loaded icon that goes with this action.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param receiver The SLOT's parent.
+ * @param slot The SLOT to invoke to execute this action.
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KToggleAction( const QString& text, const QString& pix, const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ QObject* parent, const char* name = 0 );
+
+ /**
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KToggleAction( QObject* parent = 0, const char* name = 0 );
+
+ /**
+ * Destructor
+ */
+ virtual ~KToggleAction();
+
+ /**
+ * "Plug" or insert this action into a given widget.
+ *
+ * This will typically be a menu or a toolbar. From this point
+ * on, you will never need to directly manipulate the item in the
+ * menu or toolbar. You do all enabling/disabling/manipulation
+ * directly with your KToggleAction object.
+ *
+ * @param widget The GUI element to display this action.
+ * @param index The index of the item.
+ */
+ virtual int plug( QWidget* widget, int index = -1 );
+
+ /**
+ * Returns the actual state of the action.
+ */
+ bool isChecked() const;
+
+ /**
+ * @return which "exclusive group" this action is part of.
+ * @see setExclusiveGroup
+ */
+ QString exclusiveGroup() const;
+
+ /**
+ * Defines which "exclusive group" this action is part of.
+ * In a given exclusive group, only one toggle action can be checked
+ * at a any moment. Checking an action unchecks the other actions
+ * of the group.
+ */
+ virtual void setExclusiveGroup( const QString& name );
+
+ /**
+ * Defines the text (and icon, tooltip, whatsthis) that should be displayed
+ * instead of the normal text, when the action is checked.
+ * This feature replaces the checkmark that usually appears in front of the text, in menus.
+ * It is useful when the text is mainly a verb: e.g. "Show <foo>"
+ * should turn into "Hide <foo>" when activated.
+ *
+ * If hasIcon(), the icon is kept for the 'checked state', unless
+ * @p checkedItem defines an icon explicitely. Same thing for tooltip and whatsthis.
+ * @since 3.3
+ */
+ void setCheckedState( const KGuiItem& checkedItem );
+
+ /// Reimplemented for internal reasons
+ virtual QString toolTip() const;
+
+public slots:
+ /**
+ * Sets the state of the action.
+ */
+ virtual void setChecked( bool );
+
+protected slots:
+ virtual void slotActivated();
+
+protected:
+ virtual void updateChecked( int id );
+
+signals:
+ void toggled( bool );
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KToggleActionPrivate;
+ KToggleActionPrivate *d;
+};
+
+/**
+ * @short Radiobox like action.
+ *
+ * An action that operates like a radio button. At any given time
+ * only a single action from the group will be active.
+ */
+class KDEUI_EXPORT KRadioAction : public KToggleAction
+{
+ Q_OBJECT
+public:
+ /**
+ * Constructs a radio action with text and potential keyboard
+ * accelerator but nothing else. Use this only if you really
+ * know what you are doing.
+ *
+ * @param text The text that will be displayed.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KRadioAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0, const char* name = 0 );
+
+ /**
+ * @param text The text that will be displayed.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param receiver The SLOT's parent.
+ * @param slot The SLOT to invoke to execute this action.
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KRadioAction( const QString& text, const KShortcut& cut,
+ const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 );
+
+ /**
+ * @param text The text that will be displayed.
+ * @param pix The icons that go with this action.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KRadioAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(),
+ QObject* parent = 0, const char* name = 0 );
+
+ /**
+ * @param text The text that will be displayed.
+ * @param pix The dynamically loaded icon that goes with this action.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KRadioAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(),
+ QObject* parent = 0, const char* name = 0 );
+
+ /**
+ * @param text The text that will be displayed.
+ * @param pix The icons that go with this action.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param receiver The SLOT's parent.
+ * @param slot The SLOT to invoke to execute this action.
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KRadioAction( const QString& text, const QIconSet& pix, const KShortcut& cut,
+ const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 );
+
+ /**
+ * @param text The text that will be displayed.
+ * @param pix The dynamically loaded icon that goes with this action.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param receiver The SLOT's parent.
+ * @param slot The SLOT to invoke to execute this action.
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KRadioAction( const QString& text, const QString& pix, const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ QObject* parent, const char* name = 0 );
+
+ /**
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KRadioAction( QObject* parent = 0, const char* name = 0 );
+
+protected:
+ virtual void slotActivated();
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KRadioActionPrivate;
+ KRadioActionPrivate *d;
+};
+
+/**
+ * @short Action for selecting one of several items
+ *
+ * Action for selecting one of several items.
+ *
+ * This action shows up a submenu with a list of items.
+ * One of them can be checked. If the user clicks on an item
+ * this item will automatically be checked,
+ * the formerly checked item becomes unchecked.
+ * There can be only one item checked at a time.
+ */
+class KDEUI_EXPORT KSelectAction : public KAction
+{
+ Q_OBJECT
+ Q_PROPERTY( int currentItem READ currentItem WRITE setCurrentItem )
+ Q_PROPERTY( QStringList items READ items WRITE setItems )
+ Q_PROPERTY( bool editable READ isEditable WRITE setEditable )
+ Q_PROPERTY( int comboWidth READ comboWidth WRITE setComboWidth )
+ Q_PROPERTY( QString currentText READ currentText )
+ Q_PROPERTY( bool menuAccelsEnabled READ menuAccelsEnabled WRITE setMenuAccelsEnabled )
+public:
+
+ /**
+ * Constructs a select action with text and potential keyboard
+ * accelerator but nothing else. Use this only if you really
+ * know what you are doing.
+ *
+ * @param text The text that will be displayed.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KSelectAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0, const char* name = 0 );
+
+ /**
+ * @param text The text that will be displayed.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param receiver The SLOT's parent.
+ * @param slot The SLOT to invoke to execute this action.
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KSelectAction( const QString& text, const KShortcut& cut,
+ const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 );
+
+ /**
+ * @param text The text that will be displayed.
+ * @param pix The icons that go with this action.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KSelectAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(),
+ QObject* parent = 0, const char* name = 0 );
+
+ /**
+ * @param text The text that will be displayed.
+ * @param pix The dynamically loaded icon that goes with this action.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KSelectAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(),
+ QObject* parent = 0, const char* name = 0 );
+
+ /**
+ * @param text The text that will be displayed.
+ * @param pix The icons that go with this action.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param receiver The SLOT's parent.
+ * @param slot The SLOT to invoke to execute this action.
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KSelectAction( const QString& text, const QIconSet& pix, const KShortcut& cut,
+ const QObject* receiver, const char* slot, QObject* parent, const char* name = 0 );
+
+ /**
+ * @param text The text that will be displayed.
+ * @param pix The dynamically loaded icon that goes with this action.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param receiver The SLOT's parent.
+ * @param slot The SLOT to invoke to execute this action.
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KSelectAction( const QString& text, const QString& pix, const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ QObject* parent, const char* name = 0 );
+
+ /**
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KSelectAction( QObject* parent = 0, const char* name = 0 );
+
+ /**
+ * Destructor
+ */
+ virtual ~KSelectAction();
+
+ /**
+ * "Plug" or insert this action into a given widget.
+ *
+ * This will typically be a menu or a toolbar.
+ * From this point on, you will never need to directly
+ * manipulate the item in the menu or toolbar.
+ * You do all enabling/disabling/manipulation directly with your KSelectAction object.
+ *
+ * @param widget The GUI element to display this action.
+ * @param index The index of the item.
+ */
+ virtual int plug( QWidget* widget, int index = -1 );
+
+ /**
+ * When this action is plugged into a toolbar, it creates a combobox.
+ * @return true if the combo editable.
+ */
+ virtual bool isEditable() const;
+
+ /**
+ * @return the items that can be selected with this action.
+ * Use setItems to set them.
+ */
+ virtual QStringList items() const;
+
+ /**
+ * Changes the text of item @param index to @param text .
+ */
+ virtual void changeItem( int index, const QString& text );
+
+ /**
+ * Returns the text of the currently selected item.
+ */
+ virtual QString currentText() const;
+
+ /**
+ * Returns the index of the current item.
+ * @see setCurrentItem
+ */
+ virtual int currentItem() const;
+
+ /**
+ * When this action is plugged into a toolbar, it creates a combobox.
+ * This returns the maximum width set by setComboWidth
+ */
+ virtual int comboWidth() const;
+
+ /**
+ * Sets the maximum items that are visible at once if the action
+ * is a combobox, that is the number of items in the combobox's viewport
+ * Only works before the action is plugged
+ * @since 3.5
+ */
+ void setMaxComboViewCount( int n );
+
+ /**
+ * Returns a pointer to the popup menu used by this action.
+ */
+ QPopupMenu* popupMenu() const;
+
+ /**
+ * @deprecated See setMenuAccelsEnabled .
+ * @since 3.1
+ */
+ void setRemoveAmpersandsInCombo( bool b ) KDE_DEPRECATED;
+ /// @since 3.1
+ bool removeAmpersandsInCombo() const;
+
+ /**
+ * Sets whether any occurrence of the ampersand character ( &amp; ) in items
+ * should be interpreted as keyboard accelerator for items displayed in a
+ * menu or not.
+ * @since 3.1
+ */
+ void setMenuAccelsEnabled( bool b );
+ /// @since 3.1
+ bool menuAccelsEnabled() const;
+
+ virtual bool isShortcutConfigurable() const { return false; }
+
+public slots:
+ /**
+ * Sets the currently checked item.
+ *
+ * @param index Index of the item (remember the first item is zero).
+ */
+ virtual void setCurrentItem( int index );
+
+ /**
+ * Sets the items to be displayed in this action
+ * You need to call this.
+ */
+ virtual void setItems( const QStringList &lst );
+
+ /**
+ * Clears up all the items in this action
+ */
+ virtual void clear();
+
+ /**
+ * When this action is plugged into a toolbar, it creates a combobox.
+ * This makes the combo editable or read-only.
+ */
+ virtual void setEditable( bool );
+
+ /**
+ * When this action is plugged into a toolbar, it creates a combobox.
+ * This gives a _maximum_ size to the combobox.
+ * The minimum size is automatically given by the contents (the items).
+ */
+ virtual void setComboWidth( int width );
+
+protected:
+ virtual void changeItem( int id, int index, const QString& text );
+
+ /**
+ * Depending on the menuAccelsEnabled property this method will return the
+ * actions items in a way for inclusion in a combobox with the ampersand
+ * character removed from all items or not.
+ * @since 3.1
+ */
+ QStringList comboItems() const;
+
+protected slots:
+ virtual void slotActivated( int id );
+ virtual void slotActivated( const QString &text );
+ virtual void slotActivated();
+
+signals:
+ /**
+ * This signal is emitted when an item is selected; @param index indicated
+ * the item selected.
+ */
+ void activated( int index );
+ /**
+ * This signal is emitted when an item is selected; @param text indicates
+ * the item selected.
+ */
+ void activated( const QString& text );
+
+protected:
+ virtual void updateCurrentItem( int id );
+
+ virtual void updateComboWidth( int id );
+
+ virtual void updateItems( int id );
+
+ virtual void updateClear( int id );
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ void setupMenu() const;
+ class KSelectActionPrivate;
+ KSelectActionPrivate *d;
+
+};
+
+/// Remove this class in KDE-4.0. It doesn't add _anything_ to KSelectAction
+/**
+ * @deprecated Use KSelectAction instead.
+ */
+class KDEUI_EXPORT_DEPRECATED KListAction : public KSelectAction
+{
+ Q_OBJECT
+public:
+ /**
+ * Constructs a list action with text and potential keyboard
+ * accelerator but nothing else. Use this only if you really
+ * know what you are doing.
+ *
+ * @param text The text that will be displayed.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KListAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0,
+ const char* name = 0 );
+
+ /**
+ * @param text The text that will be displayed.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param receiver The SLOT's parent.
+ * @param slot The SLOT to invoke to execute this action.
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KListAction( const QString& text, const KShortcut& cut, const QObject* receiver,
+ const char* slot, QObject* parent, const char* name = 0 );
+
+ /**
+ * @param text The text that will be displayed.
+ * @param pix The icons that go with this action.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KListAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(),
+ QObject* parent = 0, const char* name = 0 );
+
+ /**
+ * @param text The text that will be displayed.
+ * @param pix The dynamically loaded icon that goes with this action.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KListAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(),
+ QObject* parent = 0, const char* name = 0 );
+
+ /**
+ * @param text The text that will be displayed.
+ * @param pix The icons that go with this action.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param receiver The SLOT's parent.
+ * @param slot The SLOT to invoke to execute this action.
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KListAction( const QString& text, const QIconSet& pix, const KShortcut& cut,
+ const QObject* receiver, const char* slot, QObject* parent,
+ const char* name = 0 );
+
+ /**
+ * @param text The text that will be displayed.
+ * @param pix The dynamically loaded icon that goes with this action.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param receiver The SLOT's parent.
+ * @param slot The SLOT to invoke to execute this action.
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KListAction( const QString& text, const QString& pix, const KShortcut& cut,
+ const QObject* receiver, const char* slot, QObject* parent,
+ const char* name = 0 );
+
+ /**
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KListAction( QObject* parent = 0, const char* name = 0 );
+
+ /**
+ * Destructor
+ */
+ virtual ~KListAction();
+
+
+ virtual QString currentText() const;
+ virtual int currentItem() const;
+
+
+public slots:
+ /**
+ * Sets the currently checked item.
+ *
+ * @param index Index of the item (remember the first item is zero).
+ */
+ virtual void setCurrentItem( int index );
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KListActionPrivate;
+ KListActionPrivate *d;
+};
+
+/**
+ * @short Recent files action
+ *
+ * This class is an action to handle a recent files submenu.
+ * The best way to create the action is to use KStdAction::openRecent.
+ * Then you simply need to call loadEntries on startup, saveEntries
+ * on shutdown, addURL when your application loads/saves a file.
+ *
+ * @author Michael Koch
+ */
+class KDEUI_EXPORT KRecentFilesAction : public KListAction // TODO public KSelectAction
+{
+ Q_OBJECT
+ Q_PROPERTY( uint maxItems READ maxItems WRITE setMaxItems )
+public:
+ /**
+ * @param text The text that will be displayed.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ * @param maxItems The maximum number of files to display
+ */
+ KRecentFilesAction( const QString& text, const KShortcut& cut,
+ QObject* parent, const char* name = 0,
+ uint maxItems = 10 );
+
+ /**
+ * @param text The text that will be displayed.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param receiver The SLOT's parent.
+ * @param slot The SLOT to invoke when a URL is selected.
+ * Its signature is of the form slotURLSelected( const KURL & ).
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ * @param maxItems The maximum number of files to display
+ */
+ KRecentFilesAction( const QString& text, const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ QObject* parent, const char* name = 0,
+ uint maxItems = 10 );
+
+ /**
+ * @param text The text that will be displayed.
+ * @param pix The icons that go with this action.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ * @param maxItems The maximum number of files to display
+ */
+ KRecentFilesAction( const QString& text, const QIconSet& pix, const KShortcut& cut,
+ QObject* parent, const char* name = 0,
+ uint maxItems = 10 );
+
+ /**
+ * @param text The text that will be displayed.
+ * @param pix The dynamically loaded icon that goes with this action.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ * @param maxItems The maximum number of files to display
+ */
+ KRecentFilesAction( const QString& text, const QString& pix, const KShortcut& cut,
+ QObject* parent, const char* name = 0,
+ uint maxItems = 10 );
+
+ /**
+ * @param text The text that will be displayed.
+ * @param pix The icons that go with this action.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param receiver The SLOT's parent.
+ * @param slot The SLOT to invoke when a URL is selected.
+ * Its signature is of the form slotURLSelected( const KURL & ).
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ * @param maxItems The maximum number of files to display
+ */
+ KRecentFilesAction( const QString& text, const QIconSet& pix, const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ QObject* parent, const char* name = 0,
+ uint maxItems = 10 );
+
+ /**
+ * @param text The text that will be displayed.
+ * @param pix The dynamically loaded icon that goes with this action.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param receiver The SLOT's parent.
+ * @param slot The SLOT to invoke when a URL is selected.
+ * Its signature is of the form slotURLSelected( const KURL & ).
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ * @param maxItems The maximum number of files to display
+ */
+ KRecentFilesAction( const QString& text, const QString& pix, const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ QObject* parent, const char* name = 0,
+ uint maxItems = 10 );
+
+ /**
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ * @param maxItems The maximum number of files to display
+ */
+ KRecentFilesAction( QObject* parent = 0, const char* name = 0,
+ uint maxItems = 10 );
+
+ /**
+ * Destructor.
+ */
+ virtual ~KRecentFilesAction();
+
+ virtual int plug( QWidget *widget, int index = -1 );
+
+ /**
+ * Returns the maximum of items in the recent files list.
+ */
+ uint maxItems() const;
+
+//KDE4: remove completeItems() and rename items() to urls(), to get the list of URLs added to
+// the action.
+ /**
+ * @return the items that can be selected with this action.
+ * The returned items do not contain the pretty name that can be set by addURL,
+ * matching the pre-3.5 behavior.
+ */
+
+ virtual QStringList items() const;
+
+ /**
+ * @return the items that can be selected with this action.
+ * The returned items contain the pretty name that can be set by addURL.
+ * @since 3.5
+ */
+ QStringList completeItems() const;
+
+public slots:
+ /**
+ * Sets the maximum of items in the recent files list.
+ * The default for this value is 10 set in the constructor.
+ *
+ * If this value is lesser than the number of items currently
+ * in the recent files list the last items are deleted until
+ * the number of items are equal to the new maximum.
+ */
+ void setMaxItems( uint maxItems );
+
+ /**
+ * Loads the recent files entries from a given KConfig object.
+ * You can provide the name of the group used to load the entries.
+ * If the groupname is empty, entries are load from a group called 'RecentFiles'
+ *
+ * This method does not effect the active group of KConfig.
+ */
+ void loadEntries( KConfig* config, QString groupname=QString::null );
+
+ /**
+ * Saves the current recent files entries to a given KConfig object.
+ * You can provide the name of the group used to load the entries.
+ * If the groupname is empty, entries are saved to a group called 'RecentFiles'
+ *
+ * This method does not effect the active group of KConfig.
+ */
+ void saveEntries( KConfig* config, QString groupname=QString::null );
+
+ /**
+ * Add URL to recent files list.
+ *
+ * @param url The URL of the file
+ */
+ void addURL( const KURL& url );
+
+ /**
+ * Add URL to recent files list.
+ *
+ * @param url The URL of the file
+ * @param name The user visible pretty name that appears before the URL
+ * @since 3.5
+ */
+ void addURL( const KURL& url, const QString& name ); //KDE4: Combine the above two methods
+
+ /**
+ * Remove an URL from the recent files list.
+ *
+ * @param url The URL of the file
+ */
+ void removeURL( const KURL& url );
+
+ /**
+ * Removes all entries from the recent files list.
+ */
+ void clearURLList();
+
+signals:
+
+ /**
+ * This signal gets emited when the user selects an URL.
+ *
+ * @param url The URL thats the user selected.
+ */
+ void urlSelected( const KURL& url );
+
+protected slots:
+ void itemSelected( const QString& string );
+ void menuAboutToShow();
+ void menuItemActivated( int id );
+ void slotClicked();
+ virtual void slotActivated(int);
+ virtual void slotActivated(const QString& );
+ virtual void slotActivated();
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+
+private:
+ void init();
+
+ class KRecentFilesActionPrivate;
+ KRecentFilesActionPrivate *d;
+};
+
+class KDEUI_EXPORT KFontAction : public KSelectAction
+{
+ Q_OBJECT
+ Q_PROPERTY( QString font READ font WRITE setFont )
+public:
+ KFontAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0,
+ const char* name = 0 );
+ KFontAction( const QString& text, const KShortcut& cut,
+ const QObject* receiver, const char* slot, QObject* parent,
+ const char* name = 0 );
+ KFontAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(),
+ QObject* parent = 0, const char* name = 0 );
+ KFontAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(),
+ QObject* parent = 0, const char* name = 0 );
+ KFontAction( const QString& text, const QIconSet& pix, const KShortcut& cut,
+ const QObject* receiver, const char* slot, QObject* parent,
+ const char* name = 0 );
+ KFontAction( const QString& text, const QString& pix, const KShortcut& cut,
+ const QObject* receiver, const char* slot, QObject* parent,
+ const char* name = 0 );
+
+// The ctors with fontListCriteria were added after 3.3-beta1.
+// This define is used in koffice. Remove when koffice has a dependency on kdelibs-3.3 or more.
+#define KFONTACTION_HAS_CRITERIA_ARG
+ KFontAction( uint fontListCriteria, const QString& text,
+ const KShortcut& cut = KShortcut(), QObject* parent = 0,
+ const char* name = 0 );
+ KFontAction( uint fontListCriteria, const QString& text, const QString& pix,
+ const KShortcut& cut = KShortcut(),
+ QObject* parent = 0, const char* name = 0 );
+
+ KFontAction( QObject* parent = 0, const char* name = 0 );
+ ~KFontAction();
+
+ QString font() const {
+ return currentText();
+ }
+
+ int plug( QWidget*widget, int index = -1 );
+
+public slots:
+ void setFont( const QString &family );
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KFontActionPrivate;
+ KFontActionPrivate *d;
+};
+
+class KDEUI_EXPORT KFontSizeAction : public KSelectAction
+{
+ Q_OBJECT
+ Q_PROPERTY( int fontSize READ fontSize WRITE setFontSize )
+public:
+ KFontSizeAction( const QString& text, const KShortcut& cut = KShortcut(), QObject* parent = 0,
+ const char* name = 0 );
+ KFontSizeAction( const QString& text, const KShortcut& cut, const QObject* receiver,
+ const char* slot, QObject* parent, const char* name = 0 );
+ KFontSizeAction( const QString& text, const QIconSet& pix, const KShortcut& cut = KShortcut(),
+ QObject* parent = 0, const char* name = 0 );
+ KFontSizeAction( const QString& text, const QString& pix, const KShortcut& cut = KShortcut(),
+ QObject* parent = 0, const char* name = 0 );
+ KFontSizeAction( const QString& text, const QIconSet& pix, const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ QObject* parent, const char* name = 0 );
+ KFontSizeAction( const QString& text, const QString& pix, const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ QObject* parent, const char* name = 0 );
+ KFontSizeAction( QObject* parent = 0, const char* name = 0 );
+
+ virtual ~KFontSizeAction();
+
+ virtual int fontSize() const;
+
+public slots:
+ virtual void setFontSize( int size );
+
+protected slots:
+ virtual void slotActivated( int );
+ virtual void slotActivated( const QString& );
+ virtual void slotActivated() { KAction::slotActivated(); }
+
+signals:
+ void fontSizeChanged( int );
+
+private:
+ void init();
+
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KFontSizeActionPrivate;
+ KFontSizeActionPrivate *d;
+};
+
+
+/**
+ * A KActionMenu is an action that holds a sub-menu of other actions.
+ * insert() and remove() allow to insert and remove actions into this action-menu.
+ * Plugged in a popupmenu, it will create a submenu.
+ * Plugged in a toolbar, it will create a button with a popup menu.
+ *
+ * This is the action used by the XMLGUI since it holds other actions.
+ * If you want a submenu for selecting one tool among many (without icons), see KSelectAction.
+ * See also setDelayed about the main action.
+ */
+class KDEUI_EXPORT KActionMenu : public KAction
+{
+ Q_OBJECT
+ Q_PROPERTY( bool delayed READ delayed WRITE setDelayed )
+ Q_PROPERTY( bool stickyMenu READ stickyMenu WRITE setStickyMenu )
+
+public:
+ KActionMenu( const QString& text, QObject* parent = 0,
+ const char* name = 0 );
+ KActionMenu( const QString& text, const QIconSet& icon,
+ QObject* parent = 0, const char* name = 0 );
+ KActionMenu( const QString& text, const QString& icon,
+ QObject* parent = 0, const char* name = 0 );
+ KActionMenu( QObject* parent = 0, const char* name = 0 );
+ virtual ~KActionMenu();
+
+ virtual void insert( KAction*, int index = -1 );
+ virtual void remove( KAction* );
+
+ KPopupMenu* popupMenu() const;
+ void popup( const QPoint& global );
+
+ /**
+ * Returns true if this action creates a delayed popup menu
+ * when plugged in a KToolbar.
+ */
+ bool delayed() const;
+ /**
+ * If set to true, this action will create a delayed popup menu
+ * when plugged in a KToolbar. Otherwise it creates a normal popup.
+ * Default: delayed
+ *
+ * Remember that if the "main" action (the toolbar button itself)
+ * cannot be clicked, then you should call setDelayed(false).
+ *
+ * On the opposite, if the main action can be clicked, it can only happen
+ * in a toolbar: in a menu, the parent of a submenu can't be activated.
+ * To get a "normal" menu item when plugged a menu (and no submenu)
+ * use KToolBarPopupAction.
+ */
+ void setDelayed(bool _delayed);
+
+ /**
+ * Returns true if this action creates a sticky popup menu.
+ * See setStickyMenu().
+ */
+ bool stickyMenu() const;
+ /**
+ * If set to true, this action will create a sticky popup menu
+ * when plugged in a KToolbar.
+ * "Sticky", means it's visible until a selection is made or the mouse is
+ * clicked elsewhere. This feature allows you to make a selection without
+ * having to press and hold down the mouse while making a selection.
+ * Default: sticky.
+ */
+ void setStickyMenu(bool sticky);
+
+ virtual int plug( QWidget* widget, int index = -1 );
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KActionMenuPrivate;
+ KActionMenuPrivate *d;
+};
+
+/**
+ * This action is a normal action everywhere, except in a toolbar
+ * where it also has a popupmenu (optionnally delayed). This action is designed
+ * for history actions (back/forward, undo/redo) and for any other action
+ * that has more detail in a toolbar than in a menu (e.g. tool chooser
+ * with "Other" leading to a dialog...).
+ */
+class KDEUI_EXPORT KToolBarPopupAction : public KAction
+{
+ Q_OBJECT
+ Q_PROPERTY( bool delayed READ delayed WRITE setDelayed )
+ Q_PROPERTY( bool stickyMenu READ stickyMenu WRITE setStickyMenu )
+
+public:
+ //Not all constructors - because we need an icon, since this action only makes
+ // sense when being plugged at least in a toolbar.
+ /**
+ * Create a KToolBarPopupAction, with a text, an icon, an optional accelerator,
+ * parent and name.
+ *
+ * @param text The text that will be displayed.
+ * @param icon The icon to display.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KToolBarPopupAction( const QString& text, const QString& icon, const KShortcut& cut = KShortcut(),
+ QObject* parent = 0, const char* name = 0 );
+
+ /**
+ * Create a KToolBarPopupAction, with a text, an icon, an accelerator,
+ * a slot connected to the action, parent and name.
+ *
+ * If you do not want or have a keyboard accelerator, set the
+ * @p cut param to 0.
+ *
+ * @param text The text that will be displayed.
+ * @param icon The icon to display.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param receiver The SLOT's owner.
+ * @param slot The SLOT to invoke to execute this action.
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KToolBarPopupAction( const QString& text, const QString& icon, const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ QObject* parent = 0, const char* name = 0 );
+
+ /**
+ * Create a KToolBarPopupAction, with a KGuiItem, an accelerator,
+ * a slot connected to the action, parent and name. The text and the
+ * icon are taken from the KGuiItem.
+ *
+ * If you do not want or have a keyboard accelerator, set the
+ * @p cut param to 0.
+ *
+ * @param item The text and icon that will be displayed.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param receiver The SLOT's owner.
+ * @param slot The SLOT to invoke to execute this action.
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KToolBarPopupAction( const KGuiItem& item, const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ KActionCollection* parent, const char* name );
+
+ virtual ~KToolBarPopupAction();
+
+ virtual int plug( QWidget *widget, int index = -1 );
+
+ /**
+ * The popup menu that is shown when clicking (some time) on the toolbar
+ * button. You may want to plug items into it on creation, or connect to
+ * aboutToShow for a more dynamic menu.
+ */
+ KPopupMenu *popupMenu() const;
+
+ /**
+ * Returns true if this action creates a delayed popup menu
+ * when plugged in a KToolbar.
+ */
+ bool delayed() const;
+ /**
+ * If set to true, this action will create a delayed popup menu
+ * when plugged in a KToolbar. Otherwise it creates a normal popup.
+ * Default: delayed.
+ */
+ void setDelayed(bool delayed);
+ /**
+ * Returns true if this action creates a sticky popup menu.
+ * See setStickyMenu().
+ */
+ bool stickyMenu() const;
+ /**
+ * If set to true, this action will create a sticky popup menu
+ * when plugged in a KToolbar.
+ * "Sticky", means it's visible until a selection is made or the mouse is
+ * clicked elsewhere. This feature allows you to make a selection without
+ * having to press and hold down the mouse while making a selection.
+ * Only available if delayed() is true.
+ * Default: sticky.
+ */
+ void setStickyMenu(bool sticky);
+
+private:
+ KPopupMenu *m_popup;
+ bool m_delayed:1;
+ bool m_stickyMenu:1;
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KToolBarPopupActionPrivate;
+ KToolBarPopupActionPrivate *d;
+};
+
+/**
+ * An action that takes care of everything associated with
+ * showing or hiding a toolbar by a menu action. It will
+ * show or hide the toolbar with the given name when
+ * activated, and check or uncheck itself if the toolbar
+ * is manually shown or hidden.
+ *
+ * If you need to perfom some additional action when the
+ * toolbar is shown or hidden, connect to the toggled(bool)
+ * signal. It will be emitted after the toolbar's
+ * visibility has changed, whenever it changes.
+ * @since 3.1
+ */
+class KDEUI_EXPORT KToggleToolBarAction : public KToggleAction
+{
+ Q_OBJECT
+public:
+ /**
+ * Create a KToggleToolbarAction that manages the toolbar
+ * named toolBarName. This can be either the name of a
+ * toolbar in an xml ui file, or a toolbar programmatically
+ * created with that name.
+ */
+ KToggleToolBarAction( const char* toolBarName, const QString& text,
+ KActionCollection* parent, const char* name );
+ KToggleToolBarAction( KToolBar *toolBar, const QString &text,
+ KActionCollection *parent, const char *name );
+ virtual ~KToggleToolBarAction();
+
+ virtual int plug( QWidget * widget, int index = -1 );
+
+ KToolBar *toolBar() { return m_toolBar; }
+
+public slots:
+ virtual void setChecked( bool );
+
+private:
+ QCString m_toolBarName;
+ QGuardedPtr<KToolBar> m_toolBar;
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KToggleToolBarActionPrivate;
+ KToggleToolBarActionPrivate *d;
+};
+
+/**
+ * An action for switching between to/from full screen mode. Note that
+ * QWidget::isFullScreen() may reflect the new or the old state
+ * depending on how the action was triggered (by the application or
+ * from the window manager). Also don't try to track the window state
+ * yourself. Rely on this action's state (isChecked()) instead.
+ *
+ * Important: If you need to set/change the fullscreen state manually,
+ * use the relevant QWidget function (showFullScreen etc.), do not
+ * call directly the slot connected to the toggled() signal. The slot
+ * still needs to explicitly set the window state though.
+ * @since 3.2
+ */
+class KDEUI_EXPORT KToggleFullScreenAction : public KToggleAction
+{
+ Q_OBJECT
+public:
+ /**
+ * Create a KToggleFullScreenAction
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param receiver The SLOT's parent.
+ * @param slot The SLOT to invoke to execute this action.
+ * @param parent This action's parent.
+ * @param window the window that will switch to/from full screen mode
+ * @param name An internal name for this action.
+ */
+ KToggleFullScreenAction( const KShortcut &cut,
+ const QObject* receiver, const char* slot,
+ QObject* parent, QWidget* window,
+ const char* name );
+ virtual ~KToggleFullScreenAction();
+
+ /**
+ * Sets the window that will be related to this action.
+ */
+ void setWindow( QWidget* window );
+public slots:
+ virtual void setChecked( bool );
+protected:
+ /**
+ * @internal
+ */
+ virtual bool eventFilter( QObject* o, QEvent* e );
+private:
+ QWidget* window;
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KToggleFullScreenActionPrivate;
+ KToggleFullScreenActionPrivate *d;
+};
+
+
+/**
+ * An action that automatically embeds a widget into a
+ * toolbar.
+ */
+class KDEUI_EXPORT KWidgetAction : public KAction
+{
+ Q_OBJECT
+public:
+ /**
+ * Create an action that will embed widget into a toolbar
+ * when plugged. This action may only be plugged into
+ * a toolbar.
+ */
+ KWidgetAction( QWidget* widget, const QString& text,
+ const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ KActionCollection* parent, const char* name );
+ virtual ~KWidgetAction();
+
+ /**
+ * Returns the widget associated with this action.
+ */
+ QWidget* widget() { return m_widget; }
+
+ void setAutoSized( bool );
+
+ /**
+ * Plug the action. The widget passed to the constructor
+ * will be reparented to w, which must inherit KToolBar.
+ */
+ virtual int plug( QWidget* widget, int index = -1 );
+ /**
+ * Unplug the action. Ensures that the action is not
+ * destroyed. It will be hidden and reparented to 0L instead.
+ */
+ virtual void unplug( QWidget *w );
+protected slots:
+ void slotToolbarDestroyed();
+private:
+ QGuardedPtr<QWidget> m_widget;
+ bool m_autoSized;
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KWidgetActionPrivate;
+ KWidgetActionPrivate *d;
+};
+
+class KDEUI_EXPORT KActionSeparator : public KAction
+{
+ Q_OBJECT
+public:
+ KActionSeparator( QObject* parent = 0, const char* name = 0 );
+ virtual ~KActionSeparator();
+
+ virtual int plug( QWidget *widget, int index = -1 );
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KActionSeparatorPrivate;
+ KActionSeparatorPrivate *d;
+};
+
+/**
+ * An action for pasting text from the clipboard.
+ * It's useful for text handling applications as
+ * when plugged into a toolbar it provides a menu
+ * with the clipboard history if klipper is running.
+ * If klipper is not running, the menu has only one
+ * item: the current clipboard content.
+ *
+ * @since 3.2
+ */
+class KDEUI_EXPORT KPasteTextAction: public KAction
+{
+ Q_OBJECT
+public:
+ /**
+ * Create a KPasteTextAction, with a text, an icon, an accelerator,
+ * a slot connected to the action, parent and name.
+ *
+ * If you do not want or have a keyboard accelerator, set the
+ * @p cut param to 0.
+ *
+ * @param text The text that will be displayed.
+ * @param icon The icon to display.
+ * @param cut The corresponding keyboard accelerator (shortcut).
+ * @param receiver The SLOT's owner.
+ * @param slot The SLOT to invoke to execute this action.
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KPasteTextAction( const QString& text, const QString& icon, const KShortcut& cut,
+ const QObject* receiver, const char* slot,
+ QObject* parent = 0, const char* name = 0 );
+
+ virtual ~KPasteTextAction();
+
+ /**
+ * Controls the behavior of the clipboard history menu popup.
+ *
+ * @param mode If false and the clipboard contains a non-text object
+ * the popup menu with the clipboard history will appear
+ * immediately as the user clicks the toolbar action; if
+ * true, the action works like the standard paste action
+ * even if the current clipboard object is not text.
+ * Default value is true.
+ */
+ void setMixedMode(bool mode);
+
+ virtual int plug( QWidget *widget, int index = -1 );
+
+protected slots:
+ void menuAboutToShow();
+ void menuItemActivated( int id);
+ virtual void slotActivated();
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+
+private:
+ KPopupMenu *m_popup;
+ bool m_mixedMode;
+ class KPasteTextActionPrivate;
+ KPasteTextActionPrivate *d;
+};
+
+#endif
diff --git a/kdeui/kactioncollection.cpp b/kdeui/kactioncollection.cpp
new file mode 100644
index 000000000..26a3de9b3
--- /dev/null
+++ b/kdeui/kactioncollection.cpp
@@ -0,0 +1,802 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org>
+ (C) 1999 Simon Hausmann <hausmann@kde.org>
+ (C) 2000 Nicolas Hadacek <haadcek@kde.org>
+ (C) 2000 Kurt Granroth <granroth@kde.org>
+ (C) 2000 Michael Koch <koch@kde.org>
+ (C) 2001 Holger Freyther <freyther@kde.org>
+ (C) 2002 Ellis Whitehead <ellis@kde.org>
+ (C) 2002 Joseph Wenninger <jowenn@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kactioncollection.h"
+#include "kactionshortcutlist.h"
+#include "ktoolbar.h"
+#include "kxmlguifactory.h"
+#include "kxmlguiclient.h"
+
+#include <kaccel.h>
+#include <kaccelbase.h>
+#include <kapplication.h>
+#include <kdebug.h>
+
+#include <qpopupmenu.h>
+#include <qptrdict.h>
+#include <qvariant.h>
+
+class KActionCollection::KActionCollectionPrivate
+{
+public:
+ KActionCollectionPrivate()
+ {
+ m_instance = 0;
+ //m_bOneKAccelOnly = false;
+ //m_iWidgetCurrent = 0;
+ m_bAutoConnectShortcuts = true;
+ m_widget = 0;
+ m_kaccel = m_builderKAccel = 0;
+ m_dctHighlightContainers.setAutoDelete( true );
+ m_highlight = false;
+ m_currentHighlightAction = 0;
+ m_statusCleared = true;
+ m_parentGUIClient = 0L;
+ }
+
+ KInstance *m_instance;
+ QString m_sXMLFile;
+ bool m_bAutoConnectShortcuts;
+ //bool m_bOneKAccelOnly;
+ //int m_iWidgetCurrent;
+ //QValueList<QWidget*> m_widgetList;
+ //QValueList<KAccel*> m_kaccelList;
+ QValueList<KActionCollection*> m_docList;
+ QWidget *m_widget;
+ KAccel *m_kaccel;
+ KAccel *m_builderKAccel;
+
+ QAsciiDict<KAction> m_actionDict;
+ QPtrDict< QPtrList<KAction> > m_dctHighlightContainers;
+ bool m_highlight;
+ KAction *m_currentHighlightAction;
+ bool m_statusCleared;
+ const KXMLGUIClient *m_parentGUIClient;
+};
+
+KActionCollection::KActionCollection( QWidget *parent, const char *name,
+ KInstance *instance )
+ : QObject( parent, name )
+{
+ kdDebug(129) << "KActionCollection::KActionCollection( " << parent << ", " << name << " ): this = " << this << endl; // ellis
+ d = new KActionCollectionPrivate;
+ if( parent )
+ setWidget( parent );
+ //d->m_bOneKAccelOnly = (d->m_kaccelList.count() > 0);
+ setInstance( instance );
+}
+
+
+KActionCollection::KActionCollection( QWidget *watch, QObject* parent, const char *name,
+ KInstance *instance )
+ : QObject( parent, name )
+{
+ kdDebug(129) << "KActionCollection::KActionCollection( " << watch << ", " << parent << ", " << name << " ): this = " << this << endl; //ellis
+ d = new KActionCollectionPrivate;
+ if( watch )
+ setWidget( watch );
+ //d->m_bOneKAccelOnly = (d->m_kaccelList.count() > 0);
+ setInstance( instance );
+}
+
+#ifndef KDE_NO_COMPAT
+// KDE 4: remove
+KActionCollection::KActionCollection( QObject *parent, const char *name,
+ KInstance *instance )
+ : QObject( parent, name )
+{
+ kdWarning(129) << "KActionCollection::KActionCollection( QObject *parent, const char *name, KInstance *instance )" << endl; //ellis
+ kdDebug(129) << kdBacktrace() << endl;
+ d = new KActionCollectionPrivate;
+ QWidget* w = dynamic_cast<QWidget*>( parent );
+ if( w )
+ setWidget( w );
+ //d->m_bOneKAccelOnly = (d->m_kaccelList.count() > 0);
+ setInstance( instance );
+}
+
+KActionCollection::KActionCollection( const KActionCollection &copy )
+ : QObject()
+{
+ kdWarning(129) << "KActionCollection::KActionCollection( const KActionCollection & ): function is severely deprecated." << endl;
+ d = new KActionCollectionPrivate;
+ *this = copy;
+}
+#endif // KDE 4: remove end
+
+KActionCollection::KActionCollection( const char *name, const KXMLGUIClient *parent )
+ : QObject( 0L, name )
+{
+ d = new KActionCollectionPrivate;
+ d->m_parentGUIClient=parent;
+ d->m_instance=parent->instance();
+}
+
+
+KActionCollection::~KActionCollection()
+{
+ kdDebug(129) << "KActionCollection::~KActionCollection(): this = " << this << endl;
+ for ( QAsciiDictIterator<KAction> it( d->m_actionDict ); it.current(); ++it ) {
+ KAction* pAction = it.current();
+ if ( pAction->m_parentCollection == this )
+ pAction->m_parentCollection = 0L;
+ }
+
+ delete d->m_kaccel;
+ delete d->m_builderKAccel;
+ delete d; d = 0;
+}
+
+void KActionCollection::setWidget( QWidget* w )
+{
+ //if ( d->m_actionDict.count() > 0 ) {
+ // kdError(129) << "KActionCollection::setWidget(): must be called before any actions are added to collection!" << endl;
+ // kdDebug(129) << kdBacktrace() << endl;
+ //}
+ //else
+ if ( !d->m_widget ) {
+ d->m_widget = w;
+ d->m_kaccel = new KAccel( w, this, "KActionCollection-KAccel" );
+ }
+ else if ( d->m_widget != w )
+ kdWarning(129) << "KActionCollection::setWidget(): tried to change widget from " << d->m_widget << " to " << w << endl;
+}
+
+void KActionCollection::setAutoConnectShortcuts( bool b )
+{
+ d->m_bAutoConnectShortcuts = b;
+}
+
+bool KActionCollection::isAutoConnectShortcuts()
+{
+ return d->m_bAutoConnectShortcuts;
+}
+
+bool KActionCollection::addDocCollection( KActionCollection* pDoc )
+{
+ d->m_docList.append( pDoc );
+ return true;
+}
+
+void KActionCollection::beginXMLPlug( QWidget *widget )
+{
+ kdDebug(129) << "KActionCollection::beginXMLPlug( buildWidget = " << widget << " ): this = " << this << " d->m_builderKAccel = " << d->m_builderKAccel << endl;
+
+ if( widget && !d->m_builderKAccel ) {
+ d->m_builderKAccel = new KAccel( widget, this, "KActionCollection-BuilderKAccel" );
+ }
+}
+
+void KActionCollection::endXMLPlug()
+{
+ kdDebug(129) << "KActionCollection::endXMLPlug(): this = " << this << endl;
+ //s_kaccelXML = 0;
+}
+
+void KActionCollection::prepareXMLUnplug()
+{
+ kdDebug(129) << "KActionCollection::prepareXMLUnplug(): this = " << this << endl;
+ unplugShortcuts( d->m_kaccel );
+
+ if( d->m_builderKAccel ) {
+ unplugShortcuts( d->m_builderKAccel );
+ delete d->m_builderKAccel;
+ d->m_builderKAccel = 0;
+ }
+}
+
+void KActionCollection::unplugShortcuts( KAccel* kaccel )
+{
+ for ( QAsciiDictIterator<KAction> it( d->m_actionDict ); it.current(); ++it ) {
+ KAction* pAction = it.current();
+ pAction->removeKAccel( kaccel );
+ }
+
+ for( uint i = 0; i < d->m_docList.count(); i++ )
+ d->m_docList[i]->unplugShortcuts( kaccel );
+}
+
+/*void KActionCollection::addWidget( QWidget* w )
+{
+ if( !d->m_bOneKAccelOnly ) {
+ kdDebug(129) << "KActionCollection::addWidget( " << w << " ): this = " << this << endl;
+ for( uint i = 0; i < d->m_widgetList.count(); i++ ) {
+ if( d->m_widgetList[i] == w ) {
+ d->m_iWidgetCurrent = i;
+ return;
+ }
+ }
+ d->m_iWidgetCurrent = d->m_widgetList.count();
+ d->m_widgetList.append( w );
+ d->m_kaccelList.append( new KAccel( w, this, "KActionCollection-KAccel" ) );
+ }
+}
+
+void KActionCollection::removeWidget( QWidget* w )
+{
+ if( !d->m_bOneKAccelOnly ) {
+ kdDebug(129) << "KActionCollection::removeWidget( " << w << " ): this = " << this << endl;
+ for( uint i = 0; i < d->m_widgetList.count(); i++ ) {
+ if( d->m_widgetList[i] == w ) {
+ // Remove KAccel object from children.
+ KAccel* pKAccel = d->m_kaccelList[i];
+ for ( QAsciiDictIterator<KAction> it( d->m_actionDict ); it.current(); ++it ) {
+ KAction* pAction = it.current();
+ if ( pAction->m_parentCollection == this ) {
+ pAction->removeKAccel( pKAccel );
+ }
+ }
+ delete pKAccel;
+
+ d->m_widgetList.remove( d->m_widgetList.at( i ) );
+ d->m_kaccelList.remove( d->m_kaccelList.at( i ) );
+
+ if( d->m_iWidgetCurrent == (int)i )
+ d->m_iWidgetCurrent = -1;
+ else if( d->m_iWidgetCurrent > (int)i )
+ d->m_iWidgetCurrent--;
+ return;
+ }
+ }
+ kdWarning(129) << "KActionCollection::removeWidget( " << w << " ): widget not in list." << endl;
+ }
+}
+
+bool KActionCollection::ownsKAccel() const
+{
+ return d->m_bOneKAccelOnly;
+}
+
+uint KActionCollection::widgetCount() const
+{
+ return d->m_widgetList.count();
+}
+
+const KAccel* KActionCollection::widgetKAccel( uint i ) const
+{
+ return d->m_kaccelList[i];
+}*/
+
+KAccel* KActionCollection::kaccel()
+{
+ //if( d->m_kaccelList.count() > 0 )
+ // return d->m_kaccelList[d->m_iWidgetCurrent];
+ //else
+ // return 0;
+ return d->m_kaccel;
+}
+
+const KAccel* KActionCollection::kaccel() const
+{
+ //if( d->m_kaccelList.count() > 0 )
+ // return d->m_kaccelList[d->m_iWidgetCurrent];
+ //else
+ // return 0;
+ return d->m_kaccel;
+}
+
+// Return the key to use in d->m_actionDict for the given action.
+// Usually name(), except when unnamed.
+static const char* actionDictKey( KAction* action, char* buffer )
+{
+ const char* name = action->name();
+ if( !qstrcmp( name, "unnamed" ) )
+ {
+ sprintf(buffer, "unnamed-%p", (void *)action);
+ return buffer;
+ }
+ return name;
+}
+
+void KActionCollection::_insert( KAction* action )
+{
+ char unnamed_name[100];
+ const char *name = actionDictKey( action, unnamed_name );
+ KAction *a = d->m_actionDict[ name ];
+ if ( a == action )
+ return;
+
+ d->m_actionDict.insert( name, action );
+
+ emit inserted( action );
+}
+
+void KActionCollection::_remove( KAction* action )
+{
+ char unnamed_name[100];
+ const char *name = actionDictKey( action, unnamed_name );
+
+ KAction *a = d->m_actionDict.take( name );
+ if ( !a || a != action )
+ return;
+
+ emit removed( action );
+ // note that we delete the action without its parent collection set to 0.
+ // This triggers kaccel::remove, to remove any shortcut.
+ delete a;
+}
+
+KAction* KActionCollection::_take( KAction* action )
+{
+ char unnamed_name[100];
+ const char *name = actionDictKey( action, unnamed_name );
+
+ KAction *a = d->m_actionDict.take( name );
+ if ( !a || a != action )
+ return 0;
+
+ if ( a->m_parentCollection == this )
+ a->m_parentCollection = 0;
+
+ emit removed( action );
+
+ return a;
+}
+
+void KActionCollection::_clear()
+{
+ QAsciiDictIterator<KAction> it( d->m_actionDict );
+ while ( it.current() )
+ _remove( it.current() );
+}
+
+void KActionCollection::insert( KAction* action ) { _insert( action ); }
+void KActionCollection::remove( KAction* action ) { _remove( action ); }
+KAction* KActionCollection::take( KAction* action ) { return _take( action ); }
+void KActionCollection::clear() { _clear(); }
+KAccel* KActionCollection::accel() { return kaccel(); }
+const KAccel* KActionCollection::accel() const { return kaccel(); }
+KAccel* KActionCollection::builderKAccel() const { return d->m_builderKAccel; }
+
+KAction* KActionCollection::action( const char* name, const char* classname ) const
+{
+ KAction* pAction = 0;
+
+ if ( !classname && name )
+ pAction = d->m_actionDict[ name ];
+
+ else {
+ QAsciiDictIterator<KAction> it( d->m_actionDict );
+ for( ; it.current(); ++it )
+ {
+ if ( ( !name || !strcmp( it.current()->name(), name ) ) &&
+ ( !classname || !strcmp( it.current()->className(), classname ) ) ) {
+ pAction = it.current();
+ break;
+ }
+ }
+ }
+
+ if( !pAction ) {
+ for( uint i = 0; i < d->m_docList.count() && !pAction; i++ )
+ pAction = d->m_docList[i]->action( name, classname );
+ }
+
+ return pAction;
+}
+
+KAction* KActionCollection::action( int index ) const
+{
+ QAsciiDictIterator<KAction> it( d->m_actionDict );
+ it += index;
+ return it.current();
+// return d->m_actions.at( index );
+}
+
+bool KActionCollection::readShortcutSettings( const QString& sConfigGroup, KConfigBase* pConfig )
+{
+ return KActionShortcutList(this).readSettings( sConfigGroup, pConfig );
+}
+
+bool KActionCollection::writeShortcutSettings( const QString& sConfigGroup, KConfigBase* pConfig ) const
+{
+ return KActionShortcutList((KActionCollection*)this).writeSettings( sConfigGroup, pConfig );
+}
+
+uint KActionCollection::count() const
+{
+ return d->m_actionDict.count();
+}
+
+QStringList KActionCollection::groups() const
+{
+ QStringList lst;
+
+ QAsciiDictIterator<KAction> it( d->m_actionDict );
+ for( ; it.current(); ++it )
+ if ( !it.current()->group().isEmpty() && !lst.contains( it.current()->group() ) )
+ lst.append( it.current()->group() );
+
+ return lst;
+}
+
+KActionPtrList KActionCollection::actions( const QString& group ) const
+{
+ KActionPtrList lst;
+
+ QAsciiDictIterator<KAction> it( d->m_actionDict );
+ for( ; it.current(); ++it )
+ if ( it.current()->group() == group )
+ lst.append( it.current() );
+ else if ( it.current()->group().isEmpty() && group.isEmpty() )
+ lst.append( it.current() );
+
+ return lst;
+}
+
+KActionPtrList KActionCollection::actions() const
+{
+ KActionPtrList lst;
+
+ QAsciiDictIterator<KAction> it( d->m_actionDict );
+ for( ; it.current(); ++it )
+ lst.append( it.current() );
+
+ return lst;
+}
+
+void KActionCollection::setInstance( KInstance *instance )
+{
+ if ( instance )
+ d->m_instance = instance;
+ else
+ d->m_instance = KGlobal::instance();
+}
+
+KInstance *KActionCollection::instance() const
+{
+ return d->m_instance;
+}
+
+void KActionCollection::setXMLFile( const QString& sXMLFile )
+{
+ d->m_sXMLFile = sXMLFile;
+}
+
+const QString& KActionCollection::xmlFile() const
+{
+ return d->m_sXMLFile;
+}
+
+void KActionCollection::setHighlightingEnabled( bool enable )
+{
+ d->m_highlight = enable;
+}
+
+bool KActionCollection::highlightingEnabled() const
+{
+ return d->m_highlight;
+}
+
+void KActionCollection::connectHighlight( QWidget *container, KAction *action )
+{
+ if ( !d->m_highlight )
+ return;
+
+ QPtrList<KAction> *actionList = d->m_dctHighlightContainers[ container ];
+
+ if ( !actionList )
+ {
+ actionList = new QPtrList<KAction>;
+
+ if ( ::qt_cast<QPopupMenu *>( container ) )
+ {
+ connect( container, SIGNAL( highlighted( int ) ),
+ this, SLOT( slotMenuItemHighlighted( int ) ) );
+ connect( container, SIGNAL( aboutToHide() ),
+ this, SLOT( slotMenuAboutToHide() ) );
+ }
+ else if ( ::qt_cast<KToolBar *>( container ) )
+ {
+ connect( container, SIGNAL( highlighted( int, bool ) ),
+ this, SLOT( slotToolBarButtonHighlighted( int, bool ) ) );
+ }
+
+ connect( container, SIGNAL( destroyed() ),
+ this, SLOT( slotDestroyed() ) );
+
+ d->m_dctHighlightContainers.insert( container, actionList );
+ }
+
+ actionList->append( action );
+}
+
+void KActionCollection::disconnectHighlight( QWidget *container, KAction *action )
+{
+ if ( !d->m_highlight )
+ return;
+
+ QPtrList<KAction> *actionList = d->m_dctHighlightContainers[ container ];
+
+ if ( !actionList )
+ return;
+
+ actionList->removeRef( action );
+
+ if ( actionList->isEmpty() )
+ d->m_dctHighlightContainers.remove( container );
+}
+
+void KActionCollection::slotMenuItemHighlighted( int id )
+{
+ if ( !d->m_highlight )
+ return;
+
+ if ( d->m_currentHighlightAction )
+ emit actionHighlighted( d->m_currentHighlightAction, false );
+
+ QWidget *container = static_cast<QWidget *>( const_cast<QObject *>( sender() ) );
+
+ d->m_currentHighlightAction = findAction( container, id );
+
+ if ( !d->m_currentHighlightAction )
+ {
+ if ( !d->m_statusCleared )
+ emit clearStatusText();
+ d->m_statusCleared = true;
+ return;
+ }
+
+ d->m_statusCleared = false;
+ emit actionHighlighted( d->m_currentHighlightAction );
+ emit actionHighlighted( d->m_currentHighlightAction, true );
+ emit actionStatusText( d->m_currentHighlightAction->toolTip() );
+}
+
+void KActionCollection::slotMenuAboutToHide()
+{
+ if ( d->m_currentHighlightAction )
+ emit actionHighlighted( d->m_currentHighlightAction, false );
+ d->m_currentHighlightAction = 0;
+
+ if ( !d->m_statusCleared )
+ emit clearStatusText();
+ d->m_statusCleared = true;
+}
+
+void KActionCollection::slotToolBarButtonHighlighted( int id, bool highlight )
+{
+ if ( !d->m_highlight )
+ return;
+
+ QWidget *container = static_cast<QWidget *>( const_cast<QObject *>( sender() ) );
+
+ KAction *action = findAction( container, id );
+
+ if ( !action )
+ {
+ d->m_currentHighlightAction = 0;
+ // use tooltip groups for toolbar status text stuff instead (Simon)
+// emit clearStatusText();
+ return;
+ }
+
+ emit actionHighlighted( action, highlight );
+
+ if ( highlight )
+ d->m_currentHighlightAction = action;
+ else
+ {
+ d->m_currentHighlightAction = 0;
+// emit clearStatusText();
+ }
+}
+
+void KActionCollection::slotDestroyed()
+{
+ d->m_dctHighlightContainers.remove( reinterpret_cast<void *>( const_cast<QObject *>(sender()) ) );
+}
+
+KAction *KActionCollection::findAction( QWidget *container, int id )
+{
+ QPtrList<KAction> *actionList = d->m_dctHighlightContainers[ reinterpret_cast<void *>( container ) ];
+
+ if ( !actionList )
+ return 0;
+
+ QPtrListIterator<KAction> it( *actionList );
+ for (; it.current(); ++it )
+ if ( it.current()->isPlugged( container, id ) )
+ return it.current();
+
+ return 0;
+}
+
+const KXMLGUIClient *KActionCollection::parentGUIClient() const
+{
+ return d->m_parentGUIClient;
+}
+
+#ifndef KDE_NO_COMPAT
+// KDE 4: remove
+KActionCollection KActionCollection::operator+(const KActionCollection &c ) const
+{
+ kdWarning(129) << "KActionCollection::operator+(): function is severely deprecated." << endl;
+ KActionCollection ret( *this );
+
+ QValueList<KAction *> actions = c.actions();
+ QValueList<KAction *>::ConstIterator it = actions.begin();
+ QValueList<KAction *>::ConstIterator end = actions.end();
+ for (; it != end; ++it )
+ ret.insert( *it );
+
+ return ret;
+}
+
+KActionCollection &KActionCollection::operator=( const KActionCollection &copy )
+{
+ kdWarning(129) << "KActionCollection::operator=(): function is severely deprecated." << endl;
+ //d->m_bOneKAccelOnly = copy.d->m_bOneKAccelOnly;
+ //d->m_iWidgetCurrent = copy.d->m_iWidgetCurrent;
+ //d->m_widgetList = copy.d->m_widgetList;
+ //d->m_kaccelList = copy.d->m_kaccelList;
+ d->m_widget = copy.d->m_widget;
+ d->m_kaccel = copy.d->m_kaccel;
+ d->m_actionDict = copy.d->m_actionDict;
+ setInstance( copy.instance() );
+ return *this;
+}
+
+KActionCollection &KActionCollection::operator+=( const KActionCollection &c )
+{
+ kdWarning(129) << "KActionCollection::operator+=(): function is severely deprecated." << endl;
+ QAsciiDictIterator<KAction> it(c.d->m_actionDict);
+ for ( ; it.current(); ++it )
+ insert( it.current() );
+
+ return *this;
+}
+#endif // KDE 4: remove end
+
+//---------------------------------------------------------------------
+// KActionShortcutList
+//---------------------------------------------------------------------
+
+KActionShortcutList::KActionShortcutList( KActionCollection* pColl )
+: m_actions( *pColl )
+ { }
+KActionShortcutList::~KActionShortcutList()
+ { }
+uint KActionShortcutList::count() const
+ { return m_actions.count(); }
+QString KActionShortcutList::name( uint i ) const
+ { return m_actions.action(i)->name(); }
+QString KActionShortcutList::label( uint i ) const
+ { return m_actions.action(i)->text(); }
+QString KActionShortcutList::whatsThis( uint i ) const
+ { return m_actions.action(i)->whatsThis(); }
+const KShortcut& KActionShortcutList::shortcut( uint i ) const
+ { return m_actions.action(i)->shortcut(); }
+const KShortcut& KActionShortcutList::shortcutDefault( uint i ) const
+ { return m_actions.action(i)->shortcutDefault(); }
+bool KActionShortcutList::isConfigurable( uint i ) const
+ { return m_actions.action(i)->isShortcutConfigurable(); }
+bool KActionShortcutList::setShortcut( uint i, const KShortcut& cut )
+ { return m_actions.action(i)->setShortcut( cut ); }
+const KInstance* KActionShortcutList::instance() const
+ { return m_actions.instance(); }
+QVariant KActionShortcutList::getOther( Other, uint ) const
+ { return QVariant(); }
+bool KActionShortcutList::setOther( Other, uint, QVariant )
+ { return false; }
+const KAction *KActionShortcutList::action( uint i) const
+ { return m_actions.action(i); }
+
+bool KActionShortcutList::save() const
+{
+ const KXMLGUIClient* guiClient=m_actions.parentGUIClient();
+ const QString xmlFile=guiClient ? guiClient->xmlFile() : m_actions.xmlFile();
+ kdDebug(129) << "KActionShortcutList::save(): xmlFile = " << xmlFile << endl;
+
+ if( m_actions.xmlFile().isEmpty() )
+ return writeSettings();
+
+ QString attrShortcut = QString::fromLatin1("shortcut");
+ QString attrAccel = QString::fromLatin1("accel"); // Depricated attribute
+
+ // Read XML file
+ QString sXml( KXMLGUIFactory::readConfigFile( xmlFile, false, instance() ) );
+ QDomDocument doc;
+ doc.setContent( sXml );
+
+ // Process XML data
+
+ // Get hold of ActionProperties tag
+ QDomElement elem = KXMLGUIFactory::actionPropertiesElement( doc );
+
+ // now, iterate through our actions
+ uint nSize = count();
+ for( uint i = 0; i < nSize; i++ ) {
+ const QString& sName = name(i);
+
+ bool bSameAsDefault = (shortcut(i) == shortcutDefault(i));
+ //kdDebug(129) << "name = " << sName << " shortcut = " << shortcut(i).toStringInternal() << " def = " << shortcutDefault(i).toStringInternal() << endl;
+
+ // now see if this element already exists
+ // and create it if necessary (unless bSameAsDefault)
+ QDomElement act_elem = KXMLGUIFactory::findActionByName( elem, sName, !bSameAsDefault );
+ if ( act_elem.isNull() )
+ continue;
+
+ act_elem.removeAttribute( attrAccel );
+ if( bSameAsDefault ) {
+ act_elem.removeAttribute( attrShortcut );
+ //kdDebug(129) << "act_elem.attributes().count() = " << act_elem.attributes().count() << endl;
+ if( act_elem.attributes().count() == 1 )
+ elem.removeChild( act_elem );
+ } else {
+ act_elem.setAttribute( attrShortcut, shortcut(i).toStringInternal() );
+ }
+ }
+
+ // Write back to XML file
+ return KXMLGUIFactory::saveConfigFile( doc, guiClient ? guiClient->localXMLFile() : m_actions.xmlFile(), instance() );
+}
+
+//---------------------------------------------------------------------
+// KActionPtrShortcutList
+//---------------------------------------------------------------------
+
+KActionPtrShortcutList::KActionPtrShortcutList( KActionPtrList& list )
+: m_actions( list )
+ { }
+KActionPtrShortcutList::~KActionPtrShortcutList()
+ { }
+uint KActionPtrShortcutList::count() const
+ { return m_actions.count(); }
+QString KActionPtrShortcutList::name( uint i ) const
+ { return m_actions[i]->name(); }
+QString KActionPtrShortcutList::label( uint i ) const
+ { return m_actions[i]->text(); }
+QString KActionPtrShortcutList::whatsThis( uint i ) const
+ { return m_actions[i]->whatsThis(); }
+const KShortcut& KActionPtrShortcutList::shortcut( uint i ) const
+ { return m_actions[i]->shortcut(); }
+const KShortcut& KActionPtrShortcutList::shortcutDefault( uint i ) const
+ { return m_actions[i]->shortcutDefault(); }
+bool KActionPtrShortcutList::isConfigurable( uint i ) const
+ { return m_actions[i]->isShortcutConfigurable(); }
+bool KActionPtrShortcutList::setShortcut( uint i, const KShortcut& cut )
+ { return m_actions[i]->setShortcut( cut ); }
+QVariant KActionPtrShortcutList::getOther( Other, uint ) const
+ { return QVariant(); }
+bool KActionPtrShortcutList::setOther( Other, uint, QVariant )
+ { return false; }
+bool KActionPtrShortcutList::save() const
+ { return false; }
+
+void KActionShortcutList::virtual_hook( int id, void* data )
+{ KShortcutList::virtual_hook( id, data ); }
+
+void KActionPtrShortcutList::virtual_hook( int id, void* data )
+{ KShortcutList::virtual_hook( id, data ); }
+
+void KActionCollection::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+/* vim: et sw=2 ts=2
+ */
+
+#include "kactioncollection.moc"
diff --git a/kdeui/kactioncollection.h b/kdeui/kactioncollection.h
new file mode 100644
index 000000000..cf3c88e81
--- /dev/null
+++ b/kdeui/kactioncollection.h
@@ -0,0 +1,393 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org>
+ (C) 1999 Simon Hausmann <hausmann@kde.org>
+ (C) 2000 Nicolas Hadacek <haadcek@kde.org>
+ (C) 2000 Kurt Granroth <granroth@kde.org>
+ (C) 2000 Michael Koch <koch@kde.org>
+ (C) 2001 Holger Freyther <freyther@kde.org>
+ (C) 2002 Ellis Whitehead <ellis@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __kactioncollection_h__
+#define __kactioncollection_h__
+
+#include <kaction.h>
+
+#include <qkeysequence.h>
+#include <qobject.h>
+#include <qvaluelist.h>
+#include <qguardedptr.h>
+#include <kguiitem.h>
+#include <kshortcut.h>
+#include <kstdaction.h>
+#include <kicontheme.h>
+
+class QMenuBar;
+class QPopupMenu;
+class QComboBox;
+class QPoint;
+class QIconSet;
+class QString;
+class KToolBar;
+
+class KAccel;
+class KAccelActions;
+class KConfig;
+class KConfigBase;
+class KURL;
+class KInstance;
+class KToolBar;
+class KActionCollection;
+class KPopupMenu;
+class KMainWindow;
+class KXMLGUIClient;
+
+typedef QValueList<KAction *> KActionPtrList;
+
+/**
+ * A managed set of KAction objects.
+ *
+ * If you set the tooltips on KActions and want the tooltip to show in statusbar
+ * (recommended) then you will need to connect a couple of the actionclass signals
+ * to the toolbar.
+ * The easiest way of doing this is in your KMainWindow subclass, where you create
+ * a statusbar, do:
+ *
+ * \code
+ * actionCollection()->setHighlightingEnabled(true);
+ * connect(actionCollection(), SIGNAL( actionStatusText( const QString & ) ),
+ * statusBar(), SLOT( message( const QString & ) ) );
+ * connect(actionCollection(), SIGNAL( clearStatusText() ),
+ * statusBar(), SLOT( clear() ) );
+ * \endcode
+ */
+class KDEUI_EXPORT KActionCollection : public QObject
+{
+ friend class KAction;
+ friend class KXMLGUIClient;
+
+ Q_OBJECT
+
+public:
+ KActionCollection( QWidget *parent, const char *name = 0, KInstance *instance = 0 );
+ /**
+ * Use this constructor if you want the collection's actions to restrict
+ * their accelerator keys to @p watch rather than the @p parent. If
+ * you don't require shortcuts, you can pass a null to the @p watch parameter.
+ */
+ KActionCollection( QWidget *watch, QObject* parent, const char *name = 0, KInstance *instance = 0 );
+#ifndef KDE_NO_COMPAT
+ KActionCollection( const KActionCollection &copy );
+#endif
+ virtual ~KActionCollection();
+
+ /**
+ * This sets the widget to which the keyboard shortcuts should be attached.
+ * You only need to call this if a null pointer was passed in the constructor.
+ */
+ virtual void setWidget( QWidget *widget );
+
+ /**
+ * This indicates whether new actions which are created in this collection
+ * should have their keyboard shortcuts automatically connected on
+ * construction. Set to 'false' if you will be loading XML-based settings.
+ * This is automatically done by KParts. The default is 'true'.
+ * @see isAutoConnectShortcuts()
+ */
+ void setAutoConnectShortcuts( bool );
+
+ /**
+ * This indicates whether new actions which are created in this collection
+ * have their keyboard shortcuts automatically connected on
+ * construction.
+ * @see setAutoConnectShortcuts()
+ */
+ bool isAutoConnectShortcuts();
+
+ /**
+ * This sets the default shortcut scope for new actions created in this
+ * collection. The default is ScopeUnspecified. Ideally the default
+ * would have been ScopeWidget, but that would cause some backwards
+ * compatibility problems.
+ */
+ //void setDefaultScope( KAction::Scope );
+
+ /**
+ * Doc/View model. This lets you add the action collection of a document
+ * to a view's action collection.
+ */
+ bool addDocCollection( KActionCollection* pDoc );
+
+ /** Returns the number of widgets which this collection is associated with. */
+ //uint widgetCount() const;
+
+ /**
+ * Returns true if the collection has its own KAccel object. This will be
+ * the case if it was constructed with a valid widget ptr or if setWidget()
+ * was called.
+ */
+ //bool ownsKAccel() const;
+
+ /** @deprecated Deprecated because of ambiguous name. Use kaccel() */
+ virtual KAccel* accel() KDE_DEPRECATED;
+ /** @deprecated Deprecated because of ambiguous name. Use kaccel() */
+ virtual const KAccel* accel() const KDE_DEPRECATED;
+
+ /** Returns the KAccel object of the most recently set widget. */
+ KAccel* kaccel();
+ /** Returns the KAccel object of the most recently set widget. Const version for convenience. */
+ const KAccel* kaccel() const;
+
+ /** @internal, for KAction::kaccelCurrent() */
+ KAccel* builderKAccel() const;
+ /** Returns the KAccel object associated with widget #. */
+ //KAccel* widgetKAccel( uint i );
+ //const KAccel* widgetKAccel( uint i ) const;
+
+ /** Returns the number of actions in the collection */
+ virtual uint count() const;
+ bool isEmpty() const { return (count() == 0); }
+ /**
+ * Return the KAction* at position "index" in the action collection.
+ * @see count()
+ */
+ virtual KAction* action( int index ) const;
+ /**
+ * Find an action (optionally, of a given subclass of KAction) in the action collection.
+ * @param name Name of the KAction.
+ * @param classname Name of the KAction subclass.
+ * @return A pointer to the first KAction in the collection which matches the parameters or
+ * null if nothing matches.
+ */
+ virtual KAction* action( const char* name, const char* classname = 0 ) const;
+
+ /** Returns a list of all the groups of all the KActions in this action collection.
+ * @see KAction::group()
+ * @see KAction::setGroup()
+ */
+ virtual QStringList groups() const;
+ /**
+ * Returns the list of actions in a particular group managed by this action collection.
+ * @param group The name of the group.
+ */
+ virtual KActionPtrList actions( const QString& group ) const;
+ /** Returns the list of actions managed by this action collection. */
+ virtual KActionPtrList actions() const;
+
+ /**
+ * Used for reading shortcut configuration from a non-XML rc file.
+ */
+ bool readShortcutSettings( const QString& sConfigGroup = QString::null, KConfigBase* pConfig = 0 );
+ /**
+ * Used for writing shortcut configuration to a non-XML rc file.
+ */
+ bool writeShortcutSettings( const QString& sConfigGroup = QString::null, KConfigBase* pConfig = 0 ) const;
+
+ void setInstance( KInstance *instance );
+ /** The instance with which this class is associated. */
+ KInstance *instance() const;
+
+ /**
+ * @deprecated
+ */
+ void setXMLFile( const QString& );
+ /**
+ * @deprecated
+ */
+ const QString& xmlFile() const;
+
+ //TODO FOR KDE4 make this default true
+ /**
+ * Enable highlighting notification for specific KActions.
+ * This is false by default, so, by default, the highlighting
+ * signals will not be emitted.
+ *
+ * @see connectHighlight()
+ * @see disconnectHighlight()
+ * @see actionHighlighted()
+ * @see actionHighlighted()
+ * @see highlightingEnabled()
+ */
+ void setHighlightingEnabled( bool enable );
+ /**
+ * Return whether highlighting notifications are enabled.
+ * @see connectHighlight()
+ * @see disconnectHighlight()
+ * @see actionHighlighted()
+ * @see setHighlightingEnabled()
+ * @see actionHighlighted()
+ */
+ bool highlightingEnabled() const;
+
+ /**
+ * Call this function if you want to receive a signal whenever a KAction is highlighted in a menu or a toolbar.
+ * This is only needed if you do not add this action to this container.
+ * You will generally not need to call this function.
+ *
+ * @param container A container in which the KAction is plugged (must inherit QPopupMenu or KToolBar)
+ * @param action The action you are interested in
+ * @see disconnectHighlight()
+ * @see actionHighlighted()
+ * @see setHighlightingEnabled()
+ * @see highlightingEnabled()
+ * @see actionHighlighted()
+ */
+ void connectHighlight( QWidget *container, KAction *action );
+ /**
+ * Disconnect highlight notifications for a particular pair of contianer and action.
+ * This is only needed if you do not add this action to this container.
+ * You will generally not need to call this function.
+ *
+ * @param container A container in which the KAction is plugged (must inherit QPopupMenu or KToolBar)
+ * @param action The action you are interested in
+ * @see connectHighlight()
+ * @see actionHighlighted()
+ * @see setHighlightingEnabled()
+ * @see highlightingEnabled()
+ * @see actionHighlighted()
+ */
+ void disconnectHighlight( QWidget *container, KAction *action );
+
+ /**
+ * The parent KXMLGUIClient, return 0L if not available.
+ */
+ const KXMLGUIClient *parentGUIClient() const;
+
+signals:
+ void inserted( KAction* );
+ void removed( KAction* );
+
+ /** Emitted when @p action is highlighted.
+ * This is only emitted if you have setHighlightingEnabled()
+ * @see connectHighlight()
+ * @see disconnectHighlight()
+ * @see actionHighlighted()
+ * @see setHighlightingEnabled()
+ * @see highlightingEnabled()
+ */
+ void actionHighlighted( KAction *action );
+ /** Emitted when @p action is highlighed or loses highlighting.
+ * This is only emitted if you have setHighlightingEnabled()
+ * @see connectHighlight()
+ * @see disconnectHighlight()
+ * @see actionHighlighted()
+ * @see setHighlightingEnabled()
+ * @see highlightingEnabled()
+ */
+ void actionHighlighted( KAction *action, bool highlight );
+ /** Emitted when an action is highlighted, with text
+ * being the tooltip for the action.
+ * This is only emitted if you have setHighlightingEnabled()
+ *
+ * This is useful to connect to KStatusBar::message(). See
+ * this class overview for more information.
+ *
+ * @see setHighlightingEnabled()
+ */
+ void actionStatusText( const QString &text );
+ /** Emitted when an action loses highlighting.
+ * This is only emitted if you have setHighlightingEnabled()
+ *
+ * @see setHighlightingEnabled()
+ */
+ void clearStatusText();
+
+private:
+ /**
+ * @internal Only to be called by KXMLGUIFactory::addClient().
+ * When actions are being connected, KAction needs to know what
+ * widget it should connect widget-scope actions to, and what
+ * main window it should connect
+ */
+ void beginXMLPlug( QWidget *widget );
+ void endXMLPlug();
+ /** @internal. Only to be called by KXMLGUIFactory::removeClient() */
+ void prepareXMLUnplug();
+ void unplugShortcuts( KAccel* kaccel );
+
+ void _clear();
+ void _insert( KAction* );
+ void _remove( KAction* );
+ KAction* _take( KAction* );
+
+private slots:
+ void slotMenuItemHighlighted( int id );
+ void slotToolBarButtonHighlighted( int id, bool highlight );
+ void slotMenuAboutToHide();
+ void slotDestroyed();
+
+private:
+ KAction *findAction( QWidget *container, int id );
+
+#ifndef KDE_NO_COMPAT
+public:
+ KActionCollection( QObject *parent, const char *name = 0, KInstance *instance = 0 );
+#endif
+
+public:
+ /**
+ * Add an action to the collection.
+ * Generally you don't have to call this. The action inserts itself automatically
+ * into its parent collection. This can be useful however for a short-lived
+ * collection (e.g. for a popupmenu, where the signals from the collection are needed too).
+ * (don't forget that in the simple case, a list of actions should be a simple KActionPtrList).
+ * If you manually insert actions into a 2nd collection, don't forget to take them out
+ * again before destroying the collection.
+ * @param action The KAction to add.
+ */
+ void insert( KAction* action);
+
+ /**
+ * Removes an action from the collection and deletes it.
+ * Since the KAction destructor removes the action from the collection, you generally
+ * don't have to call this.
+ * @param action The KAction to remove.
+ */
+ void remove( KAction* action );
+
+ /**
+ * Removes an action from the collection.
+ * Since the KAction destructor removes the action from the collection, you generally
+ * don't have to call this.
+ * @return NULL if not found else returns action.
+ * @param action the KAction to remove.
+ */
+ KAction* take( KAction* action );
+
+#ifndef KDE_NO_COMPAT
+ KActionCollection operator+ ( const KActionCollection& ) const;
+ KActionCollection& operator= ( const KActionCollection& );
+ KActionCollection& operator+= ( const KActionCollection& );
+#endif // !KDE_NO_COMPAT
+
+ // KDE4: clear() doesn't need to be a slot
+public slots:
+ /**
+ * Clears the entire actionCollection, deleting all actions.
+ * @see remove
+ */
+ void clear();
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KActionCollection( const char* name, const KXMLGUIClient* parent );
+ class KActionCollectionPrivate;
+ KActionCollectionPrivate *d;
+};
+
+#endif
diff --git a/kdeui/kactionselector.cpp b/kdeui/kactionselector.cpp
new file mode 100644
index 000000000..68d1094f4
--- /dev/null
+++ b/kdeui/kactionselector.cpp
@@ -0,0 +1,538 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Anders Lund <anders.lund@lund.tdcadsl.dk>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#include "kactionselector.h"
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kdialog.h> // for spacingHint()
+#include <kdebug.h>
+#include <qapplication.h>
+#include <qlistbox.h>
+#include <qtoolbutton.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qevent.h>
+#include <qwhatsthis.h>
+
+class KActionSelectorPrivate {
+ public:
+ QListBox *availableListBox, *selectedListBox;
+ QToolButton *btnAdd, *btnRemove, *btnUp, *btnDown;
+ QLabel *lAvailable, *lSelected;
+ bool moveOnDoubleClick, keyboardEnabled;
+ KActionSelector::ButtonIconSize iconSize;
+ QString addIcon, removeIcon, upIcon, downIcon;
+ KActionSelector::InsertionPolicy availableInsertionPolicy, selectedInsertionPolicy;
+ bool showUpDownButtons;
+};
+
+//BEGIN Constructor/destructor
+
+KActionSelector::KActionSelector( QWidget *parent, const char *name )
+ : QWidget( parent, name )
+{
+ d = new KActionSelectorPrivate();
+ d->moveOnDoubleClick = true;
+ d->keyboardEnabled = true;
+ d->iconSize = SmallIcon;
+ d->addIcon = QApplication::reverseLayout()? "back" : "forward";
+ d->removeIcon = QApplication::reverseLayout()? "forward" : "back";
+ d->upIcon = "up";
+ d->downIcon = "down";
+ d->availableInsertionPolicy = Sorted;
+ d->selectedInsertionPolicy = BelowCurrent;
+ d->showUpDownButtons = true;
+
+ //int isz = IconSize( KIcon::Small );
+
+ QHBoxLayout *lo = new QHBoxLayout( this );
+ lo->setSpacing( KDialog::spacingHint() );
+
+ QVBoxLayout *loAv = new QVBoxLayout( lo );
+ d->lAvailable = new QLabel( i18n("&Available:"), this );
+ loAv->addWidget( d->lAvailable );
+ d->availableListBox = new QListBox( this );
+ loAv->addWidget( d->availableListBox );
+ d->lAvailable->setBuddy( d->availableListBox );
+
+ QVBoxLayout *loHBtns = new QVBoxLayout( lo );
+ loHBtns->addStretch( 1 );
+ d->btnAdd = new QToolButton( this );
+ loHBtns->addWidget( d->btnAdd );
+ d->btnRemove = new QToolButton( this );
+ loHBtns->addWidget( d->btnRemove );
+ loHBtns->addStretch( 1 );
+
+ QVBoxLayout *loS = new QVBoxLayout( lo );
+ d->lSelected = new QLabel( i18n("&Selected:"), this );
+ loS->addWidget( d->lSelected );
+ d->selectedListBox = new QListBox( this );
+ loS->addWidget( d->selectedListBox );
+ d->lSelected->setBuddy( d->selectedListBox );
+
+ QVBoxLayout *loVBtns = new QVBoxLayout( lo );
+ loVBtns->addStretch( 1 );
+ d->btnUp = new QToolButton( this );
+ d->btnUp->setAutoRepeat( true );
+ loVBtns->addWidget( d->btnUp );
+ d->btnDown = new QToolButton( this );
+ d->btnDown->setAutoRepeat( true );
+ loVBtns->addWidget( d->btnDown );
+ loVBtns->addStretch( 1 );
+
+ loadIcons();
+
+ connect( d->btnAdd, SIGNAL(clicked()), this, SLOT(buttonAddClicked()) );
+ connect( d->btnRemove, SIGNAL(clicked()), this, SLOT(buttonRemoveClicked()) );
+ connect( d->btnUp, SIGNAL(clicked()), this, SLOT(buttonUpClicked()) );
+ connect( d->btnDown, SIGNAL(clicked()), this, SLOT(buttonDownClicked()) );
+ connect( d->availableListBox, SIGNAL(doubleClicked(QListBoxItem*)),
+ this, SLOT(itemDoubleClicked(QListBoxItem*)) );
+ connect( d->selectedListBox, SIGNAL(doubleClicked(QListBoxItem*)),
+ this, SLOT(itemDoubleClicked(QListBoxItem*)) );
+ connect( d->availableListBox, SIGNAL(currentChanged(QListBoxItem*)),
+ this, SLOT(slotCurrentChanged(QListBoxItem *)) );
+ connect( d->selectedListBox, SIGNAL(currentChanged(QListBoxItem*)),
+ this, SLOT(slotCurrentChanged(QListBoxItem *)) );
+
+ d->availableListBox->installEventFilter( this );
+ d->selectedListBox->installEventFilter( this );
+}
+
+KActionSelector::~KActionSelector()
+{
+ delete d;
+}
+
+//END Constructor/destroctor
+
+//BEGIN Public Methods
+
+QListBox *KActionSelector::availableListBox() const
+{
+ return d->availableListBox;
+}
+
+QListBox *KActionSelector::selectedListBox() const
+{
+ return d->selectedListBox;
+}
+
+void KActionSelector::setButtonIcon( const QString &icon, MoveButton button )
+{
+ switch ( button )
+ {
+ case ButtonAdd:
+ d->addIcon = icon;
+ d->btnAdd->setIconSet( SmallIconSet( icon, d->iconSize ) );
+ break;
+ case ButtonRemove:
+ d->removeIcon = icon;
+ d->btnRemove->setIconSet( SmallIconSet( icon, d->iconSize ) );
+ break;
+ case ButtonUp:
+ d->upIcon = icon;
+ d->btnUp->setIconSet( SmallIconSet( icon, d->iconSize ) );
+ break;
+ case ButtonDown:
+ d->downIcon = icon;
+ d->btnDown->setIconSet( SmallIconSet( icon, d->iconSize ) );
+ break;
+ default:
+ kdDebug(13001)<<"KActionSelector::setButtonIcon: DAINBREAD!"<<endl;
+ }
+}
+
+void KActionSelector::setButtonIconSet( const QIconSet &iconset, MoveButton button )
+{
+ switch ( button )
+ {
+ case ButtonAdd:
+ d->btnAdd->setIconSet( iconset );
+ break;
+ case ButtonRemove:
+ d->btnRemove->setIconSet( iconset );
+ break;
+ case ButtonUp:
+ d->btnUp->setIconSet( iconset );
+ break;
+ case ButtonDown:
+ d->btnDown->setIconSet( iconset );
+ break;
+ default:
+ kdDebug(13001)<<"KActionSelector::setButtonIconSet: DAINBREAD!"<<endl;
+ }
+}
+
+void KActionSelector::setButtonTooltip( const QString &tip, MoveButton button )
+{
+ switch ( button )
+ {
+ case ButtonAdd:
+ d->btnAdd->setTextLabel( tip );
+ break;
+ case ButtonRemove:
+ d->btnRemove->setTextLabel( tip );
+ break;
+ case ButtonUp:
+ d->btnUp->setTextLabel( tip );
+ break;
+ case ButtonDown:
+ d->btnDown->setTextLabel( tip );
+ break;
+ default:
+ kdDebug(13001)<<"KActionSelector::setButtonToolTip: DAINBREAD!"<<endl;
+ }
+}
+
+void KActionSelector::setButtonWhatsThis( const QString &text, MoveButton button )
+{
+ switch ( button )
+ {
+ case ButtonAdd:
+ QWhatsThis::add( d->btnAdd, text );
+ break;
+ case ButtonRemove:
+ QWhatsThis::add( d->btnRemove, text );
+ break;
+ case ButtonUp:
+ QWhatsThis::add( d->btnUp, text );
+ break;
+ case ButtonDown:
+ QWhatsThis::add( d->btnDown, text );
+ break;
+ default:
+ kdDebug(13001)<<"KActionSelector::setButtonWhatsThis: DAINBREAD!"<<endl;
+ }
+}
+
+void KActionSelector::setButtonsEnabled()
+{
+ d->btnAdd->setEnabled( d->availableListBox->currentItem() > -1 );
+ d->btnRemove->setEnabled( d->selectedListBox->currentItem() > -1 );
+ d->btnUp->setEnabled( d->selectedListBox->currentItem() > 0 );
+ d->btnDown->setEnabled( d->selectedListBox->currentItem() > -1 &&
+ d->selectedListBox->currentItem() < (int)d->selectedListBox->count() - 1 );
+}
+
+//END Public Methods
+
+//BEGIN Properties
+
+bool KActionSelector::moveOnDoubleClick() const
+{
+ return d->moveOnDoubleClick;
+}
+
+void KActionSelector::setMoveOnDoubleClick( bool b )
+{
+ d->moveOnDoubleClick = b;
+}
+
+bool KActionSelector::keyboardEnabled() const
+{
+ return d->keyboardEnabled;
+}
+
+void KActionSelector::setKeyboardEnabled( bool b )
+{
+ d->keyboardEnabled = b;
+}
+
+QString KActionSelector::availableLabel() const
+{
+ return d->lAvailable->text();
+}
+
+void KActionSelector::setAvailableLabel( const QString &text )
+{
+ d->lAvailable->setText( text );
+}
+
+QString KActionSelector::selectedLabel() const
+{
+ return d->lSelected->text();
+}
+
+void KActionSelector::setSelectedLabel( const QString &text )
+{
+ d->lSelected->setText( text );
+}
+
+KActionSelector::ButtonIconSize KActionSelector::buttonIconSize() const
+{
+ return d->iconSize;
+}
+
+void KActionSelector::setButtonIconSize( ButtonIconSize size )
+{
+ d->iconSize = size;
+ // reload icons
+ loadIcons();
+}
+
+KActionSelector::InsertionPolicy KActionSelector::availableInsertionPolicy() const
+{
+ return d->availableInsertionPolicy;
+}
+
+void KActionSelector::setAvailableInsertionPolicy( InsertionPolicy p )
+{
+ d->availableInsertionPolicy = p;
+}
+
+KActionSelector::InsertionPolicy KActionSelector::selectedInsertionPolicy() const
+{
+ return d->selectedInsertionPolicy;
+}
+
+void KActionSelector::setSelectedInsertionPolicy( InsertionPolicy p )
+{
+ d->selectedInsertionPolicy = p;
+}
+
+bool KActionSelector::showUpDownButtons() const
+{
+ return d->showUpDownButtons;
+}
+
+void KActionSelector::setShowUpDownButtons( bool show )
+{
+ d->showUpDownButtons = show;
+ if ( show )
+ {
+ d->btnUp->show();
+ d->btnDown->show();
+ }
+ else
+ {
+ d->btnUp->hide();
+ d->btnDown->hide();
+ }
+}
+
+//END Properties
+
+//BEGIN Public Slots
+
+void KActionSelector::polish()
+{
+ setButtonsEnabled();
+}
+
+//END Public Slots
+
+//BEGIN Protected
+void KActionSelector::keyPressEvent( QKeyEvent *e )
+{
+ if ( ! d->keyboardEnabled ) return;
+ if ( (e->state() & Qt::ControlButton) )
+ {
+ switch ( e->key() )
+ {
+ case Key_Right:
+ buttonAddClicked();
+ break;
+ case Key_Left:
+ buttonRemoveClicked();
+ break;
+ case Key_Up:
+ buttonUpClicked();
+ break;
+ case Key_Down:
+ buttonDownClicked();
+ break;
+ default:
+ e->ignore();
+ return;
+ }
+ }
+}
+
+bool KActionSelector::eventFilter( QObject *o, QEvent *e )
+{
+ if ( d->keyboardEnabled && e->type() == QEvent::KeyPress )
+ {
+ if ( (((QKeyEvent*)e)->state() & Qt::ControlButton) )
+ {
+ switch ( ((QKeyEvent*)e)->key() )
+ {
+ case Key_Right:
+ buttonAddClicked();
+ break;
+ case Key_Left:
+ buttonRemoveClicked();
+ break;
+ case Key_Up:
+ buttonUpClicked();
+ break;
+ case Key_Down:
+ buttonDownClicked();
+ break;
+ default:
+ return QWidget::eventFilter( o, e );
+ break;
+ }
+ return true;
+ }
+ else if ( o->inherits( "QListBox" ) )
+ {
+ switch ( ((QKeyEvent*)e)->key() )
+ {
+ case Key_Return:
+ case Key_Enter:
+ QListBox *lb = (QListBox*)o;
+ int index = lb->currentItem();
+ if ( index < 0 ) break;
+ moveItem( lb->item( index ) );
+ return true;
+ }
+ }
+ }
+ return QWidget::eventFilter( o, e );
+}
+
+//END Protected
+
+//BEGIN Private Slots
+
+void KActionSelector::buttonAddClicked()
+{
+ // move all selected items from available to selected listbox
+ QListBoxItem *item = d->availableListBox->firstItem();
+ while ( item ) {
+ if ( item->isSelected() ) {
+ d->availableListBox->takeItem( item );
+ d->selectedListBox->insertItem( item, insertionIndex( d->selectedListBox, d->selectedInsertionPolicy ) );
+ d->selectedListBox->setCurrentItem( item );
+ emit added( item );
+ }
+ item = item->next();
+ }
+ if ( d->selectedInsertionPolicy == Sorted )
+ d->selectedListBox->sort();
+ d->selectedListBox->setFocus();
+}
+
+void KActionSelector::buttonRemoveClicked()
+{
+ // move all selected items from selected to available listbox
+ QListBoxItem *item = d->selectedListBox->firstItem();
+ while ( item ) {
+ if ( item->isSelected() ) {
+ d->selectedListBox->takeItem( item );
+ d->availableListBox->insertItem( item, insertionIndex( d->availableListBox, d->availableInsertionPolicy ) );
+ d->availableListBox->setCurrentItem( item );
+ emit removed( item );
+ }
+ item = item->next();
+ }
+ if ( d->availableInsertionPolicy == Sorted )
+ d->availableListBox->sort();
+ d->availableListBox->setFocus();
+}
+
+void KActionSelector::buttonUpClicked()
+{
+ int c = d->selectedListBox->currentItem();
+ if ( c < 1 ) return;
+ QListBoxItem *item = d->selectedListBox->item( c );
+ d->selectedListBox->takeItem( item );
+ d->selectedListBox->insertItem( item, c-1 );
+ d->selectedListBox->setCurrentItem( item );
+ emit movedUp( item );
+}
+
+void KActionSelector::buttonDownClicked()
+{
+ int c = d->selectedListBox->currentItem();
+ if ( c < 0 || c == int( d->selectedListBox->count() ) - 1 ) return;
+ QListBoxItem *item = d->selectedListBox->item( c );
+ d->selectedListBox->takeItem( item );
+ d->selectedListBox->insertItem( item, c+1 );
+ d->selectedListBox->setCurrentItem( item );
+ emit movedDown( item );
+}
+
+void KActionSelector::itemDoubleClicked( QListBoxItem *item )
+{
+ if ( d->moveOnDoubleClick )
+ moveItem( item );
+}
+
+//END Private Slots
+
+//BEGIN Private Methods
+
+void KActionSelector::loadIcons()
+{
+ d->btnAdd->setIconSet( SmallIconSet( d->addIcon, d->iconSize ) );
+ d->btnRemove->setIconSet( SmallIconSet( d->removeIcon, d->iconSize ) );
+ d->btnUp->setIconSet( SmallIconSet( d->upIcon, d->iconSize ) );
+ d->btnDown->setIconSet( SmallIconSet( d->downIcon, d->iconSize ) );
+}
+
+void KActionSelector::moveItem( QListBoxItem *item )
+{
+ QListBox *lbFrom = item->listBox();
+ QListBox *lbTo;
+ if ( lbFrom == d->availableListBox )
+ lbTo = d->selectedListBox;
+ else if ( lbFrom == d->selectedListBox )
+ lbTo = d->availableListBox;
+ else //?! somewhat unlikely...
+ return;
+
+ InsertionPolicy p = ( lbTo == d->availableListBox ) ?
+ d->availableInsertionPolicy : d->selectedInsertionPolicy;
+
+ lbFrom->takeItem( item );
+ lbTo->insertItem( item, insertionIndex( lbTo, p ) );
+ lbTo->setFocus();
+ lbTo->setCurrentItem( item );
+
+ if ( p == Sorted )
+ lbTo->sort();
+ if ( lbTo == d->selectedListBox )
+ emit added( item );
+ else
+ emit removed( item );
+}
+
+int KActionSelector::insertionIndex( QListBox *lb, InsertionPolicy policy )
+{
+ int index;
+ switch ( policy )
+ {
+ case BelowCurrent:
+ index = lb->currentItem();
+ if ( index > -1 ) index += 1;
+ break;
+ case AtTop:
+ index = 0;
+ break;
+ default:
+ index = -1;
+ }
+ return index;
+}
+
+//END Private Methods
+#include "kactionselector.moc"
diff --git a/kdeui/kactionselector.h b/kdeui/kactionselector.h
new file mode 100644
index 000000000..b41412266
--- /dev/null
+++ b/kdeui/kactionselector.h
@@ -0,0 +1,402 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Anders Lund <anders.lund@lund.tdcadsl.dk>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _KACTION_SELECTOR_H_
+#define _KACTION_SELECTOR_H_
+
+#include <qwidget.h>
+
+#include <kdelibs_export.h>
+
+class QListBox;
+class QListBoxItem;
+class QKeyEvent;
+class QEvent;
+class QIconSet;
+
+class KActionSelectorPrivate;
+
+/**
+ @short A widget for selecting and arranging actions/objects
+
+ This widget allows the user to select from a set of objects and arrange
+ the order of the selected ones using two list boxes labeled "Available"
+ and "Used" with horizontal arrows in between to move selected objects between
+ the two, and vertical arrows on the right to arrange the order of the selected
+ objects.
+
+ The widget moves objects to the other listbox when doubleclicked if
+ the property moveOnDoubleClick is set to true (default). See moveOnDoubleClick()
+ and setMoveOnDoubleClick().
+
+ The user control the widget using the keyboard if enabled (default),
+ see keyboardEnabled.
+
+ Note that this may conflist with keyboard selection in the selected list box,
+ if you set that to anything else than QListBox::Single (which is the default).
+
+ To use it, simply construct an instance and then add items to the two listboxes,
+ available through lbAvailable() and lbSelected(). Whenever you want, you can retrieve
+ the selected options using QListBox methods on lbSelected().
+
+ This way, you can use your own QListBoxItem class, allowing you to easily
+ store object data in those.
+
+ When an item is moved to a listbox, it is placed below the current item
+ of that listbox.
+
+ Standard arrow icons are used, but you can use icons of your own choice if desired,
+ see setButtonIcon(). It is also possible to set tooltips and whatsthis help
+ for the buttons. See setButtonTooltip() and setButtonWhatsThis().
+
+ To set whatsthis or tooltips for the listboxes, access them through
+ availableListbox() and selectedListBox().
+
+ All the moving buttons are automatically set enabled as expected.
+
+ Signals are sent each time an item is moved, allowing you to follow the
+ users actions if you need to. See addedToSelection(), removedFromSelection(),
+ movedUp() and movedDown()
+
+ @author Anders Lund <anders@alweb.dk>
+*/
+
+class KDEUI_EXPORT KActionSelector : public QWidget {
+ Q_OBJECT
+ Q_ENUMS( ButtonIconSize InsertionPolicy )
+ Q_PROPERTY( bool moveOnDoubleClick READ moveOnDoubleClick WRITE setMoveOnDoubleClick )
+ Q_PROPERTY( bool keyboardEnabled READ keyboardEnabled WRITE setKeyboardEnabled )
+ Q_PROPERTY( QString availableLabel READ availableLabel WRITE setAvailableLabel )
+ Q_PROPERTY( QString selectedLabel READ selectedLabel WRITE setSelectedLabel )
+ Q_PROPERTY( ButtonIconSize buttonIconSize READ buttonIconSize WRITE setButtonIconSize )
+ Q_PROPERTY( InsertionPolicy availableInsertionPolicy READ availableInsertionPolicy WRITE setAvailableInsertionPolicy )
+ Q_PROPERTY( InsertionPolicy selectedInsertionPolicy READ selectedInsertionPolicy WRITE setSelectedInsertionPolicy )
+ Q_PROPERTY( bool showUpDownButtons READ showUpDownButtons WRITE setShowUpDownButtons )
+
+public:
+ KActionSelector( QWidget *parent=0, const char *name=0 );
+ ~KActionSelector();
+
+ /**
+ @return The QListBox holding the available actions
+ */
+ QListBox *availableListBox() const;
+
+ /**
+ @return The QListBox holding the selected actions
+ */
+ QListBox *selectedListBox() const;
+
+ /**
+ This enum indentifies the moving buttons
+ */
+ enum MoveButton {
+ ButtonAdd,
+ ButtonRemove,
+ ButtonUp,
+ ButtonDown
+ };
+
+ /**
+ This enum identifies the icon sizes, used for the move buttons.
+ The values correspond to the following pixel sizes:
+ @li SmallIcon - the return value of IconSize( KIcon::Small ), the user defined size
+ of a small icon in KDE. This is the default setting.
+ @li Small - 16px
+ @li Medium - 22px
+ @li Large - 32px
+ @li XLarge - 48px
+ */
+ enum ButtonIconSize {
+ SmallIcon,
+ Small,
+ Medium,
+ Large,
+ XLarge
+ };
+
+ /**
+ This enum defines policies for where to insert moved items in a listbox.
+ The following policies are currently defined:
+ @li BelowCurrent - The item is inserted below the listbox'
+ currentItem() or at the end if there is no curent item.
+ @li Sorted - The listbox is sort()ed after one or more items are inserted.
+ @li AtTop - The item is inserted at index 0 in the listbox.
+ @li AtBottom - The item is inserted at the end of the listbox.
+
+ @sa availableInsertionPolicy(), setAvailableInsertionPolicy(),
+ selectedInsertionPolicy(), setSelectedInsertionPolicy().
+ */
+ enum InsertionPolicy {
+ BelowCurrent,
+ Sorted,
+ AtTop,
+ AtBottom
+ };
+
+ /**
+ @return Wheather moveOnDoubleClcik is enabled.
+
+ If enabled, an item in any listbox will be moved to the other one whenever
+ doubleclicked.
+ @sa setMoveOnDoubleClick()
+ */
+ bool moveOnDoubleClick() const;
+
+ /**
+ Sets moveOnDoubleClick to @p enable
+ @sa moveOnDoubleClick()
+ */
+ void setMoveOnDoubleClick( bool enable );
+
+ /**
+ @return Weather keyboard control is enabled.
+
+ When Keyboard control is enabled, the widget will react to
+ the following keyboard actions:
+ @li CTRL + Right - simulate clicking the add button
+ @li CTRL + Left - simulate clicking the remove button
+ @li CTRL + Up - simulate clicking the up button
+ @li CTRL + Down - simulate clicking the down button
+
+ Additionally, pressing RETURN or ENTER on one of the list boxes
+ will cause the current item of that listbox to be moved to the other
+ listbox.
+
+ The keyboard actions are enabled by default.
+
+ @sa setKeyboardEnabled()
+ */
+ bool keyboardEnabled() const;
+
+ /**
+ Sets the keyboard enabled depending on @p enable.
+ @sa keyboardEnabled()
+ */
+ void setKeyboardEnabled( bool enable );
+
+ /**
+ @return The text of the label for the available items listbox.
+ */
+ QString availableLabel() const;
+
+ /**
+ Sets the label for the available items listbox to @p text.
+ Note that this label has the listbox as its @e buddy, so that
+ if you have a single ampersand in the text, the following character
+ will become the accellerator to focus te listbox.
+ */
+ void setAvailableLabel( const QString & text );
+
+ /**
+ @return the label of the selected items listbox.
+ */
+ QString selectedLabel() const;
+
+ /**
+ Sets the label for the selected items listbox to @p text.
+ Note that this label has the listbox as its @e buddy, so that
+ if you have a single ampersand in the text, the following character
+ will become the accellerator to focus te listbox.
+ */
+ void setSelectedLabel( const QString & text );
+
+ /**
+ @return the current ButtonIconSize.
+ */
+ ButtonIconSize buttonIconSize() const;
+
+ /**
+ Sets the button icon size.
+ See ButtonIconSize for the possible values and their pixel meaning.
+ */
+ void setButtonIconSize( ButtonIconSize size );
+
+ /**
+ @return The current insertion policy for the available listbox.
+ The default policy for the available listbox is Sorted.
+ See also InsertionPolicy, setAvailableInsertionPolicy().
+ */
+ InsertionPolicy availableInsertionPolicy() const;
+
+ /**
+ Sets the insertion policy for the available listbox.
+ See also InsertionPolicy, availableInsertionPolicy().
+ */
+ void setAvailableInsertionPolicy( InsertionPolicy policy );
+
+ /**
+ @return The current insertion policy for the selected listbox.
+ The default policy for the selected listbox is BelowCurrent.
+ See also InsertionPolicy, setSelectedInsertionPolicy().
+ */
+ InsertionPolicy selectedInsertionPolicy() const;
+
+ /**
+ Sets the insertion policy for the selected listbox.
+ See also InsertionPolicy, selectedInsertionPolicy().
+ */
+ void setSelectedInsertionPolicy( InsertionPolicy policy );
+
+ /**
+ @return wheather the Up and Down buttons should be displayed.
+ */
+ bool showUpDownButtons() const;
+
+ /**
+ Sets wheather the Up and Down buttons should be displayed
+ according to @p show
+ */
+ void setShowUpDownButtons( bool show );
+
+ /**
+ Sets the pixmap of the button @p button to @p icon.
+ It calls SmallIconSet(pm) to generate the icon set.
+ */
+ void setButtonIcon( const QString &icon, MoveButton button );
+
+ /**
+ Sets the iconset for button @p button to @p iconset.
+ You can use this method to et a costum icon set. Either
+ created by QIconSet, or use the application instance of
+ KIconLoader (recommended).
+ */
+ void setButtonIconSet( const QIconSet &iconset, MoveButton button );
+
+ /**
+ Sets the tooltip for the button @p button to @p tip.
+ */
+ void setButtonTooltip( const QString &tip, MoveButton button );
+
+ /**
+ Sets the whatsthis help for button @p button to @p text.
+ */
+ void setButtonWhatsThis( const QString &text, MoveButton button );
+
+ /**
+ Sets the enabled state of all moving buttons to reflect the current
+ options.
+
+ Be sure to call this if you add or removes items to either listbox after the
+ widget is show()n
+ */
+ void setButtonsEnabled();
+
+signals:
+ /**
+ Emitted when an item is moved to the "selected" listbox.
+ */
+ void added( QListBoxItem *item );
+
+ /**
+ Emitted when an item is moved out of the "selected" listbox.
+ */
+ void removed( QListBoxItem *item );
+
+ /**
+ Emitted when an item is moved upwards in the "selected" listbox.
+ */
+ void movedUp( QListBoxItem *item );
+
+ /**
+ Emitted when an item is moved downwards in the "selected" listbox.
+ */
+ void movedDown( QListBoxItem *item );
+
+ /**
+ Emitted when an item is moved to the "selected" listbox.
+ */
+// void addedToSelection( QListBoxItem *item );
+
+public slots:
+ /**
+ Reimplemented for internal reasons.
+ (calls setButtonsEnabled())
+ */
+ void polish();
+
+protected:
+ /**
+ Reimplamented for internal reasons.
+ */
+ void keyPressEvent( QKeyEvent * );
+
+ /**
+ Reimplemented for internal reasons.
+ */
+ bool eventFilter( QObject *, QEvent * );
+
+private slots:
+ /**
+ Move selected item from available box to the selected box
+ */
+ void buttonAddClicked();
+
+ /**
+ Move selected item from selected box to available box
+ */
+ void buttonRemoveClicked();
+
+ /**
+ Move selected item in selected box upwards
+ */
+ void buttonUpClicked();
+
+ /**
+ Move seleted item in selected box downwards
+ */
+ void buttonDownClicked();
+
+ /**
+ Moves the item @p item to the other listbox if moveOnDoubleClick is enabled.
+ */
+ void itemDoubleClicked( QListBoxItem *item );
+
+ /**
+ connected to both list boxes to set the buttons enabled
+ */
+ void slotCurrentChanged( QListBoxItem * ) { setButtonsEnabled(); }
+
+private:
+
+ /**
+ Move item @p item to the other listbox
+ */
+ void moveItem( QListBoxItem *item );
+
+ /**
+ loads the icons for the move buttons.
+ */
+ void loadIcons();
+
+ /**
+ @return the index to insert an item into listbox @p lb,
+ given InsertionPolicy @p policy.
+
+ Note that if policy is Sorted, this will return -1.
+ Sort the listbox after inserting the item in that case.
+ */
+ int insertionIndex( QListBox *lb, InsertionPolicy policy );
+
+ /** @private
+ Private data storage
+ */
+ KActionSelectorPrivate *d;
+};
+
+#endif // _KACTION_SELECTOR_H_
diff --git a/kdeui/kactionshortcutlist.h b/kdeui/kactionshortcutlist.h
new file mode 100644
index 000000000..322f507d0
--- /dev/null
+++ b/kdeui/kactionshortcutlist.h
@@ -0,0 +1,79 @@
+#ifndef _KACTIONSHORTCUTLIST_H
+#define _KACTIONSHORTCUTLIST_H
+
+#include <kshortcutlist.h>
+#include <kaction.h>
+
+//---------------------------------------------------------------------
+// class KActionShortcutList
+//---------------------------------------------------------------------
+
+class KAccelShortcutListPrivate;
+class KDEUI_EXPORT KActionShortcutList : public KShortcutList
+{
+ public:
+ KActionShortcutList( KActionCollection* );
+ virtual ~KActionShortcutList();
+
+ virtual uint count() const;
+ virtual QString name( uint index ) const;
+ virtual QString label( uint index ) const;
+ virtual QString whatsThis( uint index ) const;
+ virtual const KShortcut& shortcut( uint index ) const;
+ virtual const KShortcut& shortcutDefault( uint index ) const;
+ virtual bool isConfigurable( uint index ) const;
+ virtual bool setShortcut( uint index, const KShortcut& shortcut );
+
+ virtual const KInstance* instance() const;
+
+ virtual QVariant getOther( Other, uint index ) const;
+ virtual bool setOther( Other, uint index, QVariant );
+
+ virtual bool save() const;
+
+ const KAction *action( uint ) const;
+
+ protected:
+ KActionCollection& m_actions;
+
+ protected:
+ virtual void virtual_hook( int id, void* data );
+ private:
+ KAccelShortcutListPrivate* d;
+};
+
+//---------------------------------------------------------------------
+// class KActionPtrShortcutList
+//---------------------------------------------------------------------
+
+class KAccelShortcutListPrivate;
+class KDEUI_EXPORT KActionPtrShortcutList : public KShortcutList
+{
+ public:
+ KActionPtrShortcutList( KActionPtrList& );
+ virtual ~KActionPtrShortcutList();
+
+ virtual uint count() const;
+ virtual QString name( uint index ) const;
+ virtual QString label( uint index ) const;
+ virtual QString whatsThis( uint index ) const;
+ virtual const KShortcut& shortcut( uint index ) const;
+ virtual const KShortcut& shortcutDefault( uint index ) const;
+ virtual bool isConfigurable( uint index ) const;
+ virtual bool setShortcut( uint index, const KShortcut& shortcut);
+
+ virtual QVariant getOther( Other, uint index ) const;
+ virtual bool setOther( Other, uint index, QVariant );
+
+ virtual bool save() const;
+
+ protected:
+ KActionPtrList& m_actions;
+
+ protected:
+ virtual void virtual_hook( int id, void* data );
+ private:
+ KAccelShortcutListPrivate* d;
+};
+
+#endif // !_KACTIONSHORTCUTLIST_H
diff --git a/kdeui/kactivelabel.cpp b/kdeui/kactivelabel.cpp
new file mode 100644
index 000000000..5efdea418
--- /dev/null
+++ b/kdeui/kactivelabel.cpp
@@ -0,0 +1,142 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Waldo Bastian (bastian@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; version 2
+ of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kactivelabel.h"
+
+#include <kapplication.h>
+#include <qregexp.h>
+#include <qwhatsthis.h>
+#include <qsimplerichtext.h>
+#include <kdebug.h>
+
+KActiveLabel::KActiveLabel(QWidget * parent, const char * name)
+ : QTextBrowser(parent, name)
+{
+ init();
+}
+
+KActiveLabel::KActiveLabel(const QString &text, QWidget * parent, const char * name)
+ : QTextBrowser(parent, name)
+{
+ init();
+ setText(text);
+}
+
+void KActiveLabel::init()
+{
+ setTextFormat(Qt::RichText);
+ setVScrollBarMode(QScrollView::AlwaysOff);
+ setHScrollBarMode(QScrollView::AlwaysOff);
+ setFrameStyle(QFrame::NoFrame);
+ setFocusPolicy( QWidget::TabFocus );
+ paletteChanged();
+
+ connect(this, SIGNAL(linkClicked(const QString &)),
+ this, SLOT(openLink(const QString &)));
+ if (kapp)
+ {
+ connect(kapp, SIGNAL(kdisplayPaletteChanged()),
+ this, SLOT(paletteChanged()));
+ }
+}
+
+void KActiveLabel::paletteChanged()
+{
+ QPalette p = kapp ? kapp->palette() : palette();
+ p.setBrush(QColorGroup::Base, p.brush(QPalette::Normal, QColorGroup::Background));
+ p.setColor(QColorGroup::Text, p.color(QPalette::Normal, QColorGroup::Foreground));
+ setPalette(p);
+}
+
+void KActiveLabel::openLink(const QString & link)
+{
+ QRegExp whatsthis("whatsthis:/*([^/].*)");
+ if (whatsthis.exactMatch(link)) {
+ QWhatsThis::display(whatsthis.cap(1));
+ return;
+ }
+
+ QStringList args;
+ args << "exec" << link;
+ kapp->kdeinitExec("kfmclient", args);
+}
+
+void KActiveLabel::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void KActiveLabel::focusInEvent( QFocusEvent* fe )
+{
+ QTextBrowser::focusInEvent(fe);
+ if(fe->reason() == QFocusEvent::Tab || fe->reason() == QFocusEvent::Backtab)
+ selectAll(true);
+}
+
+void KActiveLabel::focusOutEvent( QFocusEvent* fe )
+{
+ QTextBrowser::focusOutEvent(fe);
+ if(fe->reason() == QFocusEvent::Tab || fe->reason() == QFocusEvent::Backtab)
+ selectAll(false);
+}
+
+void KActiveLabel::keyPressEvent( QKeyEvent *e )
+{
+ switch ( e->key() )
+ {
+ case Key_Down:
+ case Key_Up:
+ case Key_Left:
+ case Key_Right:
+ // jump over QTextEdit's key navigation breakage.
+ // we're not interested in keyboard navigation within the text
+ QWidget::keyPressEvent( e );
+ break;
+ default:
+ QTextBrowser::keyPressEvent( e );
+ }
+}
+
+QSize KActiveLabel::minimumSizeHint() const
+{
+ QSize ms = minimumSize();
+ if ((ms.width() > 0) && (ms.height() > 0))
+ return ms;
+
+ int w = 400;
+ if (ms.width() > 0)
+ w = ms.width();
+
+ QString txt = text();
+ QSimpleRichText rt(txt, font());
+ rt.setWidth(w - 2*frameWidth() - 10);
+ w = 10 + rt.widthUsed() + 2*frameWidth();
+ if (w < ms.width())
+ w = ms.width();
+ int h = rt.height() + 2*frameWidth();
+ if ( h < ms.height())
+ h = ms.height();
+
+ return QSize(w, h);
+}
+
+QSize KActiveLabel::sizeHint() const
+{
+ return minimumSizeHint();
+}
+
+#include "kactivelabel.moc"
diff --git a/kdeui/kactivelabel.h b/kdeui/kactivelabel.h
new file mode 100644
index 000000000..ad5dd12b5
--- /dev/null
+++ b/kdeui/kactivelabel.h
@@ -0,0 +1,87 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Waldo Bastian (bastian@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; version 2
+ of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef _KACTIVELABEL_H_
+#define _KACTIVELABEL_H_
+
+#include <qtextbrowser.h>
+
+#include <kdelibs_export.h>
+
+// ### inherit KTextBrowser in KDE4
+
+class KActiveLabelPrivate;
+ /**
+ * Label with support for selection and clickable links.
+ * openLink() the actions that will be taken when the user
+ * clicks on a link.
+ *
+ * @author Waldo Bastian (bastian@kde.org)
+ * @version $Id$
+ */
+class KDEUI_EXPORT KActiveLabel : public QTextBrowser
+{
+ Q_OBJECT
+public:
+ /**
+ * Constructor.
+ *
+ * It connects the "linkClicked(const QString &)" signal to the
+ * "openLink(const QString &)" slot. You will need to disconnect
+ * this if you want to process linkClicked() yourself.
+ */
+ KActiveLabel(QWidget * parent, const char * name = 0);
+
+ /**
+ * Constructor.
+ *
+ * It connects the "linkClicked(const QString &)" signal to the
+ * "openLink(const QString &)" slot. You will need to disconnect
+ * this if you want to process linkClicked() yourself.
+ */
+ KActiveLabel(const QString & text, QWidget * parent, const char * name = 0);
+
+ QSize minimumSizeHint() const;
+ QSize sizeHint() const;
+
+public slots:
+ /**
+ * Opens @p link in the default browser.
+ *
+ * If @p link starts with the text "whatsthis:" a QWhatsThis
+ * box will appear and then display the rest of the text. The WhatsThis
+ * functionality is available since KDE 3.2.
+ */
+ virtual void openLink(const QString & link);
+
+private slots:
+ void paletteChanged();
+ void setSource( const QString &) { }
+
+private:
+ void init();
+protected:
+ virtual void virtual_hook( int id, void* data );
+ virtual void focusInEvent( QFocusEvent* fe );
+ virtual void focusOutEvent( QFocusEvent* fe );
+ virtual void keyPressEvent ( QKeyEvent * e );
+private:
+ KActiveLabelPrivate *d;
+};
+
+#endif
diff --git a/kdeui/kanimwidget.cpp b/kdeui/kanimwidget.cpp
new file mode 100644
index 000000000..8d5ca6b6c
--- /dev/null
+++ b/kdeui/kanimwidget.cpp
@@ -0,0 +1,212 @@
+// -*- c-basic-offset: 2 -*-
+
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Kurt Granroth <granroth@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#include <kanimwidget.h>
+#include <qpixmap.h>
+#include <qtimer.h>
+#include <qpainter.h>
+#include <qimage.h>
+#include <ktoolbar.h>
+#include <kdebug.h>
+#include <kiconloader.h>
+
+class KAnimWidgetPrivate
+{
+public:
+ bool loadingCompleted : 1;
+ bool initDone : 1;
+ bool transparent : 1;
+ int frames;
+ int current_frame;
+ QPixmap pixmap;
+ QTimer timer;
+ QString icon_name;
+ int size;
+};
+
+KAnimWidget::KAnimWidget( const QString& icons, int size, QWidget *parent,
+ const char *name )
+ : QFrame( parent, name ),
+ d( new KAnimWidgetPrivate )
+{
+ connect( &d->timer, SIGNAL(timeout()), this, SLOT(slotTimerUpdate()));
+
+ if (parent && parent->inherits( "KToolBar" ))
+ connect(parent, SIGNAL(modechange()), this, SLOT(updateIcons()));
+
+ d->loadingCompleted = false;
+ d->size = size;
+ d->initDone = false;
+ setIcons( icons );
+ setFrameStyle( StyledPanel | Sunken );
+}
+
+KAnimWidget::~KAnimWidget()
+{
+ d->timer.stop();
+
+ delete d; d = 0;
+}
+
+void KAnimWidget::start()
+{
+ d->current_frame = 0;
+ d->timer.start( 50 );
+}
+
+void KAnimWidget::stop()
+{
+ d->current_frame = 0;
+ d->timer.stop();
+ repaint();
+}
+
+void KAnimWidget::setSize( int size )
+{
+ if ( d->size == size )
+ return;
+
+ d->size = size;
+ updateIcons();
+}
+
+void KAnimWidget::setIcons( const QString& icons )
+{
+ if ( d->icon_name == icons )
+ return;
+
+ d->icon_name = icons;
+ updateIcons();
+}
+
+QString KAnimWidget::icons( ) const
+{
+ return d->icon_name;
+}
+
+int KAnimWidget::size( ) const
+{
+ return d->size;
+}
+
+
+void KAnimWidget::showEvent(QShowEvent* e)
+{
+ if (!d->initDone)
+ {
+ d->initDone = true;
+ updateIcons();
+ }
+ QFrame::showEvent(e);
+}
+
+void KAnimWidget::hideEvent(QHideEvent* e)
+{
+ QFrame::hideEvent(e);
+}
+
+void KAnimWidget::enterEvent( QEvent *e )
+{
+ setFrameStyle( Panel | Raised );
+
+ QFrame::enterEvent( e );
+}
+
+void KAnimWidget::leaveEvent( QEvent *e )
+{
+ setFrameStyle( StyledPanel | Sunken );
+
+ QFrame::leaveEvent( e );
+}
+
+void KAnimWidget::mousePressEvent( QMouseEvent *e )
+{
+ QFrame::mousePressEvent( e );
+}
+
+void KAnimWidget::mouseReleaseEvent( QMouseEvent *e )
+{
+ if ( e->button() == LeftButton &&
+ rect().contains( e->pos() ) )
+ emit clicked();
+
+ QFrame::mouseReleaseEvent( e );
+}
+
+void KAnimWidget::slotTimerUpdate()
+{
+ if(!isVisible())
+ return;
+
+ d->current_frame++;
+ if (d->current_frame == d->frames)
+ d->current_frame = 0;
+
+ // TODO
+ // We have to clear the widget when repainting a transparent image
+ // By doing it like this we get a bit of flicker though. A better
+ // way might be to merge it with the background in drawContents.
+ repaint(d->transparent);
+}
+
+void KAnimWidget::drawContents( QPainter *p )
+{
+ if ( d->pixmap.isNull() )
+ return;
+
+ int w = d->pixmap.width();
+ int h = w;
+ int x = (width() - w) / 2;
+ int y = (height() - h) / 2;
+ p->drawPixmap(QPoint(x, y), d->pixmap, QRect(0, d->current_frame*h, w, h));
+}
+
+void KAnimWidget::updateIcons()
+{
+ if (!d->initDone)
+ return;
+
+ if (parent()->inherits( "KToolBar" ))
+ d->size = ((KToolBar*)parent())->iconSize();
+ if (!d->size)
+ d->size = KGlobal::iconLoader()->currentSize(KIcon::MainToolbar);
+
+ QString path = KGlobal::iconLoader()->iconPath(d->icon_name, -d->size);
+ QImage img(path);
+
+ if (img.isNull())
+ return;
+
+ d->current_frame = 0;
+ d->frames = img.height() / img.width();
+ d->transparent = img.hasAlphaBuffer();
+ if (d->pixmap.width() != d->size)
+ {
+ img = img.smoothScale(d->size, d->size*d->frames);
+ }
+ d->pixmap = img;
+
+ setFixedSize( d->size+2, d->size+2 );
+ resize( d->size+2, d->size+2 );
+}
+
+void KAnimWidget::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "kanimwidget.moc"
diff --git a/kdeui/kanimwidget.h b/kdeui/kanimwidget.h
new file mode 100644
index 000000000..3c0d5f3e5
--- /dev/null
+++ b/kdeui/kanimwidget.h
@@ -0,0 +1,144 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Kurt Granroth <granroth@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef _KANIMWIDGET_H
+#define _KANIMWIDGET_H
+
+#include <qframe.h>
+
+#include <kdelibs_export.h>
+
+class QStringList;
+class QPainter;
+class QMouseEvent;
+
+class KAnimWidgetPrivate;
+/**
+ * @short Standard "About KDE" dialog box
+ *
+ * This is a widget used to display animation using multiple
+ * individual pixmaps. This widget allows you to deal with variable
+ * size icons (e.g., ones that will change based on a global setting)
+ * as it loads the icons internally. All you need to do is pass along
+ * a list of icon names and their size and everything else is taken
+ * care of.
+ *
+ * This widget also emits a 'clicked()' signal when it received a
+ * mouse press event.
+ *
+ * A quick example:
+ * \code
+ * KAnimWidget *anim = new KAnimWidget("kde", 0, this);
+ * anim->start();
+ * \endcode
+ *
+ * That example will search for the pixmaps "one.png", "two.png", and
+ * "three.png" in the share/icons/small/ directories as well as the
+ * app's pics directory.
+ *
+ * @author Kurt Granroth <granroth@kde.org>
+ */
+class KDEUI_EXPORT KAnimWidget : public QFrame
+{
+ Q_OBJECT
+ Q_PROPERTY( int size READ size WRITE setSize )
+ Q_PROPERTY( QString icons READ icons WRITE setIcons )
+
+public:
+ /**
+ * This is the most common constructor. Pass along the name of the
+ * animated icons to use (e.g., "kde") for the animation and an
+ * optional size to load and you're set. If you omit the size, the
+ * default size will be used.
+ *
+ * @param icons The icons name (e.g., "kde") to use for the animation
+ * @param size The size to load
+ * You don't have to set it if the parent is a
+ * KToolBar; in this case it will use the toolbar's
+ * size.
+ * @param parent The standard parent
+ * @param name The standard internal name
+ */
+ KAnimWidget( const QString& icons, int size = 0,
+ QWidget *parent = 0L, const char *name = 0L );
+
+ /**
+ * Destructor
+ */
+ virtual ~KAnimWidget();
+
+ /**
+ * Sets the size of the icons.
+ *
+ * @param size The size of the icons
+ */
+ void setSize( int size );
+
+ /**
+ * Returns the current size.
+ * @since 3.4
+ */
+ int size() const;
+
+ /**
+ * Returns the current icons
+ * since 3.4
+ */
+ QString icons() const;
+
+ /**
+ * Sets the name of the animated icons to load. This will use the
+ * KIconLoader::loadAnimated method for the actual loading.
+ *
+ * @param icons The name of the icons to use for the animation
+ */
+ void setIcons( const QString& icons );
+
+public slots:
+ /**
+ * Starts the animation from frame 1
+ */
+ void start();
+
+ /**
+ * Stops the animation. This will also reset the widget to frame 1.
+ */
+ void stop();
+
+signals:
+ void clicked();
+
+protected:
+ virtual void drawContents( QPainter *p );
+ virtual void leaveEvent( QEvent *e );
+ virtual void enterEvent( QEvent *e );
+ virtual void hideEvent( QHideEvent *e);
+ virtual void showEvent( QShowEvent *e);
+ virtual void mousePressEvent( QMouseEvent *e );
+ virtual void mouseReleaseEvent( QMouseEvent *e );
+
+protected slots:
+ void slotTimerUpdate();
+ void updateIcons();
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KAnimWidgetPrivate *d;
+};
+
+#endif // _KANIMWIDGET_H
diff --git a/kdeui/karrowbutton.cpp b/kdeui/karrowbutton.cpp
new file mode 100644
index 000000000..c9c423697
--- /dev/null
+++ b/kdeui/karrowbutton.cpp
@@ -0,0 +1,113 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2001 Frerich Raabe <raabe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "karrowbutton.h"
+
+#include <qstyle.h>
+#include <qpainter.h>
+
+class KArrowButtonPrivate
+{
+ public:
+ Qt::ArrowType arrow;
+};
+
+KArrowButton::KArrowButton(QWidget *parent, Qt::ArrowType arrow,
+ const char *name)
+ : QPushButton(parent, name)
+{
+ d = new KArrowButtonPrivate();
+ d->arrow = arrow;
+}
+
+KArrowButton::~KArrowButton()
+{
+ delete d;
+}
+
+QSize KArrowButton::sizeHint() const
+{
+ return QSize( 12, 12 );
+}
+
+void KArrowButton::setArrowType(Qt::ArrowType a)
+{
+ if (d->arrow != a) {
+ d->arrow = a;
+ repaint();
+ }
+}
+Qt::ArrowType KArrowButton::arrowType() const
+{
+ return d->arrow;
+}
+
+void KArrowButton::drawButton(QPainter *p)
+{
+ const unsigned int arrowSize = 8;
+ const unsigned int margin = 2;
+
+ p->fillRect( rect(), colorGroup().brush( QColorGroup::Background ) );
+ style().drawPrimitive( QStyle::PE_Panel, p, QRect( 0, 0, width(), height() ),
+ colorGroup(),
+ isDown() ? QStyle::Style_Sunken : QStyle::Style_Default,
+ QStyleOption( 2, 0 ) );
+
+ if (static_cast<unsigned int>(width()) < arrowSize + margin ||
+ static_cast<unsigned int>(height()) < arrowSize + margin)
+ return; // don't draw arrows if we are too small
+
+ unsigned int x = 0, y = 0;
+ if (d->arrow == DownArrow) {
+ x = (width() - arrowSize) / 2;
+ y = height() - (arrowSize + margin);
+ } else if (d->arrow == UpArrow) {
+ x = (width() - arrowSize) / 2;
+ y = margin;
+ } else if (d->arrow == RightArrow) {
+ x = width() - (arrowSize + margin);
+ y = (height() - arrowSize) / 2;
+ } else { // arrowType == LeftArrow
+ x = margin;
+ y = (height() - arrowSize) / 2;
+ }
+
+ if (isDown()) {
+ x++;
+ y++;
+ }
+
+ QStyle::PrimitiveElement e = QStyle::PE_ArrowLeft;
+ switch (d->arrow)
+ {
+ case Qt::LeftArrow: e = QStyle::PE_ArrowLeft; break;
+ case Qt::RightArrow: e = QStyle::PE_ArrowRight; break;
+ case Qt::UpArrow: e = QStyle::PE_ArrowUp; break;
+ case Qt::DownArrow: e = QStyle::PE_ArrowDown; break;
+ }
+ int flags = QStyle::Style_Enabled;
+ if ( isDown() )
+ flags |= QStyle::Style_Down;
+ style().drawPrimitive( e, p, QRect( QPoint( x, y ), QSize( arrowSize, arrowSize ) ),
+ colorGroup(), flags );
+}
+
+void KArrowButton::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "karrowbutton.moc"
diff --git a/kdeui/karrowbutton.h b/kdeui/karrowbutton.h
new file mode 100644
index 000000000..8f5410908
--- /dev/null
+++ b/kdeui/karrowbutton.h
@@ -0,0 +1,94 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2001, 2002 Frerich Raabe <raabe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __karrowbutton_h__
+#define __karrowbutton_h__
+
+#include <qpushbutton.h>
+
+#include <kdelibs_export.h>
+
+class KArrowButtonPrivate;
+/**
+ * @short Draws a button with an arrow.
+ *
+ * Draws a button which shows an arrow pointing into a certain direction. The
+ * arrow's alignment on the button depends on the direction it's pointing to,
+ * e.g. a left arrow is aligned at the left border, a upwards arrow at the top
+ * border. This class honors the currently configured KStyle when drawing
+ * the arrow.
+ *
+ * @author Frerich Raabe
+ */
+class KDEUI_EXPORT KArrowButton : public QPushButton
+{
+ Q_OBJECT
+ Q_PROPERTY( int arrowType READ arrowTp WRITE setArrowTp )
+
+ public:
+ /**
+ * Constructs an arrow button.
+ *
+ * @param parent This button's parent
+ * @param arrow The direction the arrrow should be pointing in
+ * @param name An internal name for this widget
+ */
+ KArrowButton(QWidget *parent = 0, Qt::ArrowType arrow = Qt::UpArrow,
+ const char *name = 0);
+
+ /**
+ * Destructor.
+ */
+ virtual ~KArrowButton();
+
+ /**
+ * Reimplemented from QPushButton.
+ */
+ virtual QSize sizeHint() const;
+
+ /**
+ * Returns the arrow type
+ * @since 3.4
+ */
+ Qt::ArrowType arrowType() const;
+
+ // hacks for moc braindamages with enums
+ int arrowTp() const { return (int) arrowType(); }
+ void setArrowTp( int tp ) { setArrowType( (Qt::ArrowType) tp ); }
+ public slots:
+ /**
+ * Defines in what direction the arrow is pointing to. Will repaint the
+ * button if necessary.
+ *
+ * @param a The direction this arrow should be pointing in
+ */
+ void setArrowType(Qt::ArrowType a);
+
+ protected:
+ /**
+ * Reimplemented from QPushButton.
+ */
+ virtual void drawButton(QPainter *);
+
+ protected:
+ virtual void virtual_hook( int id, void* data );
+ private:
+ KArrowButtonPrivate *d;
+};
+
+#endif // __karrowbutton_h__
diff --git a/kdeui/kauthicon.cpp b/kdeui/kauthicon.cpp
new file mode 100644
index 000000000..9dd567b18
--- /dev/null
+++ b/kdeui/kauthicon.cpp
@@ -0,0 +1,203 @@
+/* This file is part of the KDE libraries
+ Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+/*
+ * KAuthIcon - an icon which shows whether privileges are in effect
+ */
+
+#include <unistd.h> // For getuid
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qtimer.h>
+
+#include <klocale.h>
+
+#include "kauthicon.h"
+
+/* XPM */
+static const char * const lock_xpm[] = {
+"22 22 5 1",
+" c None",
+". c #808080",
+"+ c #000000",
+"@ c #FFFFFF",
+"# c #C0C0C0",
+" ",
+" ",
+" ",
+" ",
+" .+++. ",
+" .@@@.+ ",
+" ..@+++@.. ",
+" +@+...+@+ ",
+" +@+. +@+. ",
+" +@+. +@+. ",
+" +++++++++++ ",
+" +#########+. ",
+" +#.......#+. ",
+" +#@@@@@@@#+. ",
+" +#.......#+. ",
+" +#########+. ",
+" +++++++++++. ",
+" ........... ",
+" ",
+" ",
+" ",
+" "};
+
+/* XPM */
+static const char * const openlock_xpm[] = {
+"22 22 5 1",
+" c None",
+". c #808080",
+"+ c #000000",
+"@ c #FFFFFF",
+"# c #C0C0C0",
+" ",
+" ",
+" .+++. ",
+" .@@@.+ ",
+" ..@+++@.. ",
+" +@+...+@+ ",
+" +@+. +@+. ",
+" +@+. +@+. ",
+" +++. +@+. ",
+" ... +@+. ",
+" +@+. ",
+" +++++++++++ ",
+" +#########+. ",
+" +#.......#+. ",
+" +#@@@@@@@#+. ",
+" +#.......#+. ",
+" +#########+. ",
+" +++++++++++. ",
+" ........... ",
+" ",
+" ",
+" "};
+
+KAuthIcon::KAuthIcon(QWidget *parent, const char *name)
+ : QWidget(parent, name),
+ lockPM( const_cast< const char** >( lock_xpm)),
+ openLockPM( const_cast< const char** >(openlock_xpm))
+{
+ lockText = i18n("Editing disabled");
+ openLockText = i18n("Editing enabled");
+
+ lockBox = new QLabel(this);
+ lockBox->setFrameStyle(QFrame::WinPanel|QFrame::Raised);
+ lockBox->setPixmap(lockPM);
+ lockBox->setFixedSize(lockBox->sizeHint());
+
+ lockLabel = new QLabel(this);
+ lockLabel->setFrameStyle(QFrame::NoFrame);
+
+ // set fixed size of this frame to whichever phrase is longer
+ if (lockLabel->fontMetrics().boundingRect(lockText).width() >
+ lockLabel->fontMetrics().boundingRect(openLockText).width())
+ lockLabel->setText(lockText);
+ else
+ lockLabel->setText(openLockText);
+ lockLabel->setAlignment(AlignCenter);
+ lockLabel->setMinimumSize(lockLabel->sizeHint());
+ lockLabel->setText(lockText);
+
+ layout = new QHBoxLayout(this);
+
+ layout->addWidget(lockBox, 0, AlignLeft|AlignVCenter);
+ layout->addSpacing(5);
+ layout->addWidget(lockLabel, 0, AlignRight|AlignVCenter);
+
+ layout->activate();
+ resize(sizeHint());
+}
+
+KAuthIcon::~KAuthIcon()
+{
+}
+
+
+QSize KAuthIcon::sizeHint() const
+{
+ return layout->minimumSize();
+}
+
+
+/************************************************************************/
+
+KRootPermsIcon::KRootPermsIcon(QWidget *parent, const char *name)
+ : KAuthIcon(parent, name)
+{
+ updateStatus();
+}
+
+
+KRootPermsIcon::~KRootPermsIcon()
+{
+}
+
+void KRootPermsIcon::updateStatus()
+{
+ const bool newRoot = (geteuid() == 0);
+ lockBox->setPixmap(newRoot ? openLockPM : lockPM);
+ lockLabel->setText(newRoot ? openLockText : lockText);
+ update();
+ if (root != newRoot) {
+ root = newRoot;
+ emit authChanged(newRoot);
+ }
+}
+
+/************************************************************************/
+
+KWritePermsIcon::KWritePermsIcon(const QString & fileName,
+ QWidget *parent, const char *name)
+ : KAuthIcon(parent, name)
+{
+ fi.setFile(fileName);
+ updateStatus();
+}
+
+
+KWritePermsIcon::~KWritePermsIcon()
+{
+}
+
+void KWritePermsIcon::updateStatus()
+{
+ bool newwrite;
+ newwrite = fi.isWritable();
+ lockBox->setPixmap(newwrite ? openLockPM : lockPM);
+ lockLabel->setText(newwrite ? openLockText : lockText);
+ update();
+ if (writable != newwrite) {
+ writable = newwrite;
+ emit authChanged(newwrite);
+ }
+}
+
+void KAuthIcon::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void KRootPermsIcon::virtual_hook( int id, void* data )
+{ KAuthIcon::virtual_hook( id, data ); }
+
+void KWritePermsIcon::virtual_hook( int id, void* data )
+{ KAuthIcon::virtual_hook( id, data ); }
+
+#include "kauthicon.moc"
diff --git a/kdeui/kauthicon.h b/kdeui/kauthicon.h
new file mode 100644
index 000000000..ddbbfe9d5
--- /dev/null
+++ b/kdeui/kauthicon.h
@@ -0,0 +1,173 @@
+/* This file is part of the KDE libraries
+ Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef _KAUTHICON_H
+#define _KAUTHICON_H "$Id$"
+
+#include <qfileinfo.h>
+#include <qpixmap.h>
+#include <qstring.h>
+#include <qwidget.h>
+
+#include <kdelibs_export.h>
+
+class QHBoxLayout;
+class QLabel;
+class KAuthIconPrivate;
+
+/**
+ * @short A base class for authorization icon widgets
+ *
+ * This is the base class from which different authorization icon widget
+ * which actually do something should be derived. You can use these
+ * widgets to show that the user has (or doesn't have) the ability to do
+ * something, and why that is.
+ *
+ * One of the most useful things you can do with this is connect
+ * authChanged(bool) to setEnabled(bool) for a widget to turn it on and
+ * off depending on the status of whatever it is you are monitoring.
+ *
+ * @see KRootPermsIcon, KWritePermsIcon
+ * @author Preston Brown <pbrown@kde.org>
+ */
+class KDEUI_EXPORT KAuthIcon : public QWidget
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Constructor.
+ */
+ KAuthIcon(QWidget *parent = 0, const char *name = 0);
+ ~KAuthIcon();
+
+ virtual QSize sizeHint() const;
+ /**
+ * return the status of whatever is being monitored.
+ */
+ virtual bool status() const = 0;
+
+public slots:
+ /**
+ * Re-implement this method if you want the icon to update itself
+ * when something external has changed (i.e. a file on disk, uid/gid).
+ */
+ virtual void updateStatus() = 0;
+
+signals:
+ /**
+ * this signal is emitted when authorization has changed from
+ * its previous state.
+ * @param authorized will be true if the type of authorization
+ * described by the icon is true, otherwise it will be false.
+ */
+ void authChanged(bool authorized);
+
+protected:
+ QHBoxLayout *layout;
+
+ QLabel *lockBox;
+ QLabel *lockLabel;
+ QPixmap lockPM;
+ QPixmap openLockPM;
+ QString lockText;
+ QString openLockText;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KAuthIconPrivate *d;
+};
+
+class KRootPermsIconPrivate;
+/**
+ * Icon to show whether or not a user has root permissions.
+ *
+ * @see KAuthIcon
+ * @author Preston Brown <pbrown@kde.org>
+ */
+class KDEUI_EXPORT KRootPermsIcon : public KAuthIcon
+{
+ Q_OBJECT
+
+public:
+ KRootPermsIcon(QWidget *parent = 0, const char *name = 0);
+ ~KRootPermsIcon();
+
+ /**
+ * return whether or not the current user has root permissions.
+ */
+ bool status() const { return root; }
+
+public slots:
+ void updateStatus();
+
+protected:
+ bool root;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KRootPermsIconPrivate *d;
+};
+
+class KWritePermsIconPrivate;
+/**
+ * Auth icon for write permission display.
+ *
+ * @see KAuthIcon
+ * @author Preston Brown <pbrown@kde.org>
+ */
+class KDEUI_EXPORT KWritePermsIcon : public KAuthIcon
+{
+ Q_OBJECT
+ Q_PROPERTY( QString fileName READ fileName WRITE setFileName )
+
+public:
+ KWritePermsIcon(const QString & fileName, QWidget *parent = 0, const char *name = 0);
+ ~KWritePermsIcon();
+ /**
+ * @return whether or not the monitored file is writable.
+ */
+ bool status() const { return writable; }
+
+ /**
+ * make the icon watch a new filename.
+ * @param fileName the new file to monitor / display status for.
+ */
+ void setFileName(const QString & fileName) { fi.setFile(fileName); updateStatus(); }
+
+ /**
+ * return the filename of the currently watched file.
+ * @since 3.4
+ */
+ QString fileName() const { return fi.fileName(); }
+
+public slots:
+ void updateStatus();
+
+protected:
+ bool writable;
+ QFileInfo fi;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KWritePermsIconPrivate *d;
+};
+
+#endif
diff --git a/kdeui/kbugreport.cpp b/kdeui/kbugreport.cpp
new file mode 100644
index 000000000..f6f529197
--- /dev/null
+++ b/kdeui/kbugreport.cpp
@@ -0,0 +1,536 @@
+/* This file is part of the KDE project
+ Copyright (C) 1999 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qhbuttongroup.h>
+#include <qpushbutton.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qmultilineedit.h>
+#include <qradiobutton.h>
+#include <qwhatsthis.h>
+#include <qregexp.h>
+
+#include <kaboutdata.h>
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kprocess.h>
+#include <kstandarddirs.h>
+#include <kstdguiitem.h>
+#include <kurl.h>
+#include <kurllabel.h>
+
+#include "kbugreport.h"
+
+#include <stdio.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include <sys/utsname.h>
+
+#include "kdepackages.h"
+#include <kcombobox.h>
+#include <config.h>
+#include <ktempfile.h>
+#include <qtextstream.h>
+#include <qfile.h>
+
+class KBugReportPrivate {
+public:
+ KComboBox *appcombo;
+ QString lastError;
+ QString kde_version;
+ QString appname;
+ QString os;
+ QPushButton *submitBugButton;
+ KURL url;
+};
+
+KBugReport::KBugReport( QWidget * parentw, bool modal, const KAboutData *aboutData )
+ : KDialogBase( Plain,
+ i18n("Submit Bug Report"),
+ Ok | Cancel,
+ Ok,
+ parentw,
+ "KBugReport",
+ modal, // modal
+ true // separator
+ )
+{
+ d = new KBugReportPrivate;
+
+ // Use supplied aboutdata, otherwise the one from the active instance
+ // otherwise the KGlobal one. _activeInstance should neved be 0L in theory.
+ m_aboutData = aboutData
+ ? aboutData
+ : ( KGlobal::_activeInstance ? KGlobal::_activeInstance->aboutData()
+ : KGlobal::instance()->aboutData() );
+ m_process = 0;
+ QWidget * parent = plainPage();
+ d->submitBugButton = 0;
+
+ if ( m_aboutData->bugAddress() == QString::fromLatin1("submit@bugs.kde.org") )
+ {
+ // This is a core KDE application -> redirect to the web form
+ d->submitBugButton = new QPushButton( parent );
+ setButtonCancel( KStdGuiItem::close() );
+ }
+
+ QLabel * tmpLabel;
+ QVBoxLayout * lay = new QVBoxLayout( parent, 0, spacingHint() );
+
+ QGridLayout *glay = new QGridLayout( lay, 4, 3 );
+ glay->setColStretch( 1, 10 );
+ glay->setColStretch( 2, 10 );
+
+ int row = 0;
+
+ if ( !d->submitBugButton )
+ {
+ // From
+ QString qwtstr = i18n( "Your email address. If incorrect, use the Configure Email button to change it" );
+ tmpLabel = new QLabel( i18n("From:"), parent );
+ glay->addWidget( tmpLabel, row,0 );
+ QWhatsThis::add( tmpLabel, qwtstr );
+ m_from = new QLabel( parent );
+ glay->addWidget( m_from, row, 1 );
+ QWhatsThis::add( m_from, qwtstr );
+
+
+ // Configure email button
+ m_configureEmail = new QPushButton( i18n("Configure Email..."),
+ parent );
+ connect( m_configureEmail, SIGNAL( clicked() ), this,
+ SLOT( slotConfigureEmail() ) );
+ glay->addMultiCellWidget( m_configureEmail, 0, 2, 2, 2, AlignTop|AlignRight );
+
+ // To
+ qwtstr = i18n( "The email address this bug report is sent to." );
+ tmpLabel = new QLabel( i18n("To:"), parent );
+ glay->addWidget( tmpLabel, ++row,0 );
+ QWhatsThis::add( tmpLabel, qwtstr );
+ tmpLabel = new QLabel( m_aboutData->bugAddress(), parent );
+ glay->addWidget( tmpLabel, row, 1 );
+ QWhatsThis::add( tmpLabel, qwtstr );
+
+ setButtonOK( KGuiItem( i18n("&Send"), "mail_send", i18n( "Send bug report." ),
+ i18n( "Send this bug report to %1." ).arg( m_aboutData->bugAddress() ) ) );
+
+ }
+ else
+ {
+ m_configureEmail = 0;
+ m_from = 0;
+ showButtonOK( false );
+ }
+
+ // Program name
+ QString qwtstr = i18n( "The application for which you wish to submit a bug report - if incorrect, please use the Report Bug menu item of the correct application" );
+ tmpLabel = new QLabel( i18n("Application: "), parent );
+ glay->addWidget( tmpLabel, ++row, 0 );
+ QWhatsThis::add( tmpLabel, qwtstr );
+ d->appcombo = new KComboBox( false, parent, "app");
+ QWhatsThis::add( d->appcombo, qwtstr );
+ d->appcombo->insertStrList((const char**)packages);
+ connect(d->appcombo, SIGNAL(activated(int)), SLOT(appChanged(int)));
+ d->appname = QString::fromLatin1( m_aboutData
+ ? m_aboutData->productName()
+ : qApp->name() );
+ glay->addWidget( d->appcombo, row, 1 );
+ int index = 0;
+ for (; index < d->appcombo->count(); index++) {
+ if (d->appcombo->text(index) == d->appname) {
+ break;
+ }
+ }
+ if (index == d->appcombo->count()) { // not present
+ d->appcombo->insertItem(d->appname);
+ }
+ d->appcombo->setCurrentItem(index);
+
+ QWhatsThis::add( tmpLabel, qwtstr );
+
+ // Version
+ qwtstr = i18n( "The version of this application - please make sure that no newer version is available before sending a bug report" );
+ tmpLabel = new QLabel( i18n("Version:"), parent );
+ glay->addWidget( tmpLabel, ++row, 0 );
+ QWhatsThis::add( tmpLabel, qwtstr );
+ if (m_aboutData)
+ m_strVersion = m_aboutData->version();
+ else
+ m_strVersion = i18n("no version set (programmer error!)");
+ d->kde_version = QString::fromLatin1( KDE_VERSION_STRING );
+ d->kde_version += ", " + QString::fromLatin1( KDE_DISTRIBUTION_TEXT );
+ if ( !d->submitBugButton )
+ m_strVersion += " " + d->kde_version;
+ m_version = new QLabel( m_strVersion, parent );
+ //glay->addWidget( m_version, row, 1 );
+ glay->addMultiCellWidget( m_version, row, row, 1, 2 );
+ QWhatsThis::add( m_version, qwtstr );
+
+ tmpLabel = new QLabel(i18n("OS:"), parent);
+ glay->addWidget( tmpLabel, ++row, 0 );
+
+ struct utsname unameBuf;
+ uname( &unameBuf );
+ d->os = QString::fromLatin1( unameBuf.sysname ) +
+ " (" + QString::fromLatin1( unameBuf.machine ) + ") "
+ "release " + QString::fromLatin1( unameBuf.release );
+
+ tmpLabel = new QLabel(d->os, parent);
+ glay->addMultiCellWidget( tmpLabel, row, row, 1, 2 );
+
+ tmpLabel = new QLabel(i18n("Compiler:"), parent);
+ glay->addWidget( tmpLabel, ++row, 0 );
+ tmpLabel = new QLabel(QString::fromLatin1(KDE_COMPILER_VERSION), parent);
+ glay->addMultiCellWidget( tmpLabel, row, row, 1, 2 );
+
+ if ( !d->submitBugButton )
+ {
+ // Severity
+ m_bgSeverity = new QHButtonGroup( i18n("Se&verity"), parent );
+ static const char * const sevNames[5] = { "critical", "grave", "normal", "wishlist", "i18n" };
+ const QString sevTexts[5] = { i18n("Critical"), i18n("Grave"), i18n("normal severity","Normal"), i18n("Wishlist"), i18n("Translation") };
+
+ for (int i = 0 ; i < 5 ; i++ )
+ {
+ // Store the severity string as the name
+ QRadioButton *rb = new QRadioButton( sevTexts[i], m_bgSeverity, sevNames[i] );
+ if (i==2) rb->setChecked(true); // default : "normal"
+ }
+
+ lay->addWidget( m_bgSeverity );
+
+ // Subject
+ QHBoxLayout * hlay = new QHBoxLayout( lay );
+ tmpLabel = new QLabel( i18n("S&ubject: "), parent );
+ hlay->addWidget( tmpLabel );
+ m_subject = new KLineEdit( parent );
+ m_subject->setFocus();
+ tmpLabel->setBuddy(m_subject);
+ hlay->addWidget( m_subject );
+
+ QString text = i18n("Enter the text (in English if possible) that you wish to submit for the "
+ "bug report.\n"
+ "If you press \"Send\", a mail message will be sent to the maintainer of "
+ "this program.\n");
+ QLabel * label = new QLabel( parent, "label" );
+
+ label->setText( text );
+ lay->addWidget( label );
+
+ // The multiline-edit
+ m_lineedit = new QMultiLineEdit( parent, "QMultiLineEdit" );
+ m_lineedit->setMinimumHeight( 180 ); // make it big
+ m_lineedit->setWordWrap(QMultiLineEdit::WidgetWidth);
+ lay->addWidget( m_lineedit, 10 /*stretch*/ );
+
+ slotSetFrom();
+ } else {
+ // Point to the web form
+
+ lay->addSpacing(10);
+ QString text = i18n("To submit a bug report, click on the button below.\n"
+ "This will open a web browser window on http://bugs.kde.org where you will find a form to fill in.\n"
+ "The information displayed above will be transferred to that server.");
+ QLabel * label = new QLabel( text, parent, "label");
+ lay->addWidget( label );
+ lay->addSpacing(10);
+
+ updateURL();
+ d->submitBugButton->setText( i18n("&Launch Bug Report Wizard") );
+ d->submitBugButton->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed);
+ lay->addWidget( d->submitBugButton );
+ lay->addSpacing(10);
+
+ connect( d->submitBugButton, SIGNAL(clicked()),
+ this, SLOT(slotOk()));
+ }
+}
+
+KBugReport::~KBugReport()
+{
+ delete d;
+}
+
+void KBugReport::updateURL()
+{
+ KURL url ( "http://bugs.kde.org/wizard.cgi" );
+ url.addQueryItem( "os", d->os );
+ url.addQueryItem( "compiler", KDE_COMPILER_VERSION );
+ url.addQueryItem( "kdeVersion", d->kde_version );
+ url.addQueryItem( "appVersion", m_strVersion );
+ url.addQueryItem( "package", d->appcombo->currentText() );
+ url.addQueryItem( "kbugreport", "1" );
+ d->url = url;
+}
+
+void KBugReport::appChanged(int i)
+{
+ QString appName = d->appcombo->text(i);
+ int index = appName.find( '/' );
+ if ( index > 0 )
+ appName = appName.left( index );
+ kdDebug() << "appName " << appName << endl;
+
+ if (d->appname == appName && m_aboutData)
+ m_strVersion = m_aboutData->version();
+ else
+ m_strVersion = i18n("unknown program name", "unknown");
+
+ if ( !d->submitBugButton )
+ m_strVersion += d->kde_version;
+
+ m_version->setText(m_strVersion);
+ if ( d->submitBugButton )
+ updateURL();
+}
+
+void KBugReport::slotConfigureEmail()
+{
+ if (m_process) return;
+ m_process = new KProcess;
+ *m_process << QString::fromLatin1("kcmshell") << QString::fromLatin1("kcm_useraccount");
+ connect(m_process, SIGNAL(processExited(KProcess *)), SLOT(slotSetFrom()));
+ if (!m_process->start())
+ {
+ kdDebug() << "Couldn't start kcmshell.." << endl;
+ delete m_process;
+ m_process = 0;
+ return;
+ }
+ m_configureEmail->setEnabled(false);
+}
+
+void KBugReport::slotSetFrom()
+{
+ delete m_process;
+ m_process = 0;
+ m_configureEmail->setEnabled(true);
+
+ // ### KDE4: why oh why is KEmailSettings in kio?
+ KConfig emailConf( QString::fromLatin1("emaildefaults") );
+
+ // find out the default profile
+ emailConf.setGroup( QString::fromLatin1("Defaults") );
+ QString profile = QString::fromLatin1("PROFILE_");
+ profile += emailConf.readEntry( QString::fromLatin1("Profile"),
+ QString::fromLatin1("Default") );
+
+ emailConf.setGroup( profile );
+ QString fromaddr = emailConf.readEntry( QString::fromLatin1("EmailAddress") );
+ if (fromaddr.isEmpty()) {
+ struct passwd *p;
+ p = getpwuid(getuid());
+ fromaddr = QString::fromLatin1(p->pw_name);
+ } else {
+ QString name = emailConf.readEntry( QString::fromLatin1("FullName"));
+ if (!name.isEmpty())
+ fromaddr = name + QString::fromLatin1(" <") + fromaddr + QString::fromLatin1(">");
+ }
+ m_from->setText( fromaddr );
+}
+
+void KBugReport::slotUrlClicked(const QString &urlText)
+{
+ if ( kapp )
+ kapp->invokeBrowser( urlText );
+
+ // When using the web form, a click can also close the window, as there's
+ // not much to do. It also gives the user a direct response to his click:
+ if ( d->submitBugButton )
+ KDialogBase::slotCancel();
+}
+
+
+void KBugReport::slotOk( void )
+{
+ if ( d->submitBugButton ) {
+ if ( kapp )
+ kapp->invokeBrowser( d->url.url() );
+ return;
+ }
+
+ if( m_lineedit->text().isEmpty() ||
+ m_subject->text().isEmpty() )
+ {
+ QString msg = i18n("You must specify both a subject and a description "
+ "before the report can be sent.");
+ KMessageBox::error(this,msg);
+ return;
+ }
+
+ switch ( m_bgSeverity->id( m_bgSeverity->selected() ) )
+ {
+ case 0: // critical
+ if ( KMessageBox::questionYesNo( this, i18n(
+ "<p>You chose the severity <b>Critical</b>. "
+ "Please note that this severity is intended only for bugs that</p>"
+ "<ul><li>break unrelated software on the system (or the whole system)</li>"
+ "<li>cause serious data loss</li>"
+ "<li>introduce a security hole on the system where the affected package is installed</li></ul>\n"
+ "<p>Does the bug you are reporting cause any of the above damage? "
+ "If it does not, please select a lower severity. Thank you!</p>" ),QString::null,KStdGuiItem::cont(),KStdGuiItem::cancel() ) == KMessageBox::No )
+ return;
+ break;
+ case 1: // grave
+ if ( KMessageBox::questionYesNo( this, i18n(
+ "<p>You chose the severity <b>Grave</b>. "
+ "Please note that this severity is intended only for bugs that</p>"
+ "<ul><li>make the package in question unusable or mostly so</li>"
+ "<li>cause data loss</li>"
+ "<li>introduce a security hole allowing access to the accounts of users who use the affected package</li></ul>\n"
+ "<p>Does the bug you are reporting cause any of the above damage? "
+ "If it does not, please select a lower severity. Thank you!</p>" ),QString::null,KStdGuiItem::cont(),KStdGuiItem::cancel() ) == KMessageBox::No )
+ return;
+ break;
+ }
+ if( !sendBugReport() )
+ {
+ QString msg = i18n("Unable to send the bug report.\n"
+ "Please submit a bug report manually...\n"
+ "See http://bugs.kde.org/ for instructions.");
+ KMessageBox::error(this, msg + "\n\n" + d->lastError);
+ return;
+ }
+
+ KMessageBox::information(this,
+ i18n("Bug report sent, thank you for your input."));
+ accept();
+}
+
+void KBugReport::slotCancel()
+{
+ if( !d->submitBugButton && ( m_lineedit->edited() || m_subject->edited() ) )
+ {
+ int rc = KMessageBox::warningYesNo( this,
+ i18n( "Close and discard\nedited message?" ),
+ i18n( "Close Message" ), KStdGuiItem::discard(), KStdGuiItem::cont() );
+ if( rc == KMessageBox::No )
+ return;
+ }
+ KDialogBase::slotCancel();
+}
+
+
+QString KBugReport::text() const
+{
+ kdDebug() << m_bgSeverity->selected()->name() << endl;
+ // Prepend the pseudo-headers to the contents of the mail
+ QString severity = QString::fromLatin1(m_bgSeverity->selected()->name());
+ QString appname = d->appcombo->currentText();
+ QString os = QString::fromLatin1("OS: %1 (%2)\n").
+ arg(KDE_COMPILING_OS).
+ arg(KDE_DISTRIBUTION_TEXT);
+ QString bodyText;
+ for(int i = 0; i < m_lineedit->numLines(); i++)
+ {
+ QString line = m_lineedit->textLine(i);
+ if (!line.endsWith("\n"))
+ line += '\n';
+ bodyText += line;
+ }
+
+ if (severity == QString::fromLatin1("i18n") && KGlobal::locale()->language() != KLocale::defaultLanguage()) {
+ // Case 1 : i18n bug
+ QString package = QString::fromLatin1("i18n_%1").arg(KGlobal::locale()->language());
+ package = package.replace(QString::fromLatin1("_"), QString::fromLatin1("-"));
+ return QString::fromLatin1("Package: %1").arg(package) +
+ QString::fromLatin1("\n"
+ "Application: %1\n"
+ // not really i18n's version, so better here IMHO
+ "Version: %2\n").arg(appname).arg(m_strVersion)+
+ os+QString::fromLatin1("\n")+bodyText;
+ } else {
+ appname = appname.replace(QString::fromLatin1("_"), QString::fromLatin1("-"));
+ // Case 2 : normal bug
+ return QString::fromLatin1("Package: %1\n"
+ "Version: %2\n"
+ "Severity: %3\n")
+ .arg(appname).arg(m_strVersion).arg(severity)+
+ QString::fromLatin1("Compiler: %1\n").arg(KDE_COMPILER_VERSION)+
+ os+QString::fromLatin1("\n")+bodyText;
+ }
+}
+
+bool KBugReport::sendBugReport()
+{
+ QString recipient ( m_aboutData ?
+ m_aboutData->bugAddress() :
+ QString::fromLatin1("submit@bugs.kde.org") );
+
+ QString command;
+ command = locate("exe", "ksendbugmail");
+ if (command.isEmpty())
+ command = KStandardDirs::findExe( QString::fromLatin1("ksendbugmail") );
+
+ KTempFile outputfile;
+ outputfile.close();
+
+ QString subject = m_subject->text();
+ command += " --subject ";
+ command += KProcess::quote(subject);
+ command += " --recipient ";
+ command += KProcess::quote(recipient);
+ command += " > ";
+ command += KProcess::quote(outputfile.name());
+
+ fflush(stdin);
+ fflush(stderr);
+
+ FILE * fd = popen(QFile::encodeName(command), "w");
+ if (!fd)
+ {
+ kdError() << "Unable to open a pipe to " << command << endl;
+ return false;
+ }
+
+ QString btext = text();
+ fwrite(btext.ascii(),btext.length(),1,fd);
+ fflush(fd);
+
+ int error = pclose(fd);
+ kdDebug() << "exit status1 " << error << " " << (WIFEXITED(error)) << " " << WEXITSTATUS(error) << endl;
+
+ if ((WIFEXITED(error)) && WEXITSTATUS(error) == 1) {
+ QFile of(outputfile.name());
+ if (of.open(IO_ReadOnly )) {
+ QTextStream is(&of);
+ is.setEncoding(QTextStream::UnicodeUTF8);
+ QString line;
+ while (!is.eof())
+ line = is.readLine();
+ d->lastError = line;
+ } else {
+ d->lastError = QString::null;
+ }
+ outputfile.unlink();
+ return false;
+ }
+ outputfile.unlink();
+ return true;
+}
+
+void KBugReport::virtual_hook( int id, void* data )
+{ KDialogBase::virtual_hook( id, data ); }
+
+#include "kbugreport.moc"
diff --git a/kdeui/kbugreport.h b/kdeui/kbugreport.h
new file mode 100644
index 000000000..b5f541603
--- /dev/null
+++ b/kdeui/kbugreport.h
@@ -0,0 +1,121 @@
+/* This file is part of the KDE project
+ Copyright (C) 1999 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef _KBUGREPORT_H__
+#define _KBUGREPORT_H__
+
+#include <kdialogbase.h>
+
+class QMultiLineEdit;
+class QLineEdit;
+class QHButtonGroup;
+class KProcess;
+class KAboutData;
+class KBugReportPrivate;
+
+/**
+ * @short A dialog box for sending bug reports.
+ *
+ * All the information needed by the dialog box
+ * (program name, version, bug-report address, etc.)
+ * comes from the KAboutData class.
+ * Make sure you create an instance of KAboutData and pass it
+ * to KCmdLineArgs.
+ *
+ * @author David Faure <faure@kde.org>
+ */
+class KDEUI_EXPORT KBugReport : public KDialogBase
+{
+ Q_OBJECT
+public:
+ /**
+ * Creates a bug-report dialog.
+ * Note that you shouldn't have to do this manually,
+ * since KHelpMenu takes care of the menu item
+ * for "Report Bug..." and of creating a KBugReport dialog.
+ */
+ KBugReport( QWidget * parent = 0L, bool modal=true, const KAboutData *aboutData = 0L );
+ /**
+ * Destructor
+ */
+ virtual ~KBugReport();
+
+protected slots:
+ /**
+ * "Configure email" has been clicked - this calls kcmshell System/email
+ */
+ virtual void slotConfigureEmail();
+ /**
+ * Sets the "From" field from the e-mail configuration
+ * Called at creation time, but also after "Configure email" is closed.
+ */
+ virtual void slotSetFrom();
+ /**
+ * The URL-Label "http://bugs.kde.org/" was clicked.
+ * @deprecated remove in KDE4.0
+ */
+ virtual void slotUrlClicked(const QString &);
+ /**
+ * OK has been clicked
+ */
+ virtual void slotOk( void );
+ /**
+ * Cancel has been clicked
+ */
+ virtual void slotCancel();
+
+ /**
+ * Application combo selection changed (and was activated)
+ */
+ void appChanged(int);
+ /**
+ * Update the url to match the current os, compiler, selected app, etc
+ */
+ void updateURL();
+
+protected:
+ /**
+ * A complete copy of the bug report
+ * @return QString copy of the bug report.
+ */
+ QString text() const;
+ /**
+ * Attempt to e-mail the bug report.
+ * @return true on success
+ */
+ bool sendBugReport();
+
+ KProcess * m_process;
+ const KAboutData * m_aboutData;
+
+ QMultiLineEdit * m_lineedit;
+ QLineEdit * m_subject;
+ QLabel * m_from;
+ QLabel * m_version;
+ QString m_strVersion;
+ QHButtonGroup * m_bgSeverity;
+ QPushButton * m_configureEmail;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KBugReportPrivate *d;
+};
+
+#endif
+
diff --git a/kdeui/kbuttonbox.cpp b/kdeui/kbuttonbox.cpp
new file mode 100644
index 000000000..eab9fa072
--- /dev/null
+++ b/kdeui/kbuttonbox.cpp
@@ -0,0 +1,377 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Mario Weilguni (mweilguni@sime.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * KButtonBox class
+ *
+ * A container widget for buttons. Uses Qt layout control to place the
+ * buttons, can handle both vertical and horizontal button placement.
+*
+ * HISTORY
+ *
+ * 05/11/2004 Andrew Coles <andrew_coles@yahoo.co.uk>
+ * Now uses QPtrListIterators instead of indexing through data->buttons
+ * Item.button and data are now const pointers, set in the relevant constructors
+ *
+ * 03/08/2000 Mario Weilguni <mweilguni@kde.org>
+ * Removed all those long outdated Motif stuff
+ * Improved and clarified some if conditions (easier to understand)
+ *
+ * 11/13/98 Reginald Stadlbauer <reggie@kde.org>
+ * Now in Qt 1.4x motif default buttons have no extra width/height anymore.
+ * So the KButtonBox doesn't add this width/height to default buttons anymore
+ * which makes the buttons look better.
+ *
+ * 01/17/98 Mario Weilguni <mweilguni@sime.com>
+ * Fixed a bug in sizeHint()
+ * Improved the handling of Motif default buttons
+ *
+ * 01/09/98 Mario Weilguni <mweilguni@sime.com>
+ * The last button was to far right away from the right/bottom border.
+ * Fixed this. Removed old code. Buttons get now a minimum width.
+ * Programmer may now override minimum width and height of a button.
+ *
+ */
+
+#include "kbuttonbox.moc"
+#include <kglobalsettings.h>
+#include <kguiitem.h>
+#include <kpushbutton.h>
+#include <qptrlist.h>
+#include <assert.h>
+
+#define minButtonWidth 50
+
+class KButtonBox::Item {
+public:
+ KPushButton* const button;
+ bool noexpand;
+ unsigned short stretch;
+ unsigned short actual_size;
+
+ Item(KPushButton* const _button) : button(_button) {}
+};
+
+template class QPtrList<KButtonBox::Item>;
+
+class KButtonBoxPrivate {
+public:
+ unsigned short border;
+ unsigned short autoborder;
+ unsigned short orientation;
+ bool activated;
+ QPtrList<KButtonBox::Item> buttons;
+};
+
+KButtonBox::KButtonBox(QWidget *parent, Orientation _orientation,
+ int border, int autoborder)
+ : QWidget(parent), data(new KButtonBoxPrivate)
+{
+ assert(data);
+
+ data->orientation = _orientation;
+ data->border = border;
+ data->autoborder = autoborder < 0 ? border : autoborder;
+ data->buttons.setAutoDelete(true);
+}
+
+KButtonBox::~KButtonBox() {
+ delete data;
+}
+
+QPushButton *KButtonBox::addButton(const QString& text, bool noexpand) {
+ Item* const item = new Item(new KPushButton(text, this));
+
+ item->noexpand = noexpand;
+ data->buttons.append(item);
+ item->button->adjustSize();
+
+ this->updateGeometry();
+
+ return item->button;
+}
+
+QPushButton *KButtonBox::addButton(const KGuiItem& guiitem, bool noexpand) {
+ Item* const item = new Item(new KPushButton(guiitem, this));
+
+ item->noexpand = noexpand;
+ data->buttons.append(item);
+ item->button->adjustSize();
+
+ this->updateGeometry();
+
+ return item->button;
+}
+
+ QPushButton *
+KButtonBox::addButton(
+ const QString & text,
+ QObject * receiver,
+ const char * slot,
+ bool noexpand
+)
+{
+ QPushButton * pb = addButton(text, noexpand);
+
+ if ((0 != receiver) && (0 != slot))
+ QObject::connect(pb, SIGNAL(clicked()), receiver, slot);
+
+ return pb;
+}
+
+ QPushButton *
+KButtonBox::addButton(
+ const KGuiItem& guiitem,
+ QObject * receiver,
+ const char * slot,
+ bool noexpand
+)
+{
+ QPushButton * pb = addButton(guiitem, noexpand);
+
+ if ((0 != receiver) && (0 != slot))
+ QObject::connect(pb, SIGNAL(clicked()), receiver, slot);
+
+ return pb;
+}
+
+void KButtonBox::addStretch(int scale) {
+ if(scale > 0) {
+ Item* const item = new Item(0);
+ item->noexpand = false;
+ item->stretch = scale;
+ data->buttons.append(item);
+ }
+}
+
+void KButtonBox::layout() {
+ // resize all buttons
+ const QSize bs = bestButtonSize();
+
+ QPtrListIterator<KButtonBox::Item> itr(data->buttons);
+ Item* item;
+
+ while ( (item = itr.current()) != 0 ) {
+ QPushButton* const b = item->button;
+ if(b) {
+ if(item->noexpand)
+ b->setFixedSize(buttonSizeHint(b));
+ else
+ b->setFixedSize(bs);
+ }
+ ++itr;
+ }
+
+ setMinimumSize(sizeHint());
+}
+
+void KButtonBox::placeButtons() {
+
+ if(data->orientation == Horizontal) {
+ // calculate free size and stretches
+ int fs = width() - 2 * data->border;
+ int stretch = 0;
+ {
+ QPtrListIterator<KButtonBox::Item> itr(data->buttons);
+ Item *item;
+
+ while ( (item = itr.current()) != 0 ) {
+ QPushButton* const b = item->button;
+ if(b) {
+ fs -= b->width();
+
+ // Last button?
+ if(!itr.atLast())
+ fs -= data->autoborder;
+ } else {
+ stretch +=item->stretch;
+ }
+
+ ++itr;
+ }
+ }
+
+ // distribute buttons
+ int x_pos = data->border;
+ {
+ QPtrListIterator<KButtonBox::Item> itr(data->buttons);
+ Item *item;
+
+ while ( (item = itr.current()) != 0 ) {
+ QPushButton* const b = item->button;
+ if(b) {
+ b->move(x_pos, (height() - b->height()) / 2);
+
+ x_pos += b->width() + data->autoborder;
+ } else {
+ x_pos += (int)((((double)fs) * item->stretch) / stretch);
+ }
+
+ ++itr;
+ }
+ }
+
+ } else { // VERTICAL
+ // calcualte free size and stretches
+ int fs = height() - 2 * data->border;
+ int stretch = 0;
+ {
+ QPtrListIterator<KButtonBox::Item> itr(data->buttons);
+ Item *item;
+
+ while ( (item = itr.current()) != 0 ) {
+ QPushButton* const b = item->button;
+ if(b)
+ fs -= b->height() + data->autoborder;
+ else
+ stretch +=item->stretch;
+
+ ++itr;
+ }
+
+ }
+
+ // distribute buttons
+ int y_pos = data->border;
+ {
+ QPtrListIterator<KButtonBox::Item> itr(data->buttons);
+ Item *item;
+
+ while ( (item = itr.current()) != 0 ) {
+ QPushButton* const b = item->button;
+ if(b) {
+ b->move((width() - b->width()) / 2, y_pos);
+
+ y_pos += b->height() + data->autoborder;
+ } else {
+ y_pos += (int)((((double)fs) * item->stretch) / stretch);
+ }
+
+ ++itr;
+ }
+ }
+ }
+}
+
+void KButtonBox::resizeEvent(QResizeEvent *) {
+ placeButtons();
+}
+
+QSize KButtonBox::bestButtonSize() const {
+ QSize s(0, 0);
+
+ // calculate optimal size
+ QPtrListIterator<KButtonBox::Item> itr(data->buttons);
+ Item *item;
+
+ while ( (item = itr.current()) != 0 ) {
+ QPushButton* const b = item->button;
+
+ if(b && !item->noexpand) {
+ const QSize bs = buttonSizeHint(b);
+
+ const int bsWidth = bs.width();
+ const int bsHeight = bs.height();
+
+ if(bsWidth > s.width())
+ s.setWidth(bsWidth);
+ if(bsHeight > s.height())
+ s.setHeight(bsHeight);
+ }
+ ++itr;
+ }
+
+ return s;
+}
+
+QSize KButtonBox::sizeHint() const {
+ unsigned int dw;
+
+ if(data->buttons.isEmpty())
+ return QSize(0, 0);
+ else {
+ dw = 2 * data->border;
+
+ const QSize bs = bestButtonSize();
+
+ QPtrListIterator<KButtonBox::Item> itr(data->buttons);
+ Item *item;
+
+ while ( (item = itr.current()) != 0 ) {
+ QPushButton* const b = item->button;
+
+ if(b) {
+ QSize s;
+ if(item->noexpand)
+ s = buttonSizeHint(b);
+ else
+ s = bs;
+
+ if(data->orientation == Horizontal)
+ dw += s.width();
+ else
+ dw += s.height();
+
+ if( !itr.atLast() )
+ dw += data->autoborder;
+ }
+
+ ++itr;
+ }
+
+ if(data->orientation == Horizontal)
+ return QSize(dw, bs.height() + 2 * data->border);
+ else
+ return QSize(bs.width() + 2 * data->border, dw);
+ }
+}
+
+QSizePolicy KButtonBox::sizePolicy() const
+{
+ return data->orientation == Horizontal?
+ QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed ) :
+ QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Minimum );
+}
+
+/*
+ * Returns the best size for a button. If a button is less than
+ * minButtonWidth pixels wide, return minButtonWidth pixels
+ * as minimum width
+ */
+QSize KButtonBox::buttonSizeHint(QPushButton *b) const {
+ QSize s = b->sizeHint();
+ const QSize ms = b->minimumSize();
+ if(s.width() < minButtonWidth)
+ s.setWidth(minButtonWidth);
+
+ // allows the programmer to override the settings
+ const int msWidth = ms.width();
+ const int msHeight = ms.height();
+
+ if(msWidth > s.width())
+ s.setWidth(msWidth);
+ if(msHeight > s.height())
+ s.setHeight(msHeight);
+
+ return s;
+}
+
+void KButtonBox::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
diff --git a/kdeui/kbuttonbox.h b/kdeui/kbuttonbox.h
new file mode 100644
index 000000000..51ae7024c
--- /dev/null
+++ b/kdeui/kbuttonbox.h
@@ -0,0 +1,170 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Mario Weilguni (mweilguni@sime.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __KBUTTONBOX__H__
+#define __KBUTTONBOX__H__
+
+#include <kdelibs_export.h>
+
+#include <qwidget.h>
+class QPushButton;
+class KGuiItem;
+
+class KButtonBoxPrivate;
+/**
+ * Container widget for buttons.
+ *
+ * This class uses Qt layout control to place the buttons; can handle
+ * both vertical and horizontal button placement. The default border
+ * is now @p 0 (making it easier to deal with layouts). The space
+ * between buttons is now more Motif compliant.
+ *
+ * @author Mario Weilguni <mweilguni@sime.com>
+ * @version $Id$
+ **/
+
+class KDEUI_EXPORT KButtonBox : public QWidget
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Create an empty container for buttons.
+ *
+ * If @p _orientation is @p Vertical, the buttons inserted with
+ * addButton() are laid out from top to bottom, otherwise they
+ * are laid out from left to right.
+ */
+ KButtonBox(QWidget *parent, Orientation _orientation = Horizontal,
+ int border = 0, int _autoborder = 6);
+
+ /**
+ * Free private data field
+ */
+ ~KButtonBox();
+
+ /**
+ * @return The minimum size needed to fit all buttons.
+ *
+ * This size is
+ * calculated by the width/height of all buttons plus border/autoborder.
+ */
+ virtual QSize sizeHint() const;
+ virtual QSizePolicy sizePolicy() const;
+ virtual void resizeEvent(QResizeEvent *);
+
+ /**
+ * Add a new QPushButton.
+ *
+ * @param text the text of the button to add
+ * @param noexpand If @p noexpand is @p false, the width
+ * of the button is adjusted to fit the other buttons (the maximum
+ * of all buttons is taken). If @p noexpand is @p true, the width of this
+ * button will be set to the minimum width needed for the given text).
+ *
+ * @return A pointer to the new button.
+ */
+ QPushButton *addButton(const QString& text, bool noexpand = false);
+
+ /**
+ * Add a new QPushButton.
+ *
+ * @param text the text of the button to add.
+ * @param receiver An object to connect to.
+ * @param slot A Qt slot to connect the 'clicked()' signal to.
+ * @param noexpand If @p noexpand is @p false, the width
+ * of the button is adjusted to fit the other buttons (the maximum
+ * of all buttons is taken). If @p noexpand @p true, the width of this
+ * button will be set to the minimum width needed for the given text).
+ *
+ * @return A pointer to the new button.
+ */
+ QPushButton *addButton(const QString& text, QObject * receiver, const char * slot, bool noexpand = false);
+
+ /**
+ * Add a new QPushButton.
+ *
+ * @param guiitem text and icon on the button
+ * @param noexpand If @p noexpand is @p false, the width
+ * of the button is adjusted to fit the other buttons (the maximum
+ * of all buttons is taken). If @p noexpand is @p true, the width of this
+ * button will be set to the minimum width needed for the given text).
+ *
+ * @return A pointer to the new button.
+ *
+ * @since 3.3
+ */
+ QPushButton *addButton(const KGuiItem& guiitem, bool noexpand = false);
+
+ /**
+ * Add a new QPushButton.
+ *
+ * @param guiitem text and icon on the button
+ * @param receiver An object to connect to.
+ * @param slot A Qt slot to connect the 'clicked()' signal to.
+ * @param noexpand If @p noexpand is @p false, the width
+ * of the button is adjusted to fit the other buttons (the maximum
+ * of all buttons is taken). If @p noexpand @p true, the width of this
+ * button will be set to the minimum width needed for the given text).
+ *
+ * @return A pointer to the new button.
+ *
+ * @since 3.3
+ */
+ QPushButton *addButton(const KGuiItem& guiitem, QObject * receiver, const char * slot, bool noexpand = false);
+
+ /**
+ * Add a stretch to the buttonbox.
+ *
+ * Can be used to separate buttons. That is, if you add the
+ * buttons OK and Cancel, add a stretch, and then add the button Help,
+ * the buttons OK and Cancel will be left-aligned (or top-aligned
+ * for vertical) whereas Help will be right-aligned (or
+ * bottom-aligned for vertical).
+ *
+ * @see QBoxLayout
+ */
+ void addStretch(int scale = 1);
+
+ /**
+ * This function must be called @em once after all buttons have been
+ * inserted.
+ *
+ * It will start layout control.
+ */
+ void layout();
+
+public: // as PrivateData needs Item, it has to be exported
+ class Item;
+protected:
+ /**
+ * @return the best size for a button. Checks all buttons and takes
+ * the maximum width/height.
+ */
+ QSize bestButtonSize() const;
+ void placeButtons();
+ QSize buttonSizeHint(QPushButton *) const;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KButtonBoxPrivate* const data;
+};
+
+#endif
diff --git a/kdeui/kcharselect.cpp b/kdeui/kcharselect.cpp
new file mode 100644
index 000000000..295b3efc9
--- /dev/null
+++ b/kdeui/kcharselect.cpp
@@ -0,0 +1,546 @@
+/* This file is part of the KDE libraries
+
+ Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kcharselect.h"
+#include "kcharselect.moc"
+
+#include <qbrush.h>
+#include <qcolor.h>
+#include <qevent.h>
+#include <qfont.h>
+#include <qfontdatabase.h>
+#include <qhbox.h>
+#include <qkeycode.h>
+#include <qlabel.h>
+#include <qpainter.h>
+#include <qpen.h>
+#include <qregexp.h>
+#include <qstyle.h>
+#include <qtooltip.h>
+#include <qvalidator.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kdialog.h>
+#include <klineedit.h>
+#include <klocale.h>
+
+class KCharSelect::KCharSelectPrivate
+{
+public:
+ QLineEdit *unicodeLine;
+};
+
+QFontDatabase * KCharSelect::fontDataBase = 0;
+
+void KCharSelect::cleanupFontDatabase()
+{
+ delete fontDataBase;
+ fontDataBase = 0;
+}
+
+/******************************************************************/
+/* Class: KCharSelectTable */
+/******************************************************************/
+
+//==================================================================
+KCharSelectTable::KCharSelectTable( QWidget *parent, const char *name, const QString &_font,
+ const QChar &_chr, int _tableNum )
+ : QGridView( parent, name ), vFont( _font ), vChr( _chr ),
+ vTableNum( _tableNum ), vPos( 0, 0 ), focusItem( _chr ), focusPos( 0, 0 ), d(0)
+{
+ setBackgroundColor( colorGroup().base() );
+
+ setCellWidth( 20 );
+ setCellHeight( 25 );
+
+ setNumCols( 32 );
+ setNumRows( 8 );
+
+ repaintContents( false );
+
+ setToolTips();
+
+ setFocusPolicy( QWidget::StrongFocus );
+ setBackgroundMode( QWidget::NoBackground );
+}
+
+//==================================================================
+void KCharSelectTable::setFont( const QString &_font )
+{
+ vFont = _font;
+ repaintContents( false );
+
+ setToolTips();
+}
+
+//==================================================================
+void KCharSelectTable::setChar( const QChar &_chr )
+{
+ vChr = _chr;
+ repaintContents( false );
+}
+
+//==================================================================
+void KCharSelectTable::setTableNum( int _tableNum )
+{
+ focusItem = QChar( _tableNum * 256 );
+
+ vTableNum = _tableNum;
+ repaintContents( false );
+
+ setToolTips();
+}
+
+//==================================================================
+QSize KCharSelectTable::sizeHint() const
+{
+ int w = cellWidth();
+ int h = cellHeight();
+
+ w *= numCols();
+ h *= numRows();
+
+ return QSize( w, h );
+}
+
+//==================================================================
+void KCharSelectTable::resizeEvent( QResizeEvent * e )
+{
+ const int new_w = (e->size().width() - 2*(margin()+frameWidth())) / numCols();
+ const int new_h = (e->size().height() - 2*(margin()+frameWidth())) / numRows();
+
+ if( new_w != cellWidth())
+ setCellWidth( new_w );
+ if( new_h != cellHeight())
+ setCellHeight( new_h );
+
+ setToolTips();
+}
+
+//==================================================================
+void KCharSelectTable::paintCell( class QPainter* p, int row, int col )
+{
+ const int w = cellWidth();
+ const int h = cellHeight();
+ const int x2 = w - 1;
+ const int y2 = h - 1;
+
+ //if( row == 0 && col == 0 ) {
+ // printf("Repaint %d\n", temp++);
+ // fflush( stdout );
+ // }
+
+ QFont font = QFont( vFont );
+ font.setPixelSize( int(.7 * h) );
+
+ unsigned short c = vTableNum * 256;
+ c += row * numCols();
+ c += col;
+
+ if ( c == vChr.unicode() ) {
+ p->setBrush( QBrush( colorGroup().highlight() ) );
+ p->setPen( NoPen );
+ p->drawRect( 0, 0, w, h );
+ p->setPen( colorGroup().highlightedText() );
+ vPos = QPoint( col, row );
+ } else {
+ QFontMetrics fm = QFontMetrics( font );
+ if( fm.inFont( c ) )
+ p->setBrush( QBrush( colorGroup().base() ) );
+ else
+ p->setBrush( QBrush( colorGroup().button() ) );
+ p->setPen( NoPen );
+ p->drawRect( 0, 0, w, h );
+ p->setPen( colorGroup().text() );
+ }
+
+ if ( c == focusItem.unicode() && hasFocus() ) {
+ style().drawPrimitive( QStyle::PE_FocusRect, p, QRect( 2, 2, w - 4, h - 4 ),
+ colorGroup() );
+ focusPos = QPoint( col, row );
+ }
+
+ p->setFont( font );
+
+ p->drawText( 0, 0, x2, y2, AlignHCenter | AlignVCenter, QString( QChar( c ) ) );
+
+ p->setPen( colorGroup().text() );
+ p->drawLine( x2, 0, x2, y2 );
+ p->drawLine( 0, y2, x2, y2 );
+
+ if ( row == 0 )
+ p->drawLine( 0, 0, x2, 0 );
+ if ( col == 0 )
+ p->drawLine( 0, 0, 0, y2 );
+}
+
+//==================================================================
+void KCharSelectTable::mouseMoveEvent( QMouseEvent *e )
+{
+ const int row = rowAt( e->y() );
+ const int col = columnAt( e->x() );
+ if ( row >= 0 && row < numRows() && col >= 0 && col < numCols() ) {
+ const QPoint oldPos = vPos;
+
+ vPos.setX( col );
+ vPos.setY( row );
+
+ vChr = QChar( vTableNum * 256 + numCols() * vPos.y() + vPos.x() );
+
+ const QPoint oldFocus = focusPos;
+
+ focusPos = vPos;
+ focusItem = vChr;
+
+ repaintCell( oldFocus.y(), oldFocus.x(), true );
+ repaintCell( oldPos.y(), oldPos.x(), true );
+ repaintCell( vPos.y(), vPos.x(), true );
+
+ emit highlighted( vChr );
+ emit highlighted();
+
+ emit focusItemChanged( focusItem );
+ emit focusItemChanged();
+ }
+}
+
+//==================================================================
+void KCharSelectTable::keyPressEvent( QKeyEvent *e )
+{
+ switch ( e->key() ) {
+ case Key_Left:
+ gotoLeft();
+ break;
+ case Key_Right:
+ gotoRight();
+ break;
+ case Key_Up:
+ gotoUp();
+ break;
+ case Key_Down:
+ gotoDown();
+ break;
+ case Key_Next:
+ emit tableDown();
+ break;
+ case Key_Prior:
+ emit tableUp();
+ break;
+ case Key_Space:
+ emit activated( ' ' );
+ emit activated();
+ emit highlighted( ' ' );
+ emit highlighted();
+ break;
+ case Key_Enter: case Key_Return: {
+ const QPoint oldPos = vPos;
+
+ vPos = focusPos;
+ vChr = focusItem;
+
+ repaintCell( oldPos.y(), oldPos.x(), true );
+ repaintCell( vPos.y(), vPos.x(), true );
+
+ emit activated( vChr );
+ emit activated();
+ emit highlighted( vChr );
+ emit highlighted();
+ } break;
+ }
+}
+
+//==================================================================
+void KCharSelectTable::gotoLeft()
+{
+ if ( focusPos.x() > 0 ) {
+ const QPoint oldPos = focusPos;
+
+ focusPos.setX( focusPos.x() - 1 );
+
+ focusItem = QChar( vTableNum * 256 + numCols() * focusPos.y() + focusPos.x() );
+
+ repaintCell( oldPos.y(), oldPos.x(), true );
+ repaintCell( focusPos.y(), focusPos.x(), true );
+
+ emit focusItemChanged( vChr );
+ emit focusItemChanged();
+ }
+}
+
+//==================================================================
+void KCharSelectTable::gotoRight()
+{
+ if ( focusPos.x() < numCols()-1 ) {
+ const QPoint oldPos = focusPos;
+
+ focusPos.setX( focusPos.x() + 1 );
+
+ focusItem = QChar( vTableNum * 256 + numCols() * focusPos.y() + focusPos.x() );
+
+ repaintCell( oldPos.y(), oldPos.x(), true );
+ repaintCell( focusPos.y(), focusPos.x(), true );
+
+ emit focusItemChanged( vChr );
+ emit focusItemChanged();
+ }
+}
+
+//==================================================================
+void KCharSelectTable::gotoUp()
+{
+ if ( focusPos.y() > 0 ) {
+ const QPoint oldPos = focusPos;
+
+ focusPos.setY( focusPos.y() - 1 );
+
+ focusItem = QChar( vTableNum * 256 + numCols() * focusPos.y() + focusPos.x() );
+
+ repaintCell( oldPos.y(), oldPos.x(), true );
+ repaintCell( focusPos.y(), focusPos.x(), true );
+
+ emit focusItemChanged( vChr );
+ emit focusItemChanged();
+ }
+}
+
+//==================================================================
+void KCharSelectTable::gotoDown()
+{
+ if ( focusPos.y() < numRows()-1 ) {
+ const QPoint oldPos = focusPos;
+
+ focusPos.setY( focusPos.y() + 1 );
+
+ focusItem = QChar( vTableNum * 256 + numCols() * focusPos.y() + focusPos.x() );
+
+ repaintCell( oldPos.y(), oldPos.x(), true );
+ repaintCell( focusPos.y(), focusPos.x(), true );
+
+ emit focusItemChanged( vChr );
+ emit focusItemChanged();
+ }
+}
+
+//==================================================================
+void KCharSelectTable::setToolTips()
+{
+ const int rowCount = numRows();
+ const int colCount = numCols();
+ for( int i=0 ; i< rowCount; ++i )
+ {
+ for( int j=0; j< colCount; ++j )
+ {
+ const QRect r( cellWidth()*j, cellHeight()*i, cellWidth(), cellHeight() );
+ QToolTip::remove(this,r);
+ const ushort uni = vTableNum * 256 + numCols()*i + j;
+ QString s;
+ s.sprintf( "%04X", uint( uni ) );
+ QString character; // Character (which sometimes need to be escaped)
+ switch ( uni )
+ {
+ case 0x3c: character = "&lt;"; break;
+ case 0x3e: character = "&gt;"; break;
+ case 0x26: character = "&amp;"; break;
+ case 0x27: character = "&apos;"; break;
+ case 0x22: character = "&quot;"; break;
+ default: character = QChar( uni ); break;
+ }
+ QToolTip::add(this, r, i18n( "Character","<qt><font size=\"+4\" face=\"%1\">%2</font><br>Unicode code point: U+%3<br>(In decimal: %4)<br>(Character: %5)</qt>" ).arg( vFont ).arg( character ).arg( s ).arg( uni ).arg( character ) );
+ }
+ }
+}
+
+/******************************************************************/
+/* Class: KCharSelect */
+/******************************************************************/
+
+//==================================================================
+KCharSelect::KCharSelect( QWidget *parent, const char *name, const QString &_font, const QChar &_chr, int _tableNum )
+ : QVBox( parent, name ), d(new KCharSelectPrivate)
+{
+ setSpacing( KDialog::spacingHint() );
+ QHBox* const bar = new QHBox( this );
+ bar->setSpacing( KDialog::spacingHint() );
+
+ QLabel* const lFont = new QLabel( i18n( "Font:" ), bar );
+ lFont->resize( lFont->sizeHint() );
+ lFont->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
+ lFont->setMaximumWidth( lFont->sizeHint().width() );
+
+ fontCombo = new QComboBox( true, bar );
+ fillFontCombo();
+ fontCombo->resize( fontCombo->sizeHint() );
+
+ connect( fontCombo, SIGNAL( activated( const QString & ) ), this, SLOT( fontSelected( const QString & ) ) );
+
+ QLabel* const lTable = new QLabel( i18n( "Table:" ), bar );
+ lTable->resize( lTable->sizeHint() );
+ lTable->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
+ lTable->setMaximumWidth( lTable->sizeHint().width() );
+
+ tableSpinBox = new QSpinBox( 0, 255, 1, bar );
+ tableSpinBox->resize( tableSpinBox->sizeHint() );
+
+ connect( tableSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT( tableChanged( int ) ) );
+
+ QLabel* const lUnicode = new QLabel( i18n( "&Unicode code point:" ), bar );
+ lUnicode->resize( lUnicode->sizeHint() );
+ lUnicode->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
+ lUnicode->setMaximumWidth( lUnicode->sizeHint().width() );
+
+ const QRegExp rx( "[a-fA-F0-9]{1,4}" );
+ QValidator* const validator = new QRegExpValidator( rx, this );
+
+ d->unicodeLine = new KLineEdit( bar );
+ d->unicodeLine->setValidator(validator);
+ lUnicode->setBuddy(d->unicodeLine);
+ d->unicodeLine->resize( d->unicodeLine->sizeHint() );
+ slotUpdateUnicode(_chr);
+
+ connect( d->unicodeLine, SIGNAL( returnPressed() ), this, SLOT( slotUnicodeEntered() ) );
+
+ charTable = new KCharSelectTable( this, name, _font.isEmpty() ? QVBox::font().family() : _font, _chr, _tableNum );
+ const QSize sz( charTable->contentsWidth() + 4 ,
+ charTable->contentsHeight() + 4 );
+ charTable->resize( sz );
+ //charTable->setMaximumSize( sz );
+ charTable->setMinimumSize( sz );
+ charTable->setHScrollBarMode( QScrollView::AlwaysOff );
+ charTable->setVScrollBarMode( QScrollView::AlwaysOff );
+
+ setFont( _font.isEmpty() ? QVBox::font().family() : _font );
+ setTableNum( _tableNum );
+
+ connect( charTable, SIGNAL( highlighted( const QChar & ) ), this, SLOT( slotUpdateUnicode( const QChar & ) ) );
+ connect( charTable, SIGNAL( highlighted( const QChar & ) ), this, SLOT( charHighlighted( const QChar & ) ) );
+ connect( charTable, SIGNAL( highlighted() ), this, SLOT( charHighlighted() ) );
+ connect( charTable, SIGNAL( activated( const QChar & ) ), this, SLOT( charActivated( const QChar & ) ) );
+ connect( charTable, SIGNAL( activated() ), this, SLOT( charActivated() ) );
+ connect( charTable, SIGNAL( focusItemChanged( const QChar & ) ),
+ this, SLOT( charFocusItemChanged( const QChar & ) ) );
+ connect( charTable, SIGNAL( focusItemChanged() ), this, SLOT( charFocusItemChanged() ) );
+ connect( charTable, SIGNAL( tableUp() ), this, SLOT( charTableUp() ) );
+ connect( charTable, SIGNAL( tableDown() ), this, SLOT( charTableDown() ) );
+
+ connect( charTable, SIGNAL(doubleClicked()),this,SLOT(slotDoubleClicked()));
+
+ setFocusPolicy( QWidget::StrongFocus );
+ setFocusProxy( charTable );
+}
+
+KCharSelect::~KCharSelect()
+{
+ delete d;
+}
+
+//==================================================================
+QSize KCharSelect::sizeHint() const
+{
+ return QVBox::sizeHint();
+}
+
+//==================================================================
+void KCharSelect::setFont( const QString &_font )
+{
+ const QValueList<QString>::Iterator it = fontList.find( _font );
+ if ( it != fontList.end() ) {
+ QValueList<QString>::Iterator it2 = fontList.begin();
+ int pos = 0;
+ for ( ; it != it2; ++it2, ++pos);
+ fontCombo->setCurrentItem( pos );
+ charTable->setFont( _font );
+ }
+ else
+ kdWarning() << "Can't find Font: " << _font << endl;
+}
+
+//==================================================================
+void KCharSelect::setChar( const QChar &_chr )
+{
+ charTable->setChar( _chr );
+ slotUpdateUnicode( _chr );
+}
+
+//==================================================================
+void KCharSelect::setTableNum( int _tableNum )
+{
+ tableSpinBox->setValue( _tableNum );
+ charTable->setTableNum( _tableNum );
+}
+
+//==================================================================
+void KCharSelect::fillFontCombo()
+{
+ if ( !fontDataBase ) {
+ fontDataBase = new QFontDatabase();
+ qAddPostRoutine( cleanupFontDatabase );
+ }
+ fontList=fontDataBase->families();
+ fontCombo->insertStringList( fontList );
+}
+
+//==================================================================
+void KCharSelect::fontSelected( const QString &_font )
+{
+ charTable->setFont( _font );
+ emit fontChanged( _font );
+}
+
+//==================================================================
+void KCharSelect::tableChanged( int _value )
+{
+ charTable->setTableNum( _value );
+}
+
+//==================================================================
+void KCharSelect::slotUnicodeEntered( )
+{
+ const QString s = d->unicodeLine->text();
+ if (s.isEmpty())
+ return;
+
+ bool ok;
+ const int uc = s.toInt(&ok, 16);
+ if (!ok)
+ return;
+
+ const int table = uc / 256;
+ charTable->setTableNum( table );
+ tableSpinBox->setValue(table);
+ const QChar ch(uc);
+ charTable->setChar( ch );
+ charActivated( ch );
+}
+
+void KCharSelect::slotUpdateUnicode( const QChar &c )
+{
+ const int uc = c.unicode();
+ QString s;
+ s.sprintf("%04X", uc);
+ d->unicodeLine->setText(s);
+}
+
+void KCharSelectTable::virtual_hook( int, void*)
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void KCharSelect::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
diff --git a/kdeui/kcharselect.h b/kdeui/kcharselect.h
new file mode 100644
index 000000000..a511e5952
--- /dev/null
+++ b/kdeui/kcharselect.h
@@ -0,0 +1,266 @@
+/* This file is part of the KDE libraries
+
+ Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef kcharselect_h
+#define kcharselect_h
+
+#include <qgridview.h>
+#include <qvbox.h>
+#include <qcombobox.h>
+#include <qspinbox.h>
+#include <qstring.h>
+#include <qpoint.h>
+#include <qstringlist.h>
+
+#include <kdelibs_export.h>
+
+class QFont;
+class QFontDatabase;
+class QMouseEvent;
+class QSpinBox;
+class KCharSelectTablePrivate;
+class KCharSelectPrivate;
+
+/**
+ * @short Character selection table
+ *
+ * A table widget which displays the characters of a font. Internally
+ * used by KCharSelect. See the KCharSelect documentation for further
+ * details.
+ *
+ * @author Reginald Stadlbauer <reggie@kde.org>
+ */
+
+class KDEUI_EXPORT KCharSelectTable : public QGridView
+{
+ Q_OBJECT
+
+public:
+ KCharSelectTable( QWidget *parent, const char *name, const QString &_font,
+ const QChar &_chr, int _tableNum );
+
+ virtual QSize sizeHint() const;
+ virtual void resizeEvent( QResizeEvent * );
+
+ virtual void setFont( const QString &_font );
+ virtual void setChar( const QChar &_chr );
+ virtual void setTableNum( int _tableNum );
+
+ virtual QChar chr() { return vChr; }
+
+protected:
+ virtual void paintCell( class QPainter *p, int row, int col );
+
+ virtual void mousePressEvent( QMouseEvent *e ) { mouseMoveEvent( e ); }
+ virtual void mouseDoubleClickEvent ( QMouseEvent *e ){ mouseMoveEvent( e ); emit doubleClicked();}
+ virtual void mouseReleaseEvent( QMouseEvent *e ) { mouseMoveEvent( e ); emit activated( chr() ); emit activated(); }
+ virtual void mouseMoveEvent( QMouseEvent *e );
+
+ virtual void keyPressEvent( QKeyEvent *e );
+
+ void gotoLeft();
+ void gotoRight();
+ void gotoUp();
+ void gotoDown();
+
+ QString vFont;
+ QChar vChr;
+ int vTableNum;
+ QPoint vPos;
+ QChar focusItem;
+ QPoint focusPos;
+ int temp;
+
+signals:
+ void highlighted( const QChar &c );
+ void highlighted();
+ void activated( const QChar &c );
+ void activated();
+ void focusItemChanged();
+ void focusItemChanged( const QChar &c );
+ void tableUp();
+ void tableDown();
+ void doubleClicked();
+
+private:
+ virtual void setFont(const QFont &f) { QGridView::setFont(f); }
+ void setToolTips();
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KCharSelectTablePrivate* const d;
+};
+
+/**
+ * @short Character selection widget
+ *
+ * This widget allows the user to select a character of a
+ * specified font in a table
+ *
+ * \image html kcharselect.png "Character Selection Widget"
+ *
+ * You can specify the font whose characters should be displayed via
+ * setFont() or in the constructor. Using enableFontCombo() you can allow the
+ * user to choose the font from a combob-box. As only 256 characters
+ * are displayed at once in the table, using the spinbox on the top
+ * the user can choose starting from which character the table
+ * displays them. This spinbox also can be enabled or disabled using
+ * enableTableSpinBox().
+ *
+ * KCharSelect supports keyboard and mouse navigation. Click+Move
+ * always selects the character below the mouse cursor. Using the
+ * arrow keys moves the focus mark around and pressing RETURN
+ * or SPACE selects the cell which contains the focus mark.
+ *
+ * To get the current selected character, use the chr()
+ * method. You can set the character which should be displayed with
+ * setChar() and the table number which should be displayed with
+ * setTableNum().
+ *
+ * @author Reginald Stadlbauer <reggie@kde.org>
+ */
+
+class KDEUI_EXPORT KCharSelect : public QVBox
+{
+ Q_OBJECT
+ Q_PROPERTY( QString fontFamily READ font WRITE setFont )
+ Q_PROPERTY( int tableNum READ tableNum WRITE setTableNum )
+ Q_PROPERTY( bool fontComboEnabled READ isFontComboEnabled WRITE enableFontCombo )
+ Q_PROPERTY( bool tableSpinBoxEnabled READ isTableSpinBoxEnabled WRITE enableTableSpinBox )
+
+public:
+ /**
+ * Constructor. @p font specifies which font should be displayed, @p
+ * chr which character should be selected and @p tableNum specifies
+ * the number of the table which should be displayed.
+ */
+ KCharSelect( QWidget *parent, const char *name,
+ const QString &font = QString::null, const QChar &chr = ' ', int tableNum = 0 );
+ ~KCharSelect();
+ /**
+ * Reimplemented.
+ */
+ virtual QSize sizeHint() const;
+
+ /**
+ * Sets the font which is displayed to @p font
+ */
+ virtual void setFont( const QString &font );
+
+ /**
+ * Sets the currently selected character to @p chr.
+ */
+ virtual void setChar( const QChar &chr );
+
+ /**
+ * Sets the currently displayed table to @p tableNum.
+ */
+ virtual void setTableNum( int tableNum );
+
+ /**
+ * Returns the currently selected character.
+ */
+ virtual QChar chr() const { return charTable->chr(); }
+
+ /**
+ * Returns the currently displayed font.
+ */
+ virtual QString font() const { return fontCombo->currentText(); }
+
+ /**
+ * Returns the currently displayed table
+ */
+ virtual int tableNum() const { return tableSpinBox->value(); }
+
+ /**
+ * If @p e is set to true, the combobox which allows the user to
+ * select the font which should be displayed is enabled, else
+ * disabled.
+ */
+ virtual void enableFontCombo( bool e ) { fontCombo->setEnabled( e ); }
+
+ /**
+
+ * If @p e is set to true, the spinbox which allows the user to
+ * specify which characters of the font should be displayed, is
+ * enabled, else disabled.
+ */
+ virtual void enableTableSpinBox( bool e ) { tableSpinBox->setEnabled( e ); }
+
+ /**
+ * Returns wether the font combobox on the top is enabled or
+ * disabled.
+ *
+ * @see enableFontCombo()
+ */
+ virtual bool isFontComboEnabled() const { return fontCombo->isEnabled(); }
+
+ /**
+ * Returns wether the table spinbox on the top is enabled or
+ * disabled.
+ *
+ * @see enableTableSpinBox()
+ */
+ virtual bool isTableSpinBoxEnabled() const { return tableSpinBox->isEnabled(); }
+
+protected:
+ virtual void fillFontCombo();
+ static void cleanupFontDatabase();
+
+ QComboBox *fontCombo;
+ QSpinBox *tableSpinBox;
+ KCharSelectTable *charTable;
+ QStringList fontList;
+ static QFontDatabase * fontDataBase;
+
+protected slots:
+ void fontSelected( const QString &_font );
+ void tableChanged( int _value );
+ void charHighlighted( const QChar &c ) { emit highlighted( c ); }
+ void charHighlighted() { emit highlighted(); }
+ void charActivated( const QChar &c ) { emit activated( c ); }
+ void charActivated() { emit activated(); }
+ void charFocusItemChanged() { emit focusItemChanged(); }
+ void charFocusItemChanged( const QChar &c ) { emit focusItemChanged( c ); }
+ void charTableUp() { if ( tableNum() < 255 ) setTableNum( tableNum() + 1 ); }
+ void charTableDown() { if ( tableNum() > 0 ) setTableNum( tableNum() - 1 ); }
+ void slotDoubleClicked() { emit doubleClicked(); }
+ void slotUnicodeEntered();
+ void slotUpdateUnicode( const QChar &c );
+signals:
+ void highlighted( const QChar &c );
+ void highlighted();
+ void activated( const QChar &c );
+ void activated();
+ void fontChanged( const QString &_font );
+ void focusItemChanged();
+ void focusItemChanged( const QChar &c );
+ void doubleClicked();
+
+private:
+ virtual void setFont(const QFont &f) { QVBox::setFont(f); }
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KCharSelectPrivate;
+ KCharSelectPrivate* const d;
+};
+
+#endif
diff --git a/kdeui/kcmenumngr.cpp b/kdeui/kcmenumngr.cpp
new file mode 100644
index 000000000..6255a764d
--- /dev/null
+++ b/kdeui/kcmenumngr.cpp
@@ -0,0 +1,129 @@
+/*
+ * This file is part of the KDE Libraries
+ * Copyright (C) 1999 Matthias Ettrich <ettrich@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#include <qwidget.h>
+#include <qpopupmenu.h>
+#include "kcmenumngr.h"
+#include "kglobal.h"
+#include "kconfig.h"
+#include "kshortcut.h"
+
+#undef KeyPress
+#undef None
+
+template class QPtrDict<QPopupMenu>;
+
+KContextMenuManager* KContextMenuManager::manager = 0;
+
+KContextMenuManager::KContextMenuManager( QObject* parent, const char* name )
+ : QObject( parent, name)
+{
+ KConfigGroupSaver saver ( KGlobal::config(), QString::fromLatin1("Shortcuts") ) ;
+ menuKey = KShortcut( saver.config()->readEntry(QString::fromLatin1("PopupContextMenu"), QString::fromLatin1("Menu") ) ).keyCodeQt();
+ saver.config()->setGroup( QString::fromLatin1("ContextMenus") ) ;
+ showOnPress = saver.config()->readBoolEntry(QString::fromLatin1("ShowOnPress"), true );
+}
+
+KContextMenuManager::~KContextMenuManager()
+{
+}
+
+
+bool KContextMenuManager::showOnButtonPress( void )
+{
+ if ( !manager )
+ manager = new KContextMenuManager;
+ return manager->showOnPress;
+}
+
+
+void KContextMenuManager::insert( QWidget* widget, QPopupMenu* popup )
+{
+ if ( !manager )
+ manager = new KContextMenuManager;
+
+ manager->connect( widget, SIGNAL( destroyed() ), manager, SLOT( widgetDestroyed() ) );
+ manager->menus.insert( widget, popup );
+ widget->installEventFilter( manager );
+}
+
+bool KContextMenuManager::eventFilter( QObject *o, QEvent * e)
+{
+ QPopupMenu* popup = 0;
+ QPoint pos;
+ switch ( e->type() ) {
+ case QEvent::MouseButtonPress:
+ if (((QMouseEvent*) e )->button() != RightButton )
+ break;
+ if ( !showOnPress )
+ return true; // eat event for safety
+ popup = menus[o];
+ pos = ((QMouseEvent*) e )->globalPos();
+ break;
+ case QEvent::MouseButtonRelease:
+ if ( showOnPress || ((QMouseEvent*) e )->button() != RightButton )
+ break;
+ popup = menus[o];
+ pos = ((QMouseEvent*) e )->globalPos();
+ break;
+ case QEvent::KeyPress:
+ {
+ if ( !o->isWidgetType() )
+ break;
+ QKeyEvent *k = (QKeyEvent *)e;
+ int key = k->key();
+ if ( k->state() & ShiftButton )
+ key |= SHIFT;
+ if ( k->state() & ControlButton )
+ key |= CTRL;
+ if ( k->state() & AltButton )
+ key |= ALT;
+ if ( key != menuKey )
+ break;
+ popup = menus[o];
+ if ( popup ) {
+ QWidget* w = (QWidget*) o ;
+
+ // ### workaround
+ pos = w->mapToGlobal( w->rect().center() );
+ // with later Qt snapshot
+ // pos = w->mapToGlobal( w->microFocusHint().center() );
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ if ( popup ) {
+ popup->popup( pos );
+ return true;
+ }
+
+ return false;
+}
+
+void KContextMenuManager::widgetDestroyed()
+{
+ if ( menus.find( (QObject*)sender() ) )
+ menus.remove( (QObject*)sender() );
+}
+
+#include "kcmenumngr.moc"
diff --git a/kdeui/kcmenumngr.h b/kdeui/kcmenumngr.h
new file mode 100644
index 000000000..36a2580ad
--- /dev/null
+++ b/kdeui/kcmenumngr.h
@@ -0,0 +1,114 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Matthias Ettrich (ettrich@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCMENUMNGR_H
+#define KCMENUMNGR_H
+
+
+class QWidget;
+class QPopupMenu;
+class KContextMenuManagerPrivate;
+#include <qobject.h>
+#include <qptrdict.h>
+#include <qkeysequence.h>
+
+#include <kdelibs_export.h>
+
+/**
+@short Convenience class to mangage context menus
+@author Matthias Ettrich <ettrich@kde.org>
+
+KContextMenuManager manages configurable context popup menus. Instead
+of reimplementing QWidget::mousePressEvent() or
+ QWidget::mouseReleaseEvent() and/or QWidget::keyPressEvent(), simply
+create the popup menu and insert it into the context menu manager with
+the static function insert().
+
+Example:
+\code
+ KContextMenuManager::insert( myWidget, myPopupMenu );
+\endcode
+
+
+Context menus are invoked with either a special shortcut key (usually
+the menu key) or the right mouse button.
+
+Menus are configurable in the [ContextMenus] group of the application's
+configuration file, usually in kdeglobals:
+\code
+ [ContextMenus]
+ ShowOnPress=true|false
+\endcode
+
+@p ShowOnPress defines whether the menu shall be shown on mouse
+press or on mouse release.
+
+The shortcut key to invoke the context menu is defined in the standard
+[Keys] section of the application configuration:
+\code
+ [Keys]
+ ...
+ PopupContextMenu=Menu
+ ...
+\endcode
+The key can be configured with the standard keys module in the KDE control center.
+
+If the popup menu is invoked with the keyboard shortcut, it's shown at
+the position of the micro focus hint of the widget ( QWidget::microFocusHint() ).
+*/
+
+class KDEUI_EXPORT KContextMenuManager : public QObject
+{
+ Q_OBJECT
+public:
+
+ /**
+ Makes @p popup a context popup menu for widget @p widget.
+
+ Ownership of the popup menu is not transferred to the context
+ menu manager.
+ */
+ static void insert( QWidget* widget, QPopupMenu* popup );
+
+ /**
+ * Use this method to get information about when a popup menu
+ * should be activated. This can be useful if the popup menu is
+ * to be activated from a listview.
+ *
+ * @return true if the menu should be made visible on a button press
+ * or false after a button press-release sequence.
+ */
+ static bool showOnButtonPress( void );
+
+private slots:
+ void widgetDestroyed();
+private:
+ KContextMenuManager( QObject* parent = 0, const char* name = 0);
+ ~KContextMenuManager();
+ bool eventFilter( QObject *, QEvent * );
+ QPtrDict<QPopupMenu> menus;
+ bool showOnPress;
+ QKeySequence menuKey;
+ static KContextMenuManager* manager;
+ friend class I_really_like_this_class; // avoid warning
+
+ KContextMenuManagerPrivate *d;
+};
+
+#endif
diff --git a/kdeui/kcmodule.cpp b/kdeui/kcmodule.cpp
new file mode 100644
index 000000000..43b2cdd95
--- /dev/null
+++ b/kdeui/kcmodule.cpp
@@ -0,0 +1,220 @@
+/*
+ This file is part of the KDE libraries
+
+<<<Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be>
+ Copyright (C) 2004 Frans Englich <frans.englich@telia.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include <qlayout.h>
+
+#include <kaboutdata.h>
+#include <kconfigskeleton.h>
+#include <kconfigdialogmanager.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kinstance.h>
+#include <klocale.h>
+
+#include "kcmodule.h"
+#include "kcmodule.moc"
+
+class KCModulePrivate
+{
+public:
+ KCModulePrivate():
+ _about( 0 ),
+ _useRootOnlyMsg( false ),
+ _hasOwnInstance( true ),
+ _unmanagedWidgetChangeState( false )
+ { }
+
+ KInstance *_instance;
+ KAboutData *_about;
+ QString _rootOnlyMsg;
+ bool _useRootOnlyMsg;
+ bool _hasOwnInstance;
+ QPtrList<KConfigDialogManager> managers;
+ QString _quickHelp;
+
+ // this member is used to record the state on non-automatically
+ // managed widgets, allowing for mixed KConfigXT-drive and manual
+ // widgets to coexist peacefully and do the correct thing with
+ // the changed(bool) signal
+ bool _unmanagedWidgetChangeState;
+};
+
+KCModule::KCModule(QWidget *parent, const char *name, const QStringList &)
+ : QWidget(parent, name)
+{
+ init();
+ if (name && strlen(name)) {
+ d->_instance = new KInstance(name);
+ KGlobal::locale()->insertCatalogue(name);
+ } else
+ d->_instance = new KInstance("kcmunnamed");
+ KGlobal::setActiveInstance(this->instance());
+
+ d->managers.setAutoDelete( true );
+
+}
+
+KCModule::KCModule(KInstance *instance, QWidget *parent, const QStringList & )
+ : QWidget(parent, instance ? instance->instanceName().data() : 0)
+{
+ init();
+ d->_instance = instance;
+
+ if (instance)
+ {
+ KGlobal::locale()->insertCatalogue(instance->instanceName());
+ }
+
+ d->_hasOwnInstance = false;
+ KGlobal::setActiveInstance(this->instance());
+}
+
+void KCModule::init()
+{
+ d = new KCModulePrivate;
+ _btn = Help|Default|Apply;
+}
+
+KConfigDialogManager* KCModule::addConfig( KConfigSkeleton *config, QWidget* widget )
+{
+ KConfigDialogManager* manager = new KConfigDialogManager( widget, config, name() );
+ connect( manager, SIGNAL( widgetModified() ), SLOT( widgetChanged() ));
+ d->managers.append( manager );
+ return manager;
+}
+
+KCModule::~KCModule()
+{
+ if (d->_hasOwnInstance)
+ delete d->_instance;
+ delete d->_about;
+ delete d;
+}
+
+void KCModule::load()
+{
+ KConfigDialogManager* manager;
+ for( manager = d->managers.first(); manager; manager = d->managers.next() )
+ manager->updateWidgets();
+}
+
+void KCModule::save()
+{
+ KConfigDialogManager* manager;
+ for( manager = d->managers.first(); manager; manager = d->managers.next() )
+ manager->updateSettings();
+ emit( changed( false ));
+}
+
+void KCModule::defaults()
+{
+ KConfigDialogManager* manager;
+ for( manager = d->managers.first(); manager; manager = d->managers.next() )
+ manager->updateWidgetsDefault();
+}
+
+void KCModule::widgetChanged()
+{
+ emit changed(d->_unmanagedWidgetChangeState || managedWidgetChangeState());
+}
+
+bool KCModule::managedWidgetChangeState() const
+{
+ KConfigDialogManager* manager;
+ for( manager = d->managers.first(); manager; manager = d->managers.next() )
+ {
+ if ( manager->hasChanged() )
+ return true;
+ }
+
+ return false;
+}
+
+void KCModule::unmanagedWidgetChangeState(bool changed)
+{
+ d->_unmanagedWidgetChangeState = changed;
+ widgetChanged();
+}
+
+const KAboutData *KCModule::aboutData() const
+{
+ return d->_about;
+}
+
+void KCModule::setAboutData( KAboutData* about )
+{
+ delete d->_about;
+ d->_about = about;
+}
+
+void KCModule::setRootOnlyMsg(const QString& msg)
+{
+ d->_rootOnlyMsg = msg;
+}
+
+QString KCModule::rootOnlyMsg() const
+{
+ return d->_rootOnlyMsg;
+}
+
+void KCModule::setUseRootOnlyMsg(bool on)
+{
+ d->_useRootOnlyMsg = on;
+}
+
+bool KCModule::useRootOnlyMsg() const
+{
+ return d->_useRootOnlyMsg;
+}
+
+void KCModule::changed()
+{
+ emit changed(true);
+}
+
+KInstance *KCModule::instance() const
+{
+ return d->_instance;
+}
+
+void KCModule::setQuickHelp( const QString& help )
+{
+ d->_quickHelp = help;
+ emit( quickHelpChanged() );
+}
+
+QString KCModule::quickHelp() const
+{
+ return d->_quickHelp;
+}
+
+
+const QPtrList<KConfigDialogManager>& KCModule::configs() const
+{
+ return d->managers;
+}
+
+void KCModule::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+// vim: sw=4 et sts=4
diff --git a/kdeui/kcmodule.h b/kdeui/kcmodule.h
new file mode 100644
index 000000000..a8297c4ce
--- /dev/null
+++ b/kdeui/kcmodule.h
@@ -0,0 +1,361 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (c) 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#ifndef KCMODULE_H
+#define KCMODULE_H
+
+#include <qwidget.h>
+
+#include <kdelibs_export.h>
+
+class QStringList;
+
+class KAboutData;
+class KConfigDialogManager;
+class KConfigSkeleton;
+class KCModulePrivate;
+class KInstance;
+
+/**
+ * The base class for control center modules.
+ *
+ * Starting from KDE 2.0, control center modules are realized as shared
+ * libraries that are loaded into the control center at runtime.
+ *
+ * The module in principle is a simple widget displaying the
+ * item to be changed. The module has a very small interface.
+ *
+ * All the necessary glue logic and the GUI bells and whistles
+ * are provided by the control center and must not concern
+ * the module author.
+ *
+ * To write a config module, you have to create a library
+ * that contains at one factory function like this:
+ *
+ * \code
+ * #include <kgenericfactory.h>
+ *
+ * typedef KGenericFactory<YourKCModule, QWidget> YourKCModuleFactory;
+ * K_EXPORT_COMPONENT_FACTORY( yourLibName, YourKCModuleFactory("name_of_the_po_file") );
+ * \endcode
+ *
+ * The parameter "name_of_the_po_file" has to correspond with the messages target
+ * that you created in your Makefile.am.
+ *
+ * See http://developer.kde.org/documentation/other/kcm_howto.html
+ * for more detailed documentation.
+ *
+ * @author Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
+ */
+class KDEUI_EXPORT KCModule : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ /**
+ * An enumeration type for the buttons used by this module.
+ * You should only use Help, Default and Apply. The rest is obsolete.
+ *
+ * @see KCModule::buttons @see KCModule::setButtons
+ */
+ enum Button {Help=1, Default=2, Apply=16,
+ Reset=4, /* obsolete, do not use! */
+ Cancel=8, /* obsolete, do not use! */
+ Ok=32, /* obsolete, do not use! */
+ SysDefault=64 /* obsolete, do not use! */ };
+
+ /*
+ * Base class for all KControlModules.
+ * Make sure you have a QStringList argument in your
+ * implementation.
+ */
+ KCModule(QWidget *parent=0, const char *name=0, const QStringList &args=QStringList() );
+
+ KCModule(KInstance *instance, QWidget *parent=0, const QStringList &args=QStringList() );
+
+ /*
+ * Destroys the module.
+ */
+ ~KCModule();
+
+ /**
+ * Load the configuration data into the module.
+ *
+ * The load method sets the user interface elements of the
+ * module to reflect the current settings stored in the
+ * configuration files.
+ *
+ * This method is invoked whenever the module should read its configuration
+ * (most of the times from a config file) and update the user interface.
+ * This happens when the user clicks the "Reset" button in the control
+ * center, to undo all of his changes and restore the currently valid
+ * settings.
+ *
+ * If you use KConfigXT, loading is taken care of automatically and
+ * you do not need to do it manually. However, if you for some reason reimplement it and
+ * also are using KConfigXT, you must call this function otherwise the loading of KConfigXT
+ * options will not work.
+ *
+ */
+ virtual void load();
+ // ### KDE 4: Call load() automatically through a single-shot timer
+ // from the constructor // and change documentation
+
+ /**
+ * Save the configuration data.
+ *
+ * The save method stores the config information as shown
+ * in the user interface in the config files.
+ *
+ * If necessary, this method also updates the running system,
+ * e.g. by restarting applications. This normally does not apply for
+ * KSettings::Dialog modules where the updating is taken care of by
+ * KSettings::Dispatcher.
+ *
+ * save is called when the user clicks "Apply" or "Ok".
+ *
+ * If you use KConfigXT, saving is taken care off automatically and
+ * you do not need to load manually. However, if you for some reason reimplement it and
+ * also are using KConfigXT, you must call this function, otherwise the saving of KConfigXT
+ * options will not work. Call it at the very end of your reimplementation, to avoid
+ * changed() signals getting emitted when you modify widgets.
+ */
+ virtual void save();
+
+ /**
+ * Sets the configuration to sensible default values.
+ *
+ * This method is called when the user clicks the "Default"
+ * button. It should set the display to useful values.
+ *
+ * If you use KConfigXT, you do not have to reimplement this function since
+ * the fetching and settings of default values is done automatically. However, if you
+ * reimplement and also are using KConfigXT, remember to call the base function at the
+ * very end of your reimplementation.
+ */
+ virtual void defaults();
+
+ /**
+ * Set the configuration to system default values.
+ *
+ * This method is called when the user clicks the "System-Default"
+ * button. It should set the display to the system default values.
+ *
+ * @note The default behavior is to call defaults().
+ */
+ virtual void sysdefaults() { defaults(); }
+ // KDE 4 deprecate
+
+ /**
+ * Return a quick-help text.
+ *
+ * This method is called when the module is docked.
+ * The quick-help text should contain a short description of the module and
+ * links to the module's help files. You can use QML formatting tags in the text.
+ *
+ * @note make sure the quick help text gets translated (use i18n()).
+ */
+ virtual QString quickHelp() const;
+
+ /**
+ * This is generally only called for the KBugReport.
+ * If you override you should have it return a pointer to a constant.
+ *
+ *
+ * @returns the KAboutData for this module
+ */
+ virtual const KAboutData *aboutData() const;
+
+ /**
+ * This sets the KAboutData returned by aboutData()
+ * @since 3.3
+ */
+ void setAboutData( KAboutData* about );
+
+ /**
+ * Indicate which buttons will be used.
+ *
+ * The return value is a value or'ed together from
+ * the Button enumeration type.
+ *
+ * @see KCModule::setButtons
+ */
+ int buttons() const { return _btn; }
+
+ /**
+ * Get the RootOnly message for this module.
+ *
+ * When the module must be run as root, or acts differently
+ * for root and a normal user, it is sometimes useful to
+ * customize the message that appears at the top of the module
+ * when used as a normal user. This function returns this
+ * customized message. If none has been set, a default message
+ * will be used.
+ *
+ * @see KCModule::setRootOnlyMsg
+ */
+ QString rootOnlyMsg() const;
+
+ /**
+ * Tell if KControl should show a RootOnly message when run as
+ * a normal user.
+ *
+ * In some cases, the module don't want a RootOnly message to
+ * appear (for example if it has already one). This function
+ * tells KControl if a RootOnly message should be shown
+ *
+ * @see KCModule::setUseRootOnlyMsg
+ */
+ bool useRootOnlyMsg() const;
+
+ KInstance *instance() const;
+
+ /**
+ * @return a list of @ref KConfigDialogManager's in use, if any.
+ * @since 3.4
+ */
+ const QPtrList<KConfigDialogManager>& configs() const;
+
+protected:
+ /**
+ * Adds a KConfigskeleton @p config to watch the widget @p widget
+ *
+ * This function is useful if you need to handle multiple configuration files.
+ *
+ * @since 3.3
+ * @return a pointer to the KConfigDialogManager in use
+ * @param config the KConfigSkeleton to use
+ * @param widget the widget to watch
+ */
+ KConfigDialogManager* addConfig( KConfigSkeleton *config, QWidget* widget );
+
+ /**
+ * Sets the quick help.
+ *
+ * @since 3.3
+ */
+ void setQuickHelp( const QString& help );
+
+signals:
+
+ /**
+ * Indicate that the state of the modules contents has changed.
+ *
+ * This signal is emitted whenever the state of the configuration
+ * shown in the module changes. It allows the control center to
+ * keep track of unsaved changes.
+ */
+ void changed(bool state);
+
+ /**
+ * Indicate that the module's quickhelp has changed.
+ *
+ * Emit this signal whenever the module's quickhelp changes.
+ * Modules implemented as tabbed dialogs might want to implement
+ * per-tab quickhelp for example.
+ *
+ */
+ void quickHelpChanged();
+
+protected slots:
+
+ /**
+ * Calling this slot is equivalent to emitting changed(true).
+ * @since 3.3
+ */
+ void changed();
+
+ /**
+ * A managed widget was changed, the widget settings and the current
+ * settings are compared and a corresponding changed() signal is emitted
+ * @since 3.4
+ */
+ void widgetChanged();
+
+protected:
+
+ /**
+ * Sets the buttons to display.
+ *
+ * Help: shows a "Help" button.
+ * Default: shows a "Use Defaults" button
+ * Apply: in kcontrol this will show an "Apply" and "Reset" button
+ * in kcmshell this will show an "Ok", "Apply" and "Cancel" button
+ *
+ * If Apply is not specified, kcmshell will show a "Close" button.
+ *
+ * @see KCModule::buttons
+ */
+ void setButtons(int btn) { _btn = btn; }
+
+ /**
+ * Sets the RootOnly message.
+ *
+ * This message will be shown at the top of the module of the
+ * corresponding desktop file contains the line X-KDE-RootOnly=true.
+ * If no message is set, a default one will be used.
+ *
+ * @see KCModule::rootOnlyMsg
+ */
+ void setRootOnlyMsg(const QString& msg);
+
+ /**
+ * Change whether or not the RootOnly message should be shown.
+ *
+ * Following the value of @p on, the RootOnly message will be
+ * shown or not.
+ *
+ * @see KCModule::useRootOnlyMsg
+ */
+ void setUseRootOnlyMsg(bool on);
+
+ /**
+ * Returns the changed state of automatically managed widgets in this dialog
+ * @since 3.5
+ */
+ bool managedWidgetChangeState() const;
+
+ /**
+ * Call this method when your manually managed widgets change state between
+ * changed and not changed
+ * @since 3.5
+ */
+ void unmanagedWidgetChangeState(bool);
+
+private:
+
+ int _btn;
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KCModulePrivate *d;
+
+ /**
+ * Internal function for initialization of the class.
+ */
+ void init();
+
+};
+
+#endif //KCMODULE_H
+
diff --git a/kdeui/kcolorbtn.h b/kdeui/kcolorbtn.h
new file mode 100644
index 000000000..1bf95def3
--- /dev/null
+++ b/kdeui/kcolorbtn.h
@@ -0,0 +1,12 @@
+#ifndef KCOLORBTN_H
+#define KCOLORBTN_H
+
+#ifdef KDE_NO_COMPAT
+#ifdef __GNUC__
+#warning <kcolorbtn.h> is the old name. Use <kcolorbutton.h> from now on
+#endif
+#endif
+#include <kcolorbutton.h>
+
+#endif
+
diff --git a/kdeui/kcolorbutton.cpp b/kdeui/kcolorbutton.cpp
new file mode 100644
index 000000000..a3602ed4e
--- /dev/null
+++ b/kdeui/kcolorbutton.cpp
@@ -0,0 +1,207 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Martin Jones (mjones@kde.org)
+ Copyright (C) 1999 Cristian Tibirna (ctibirna@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config.h>
+
+#include <qpainter.h>
+#include <qdrawutil.h>
+#include <qapplication.h>
+#include <qclipboard.h>
+#include <qstyle.h>
+#include <kglobalsettings.h>
+#include <kstdaccel.h>
+#include "kcolordialog.h"
+#include "kcolorbutton.h"
+#include "kcolordrag.h"
+
+class KColorButton::KColorButtonPrivate
+{
+public:
+ bool m_bdefaultColor;
+ QColor m_defaultColor;
+};
+
+KColorButton::KColorButton( QWidget *parent, const char *name )
+ : QPushButton( parent, name )
+{
+ d = new KColorButtonPrivate;
+ d->m_bdefaultColor = false;
+ d->m_defaultColor = QColor();
+ setAcceptDrops( true);
+
+ // 2000-10-15 (putzer): fixes broken keyboard usage
+ connect (this, SIGNAL(clicked()), this, SLOT(chooseColor()));
+}
+
+KColorButton::KColorButton( const QColor &c, QWidget *parent,
+ const char *name )
+ : QPushButton( parent, name ), col(c)
+{
+ d = new KColorButtonPrivate;
+ d->m_bdefaultColor = false;
+ d->m_defaultColor = QColor();
+ setAcceptDrops( true);
+
+ // 2000-10-15 (putzer): fixes broken keyboard usage
+ connect (this, SIGNAL(clicked()), this, SLOT(chooseColor()));
+}
+
+KColorButton::KColorButton( const QColor &c, const QColor &defaultColor, QWidget *parent,
+ const char *name )
+ : QPushButton( parent, name ), col(c)
+{
+ d = new KColorButtonPrivate;
+ d->m_bdefaultColor = true;
+ d->m_defaultColor = defaultColor;
+ setAcceptDrops( true);
+
+ // 2000-10-15 (putzer): fixes broken keyboard usage
+ connect (this, SIGNAL(clicked()), this, SLOT(chooseColor()));
+}
+
+KColorButton::~KColorButton()
+{
+ delete d;
+}
+
+void KColorButton::setColor( const QColor &c )
+{
+ if ( col != c ) {
+ col = c;
+ repaint( false );
+ emit changed( col );
+ }
+}
+
+QColor KColorButton::defaultColor() const
+{
+ return d->m_defaultColor;
+}
+
+void KColorButton::setDefaultColor( const QColor &c )
+{
+ d->m_bdefaultColor = c.isValid();
+ d->m_defaultColor = c;
+}
+
+
+void KColorButton::drawButtonLabel( QPainter *painter )
+{
+ int x, y, w, h;
+ QRect r = style().subRect( QStyle::SR_PushButtonContents, this );
+ r.rect(&x, &y, &w, &h);
+
+ int margin = style().pixelMetric( QStyle::PM_ButtonMargin, this );
+ x += margin;
+ y += margin;
+ w -= 2*margin;
+ h -= 2*margin;
+
+ if (isOn() || isDown()) {
+ x += style().pixelMetric( QStyle::PM_ButtonShiftHorizontal, this );
+ y += style().pixelMetric( QStyle::PM_ButtonShiftVertical, this );
+ }
+
+ QColor fillCol = isEnabled() ? col : backgroundColor();
+ qDrawShadePanel( painter, x, y, w, h, colorGroup(), true, 1, NULL);
+ if ( fillCol.isValid() )
+ painter->fillRect( x+1, y+1, w-2, h-2, fillCol );
+
+ if ( hasFocus() ) {
+ QRect focusRect = style().subRect( QStyle::SR_PushButtonFocusRect, this );
+ style().drawPrimitive( QStyle::PE_FocusRect, painter, focusRect, colorGroup() );
+ }
+}
+
+QSize KColorButton::sizeHint() const
+{
+ return style().sizeFromContents(QStyle::CT_PushButton, this, QSize(40, 15)).
+ expandedTo(QApplication::globalStrut());
+}
+
+void KColorButton::dragEnterEvent( QDragEnterEvent *event)
+{
+ event->accept( KColorDrag::canDecode( event) && isEnabled());
+}
+
+void KColorButton::dropEvent( QDropEvent *event)
+{
+ QColor c;
+ if( KColorDrag::decode( event, c)) {
+ setColor(c);
+ }
+}
+
+void KColorButton::keyPressEvent( QKeyEvent *e )
+{
+ KKey key( e );
+
+ if ( KStdAccel::copy().contains( key ) ) {
+ QMimeSource* mime = new KColorDrag( color() );
+ QApplication::clipboard()->setData( mime, QClipboard::Clipboard );
+ }
+ else if ( KStdAccel::paste().contains( key ) ) {
+ QColor color;
+ KColorDrag::decode( QApplication::clipboard()->data( QClipboard::Clipboard ), color );
+ setColor( color );
+ }
+ else
+ QPushButton::keyPressEvent( e );
+}
+
+void KColorButton::mousePressEvent( QMouseEvent *e)
+{
+ mPos = e->pos();
+ QPushButton::mousePressEvent(e);
+}
+
+void KColorButton::mouseMoveEvent( QMouseEvent *e)
+{
+ if( (e->state() & LeftButton) &&
+ (e->pos()-mPos).manhattanLength() > KGlobalSettings::dndEventDelay() )
+ {
+ // Drag color object
+ KColorDrag *dg = new KColorDrag( color(), this);
+ dg->dragCopy();
+ setDown(false);
+ }
+}
+
+void KColorButton::chooseColor()
+{
+ QColor c = color();
+ if ( d->m_bdefaultColor )
+ {
+ if( KColorDialog::getColor( c, d->m_defaultColor, this ) != QDialog::Rejected ) {
+ setColor( c );
+ }
+ }
+ else
+ {
+ if( KColorDialog::getColor( c, this ) != QDialog::Rejected ) {
+ setColor( c );
+ }
+ }
+}
+
+void KColorButton::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "kcolorbutton.moc"
diff --git a/kdeui/kcolorbutton.h b/kdeui/kcolorbutton.h
new file mode 100644
index 000000000..cb522cdfa
--- /dev/null
+++ b/kdeui/kcolorbutton.h
@@ -0,0 +1,115 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Martin Jones (mjones@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __COLBTN_H__
+#define __COLBTN_H__
+
+#include <qpushbutton.h>
+
+#include <kdelibs_export.h>
+
+class KColorButtonPrivate;
+/**
+* @short A pushbutton to display or allow user selection of a color.
+*
+* This widget can be used to display or allow user selection of a color.
+*
+* @see KColorDialog
+*
+* \image html kcolorbutton.png "KDE Color Button"
+*/
+class KDEUI_EXPORT KColorButton : public QPushButton
+{
+ Q_OBJECT
+ Q_PROPERTY( QColor color READ color WRITE setColor )
+ Q_PROPERTY( QColor defaultColor READ defaultColor WRITE setDefaultColor )
+
+public:
+ /**
+ * Creates a color button.
+ */
+ KColorButton( QWidget *parent, const char *name = 0L );
+
+ /**
+ * Creates a color button with an initial color @p c.
+ */
+ KColorButton( const QColor &c, QWidget *parent, const char *name = 0L );
+ /// @since 3.1
+ KColorButton( const QColor &c, const QColor &defaultColor, QWidget *parent,
+ const char *name=0L );
+
+ virtual ~KColorButton();
+
+ /**
+ * Returns the currently chosen color.
+ */
+ QColor color() const
+ { return col; }
+
+ /**
+ * Sets the current color to @p c.
+ */
+ void setColor( const QColor &c );
+
+ /**
+ * Returns the default color or an invalid color
+ * if no default color is set.
+ * @since 3.4
+ */
+ QColor defaultColor() const;
+
+ /**
+ * Sets the default color to @p c.
+ * @since 3.4
+ */
+ void setDefaultColor( const QColor &c );
+
+ QSize sizeHint() const;
+
+signals:
+ /**
+ * Emitted when the color of the widget
+ * is changed, either with setColor() or via user selection.
+ */
+ void changed( const QColor &newColor );
+
+protected slots:
+ void chooseColor();
+
+protected:
+ virtual void drawButtonLabel( QPainter *p );
+ virtual void dragEnterEvent( QDragEnterEvent *);
+ virtual void dropEvent( QDropEvent *);
+ virtual void mousePressEvent( QMouseEvent *e );
+ virtual void mouseMoveEvent( QMouseEvent *e);
+ virtual void keyPressEvent( QKeyEvent *e );
+private:
+ QColor col;
+ QPoint mPos;
+ bool dragFlag;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KColorButtonPrivate;
+ KColorButtonPrivate *d;
+};
+
+#endif
+
diff --git a/kdeui/kcolorcombo.cpp b/kdeui/kcolorcombo.cpp
new file mode 100644
index 000000000..1e39d75cb
--- /dev/null
+++ b/kdeui/kcolorcombo.cpp
@@ -0,0 +1,264 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Martin Jones (mjones@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+//-----------------------------------------------------------------------------
+// KDE color selection dialog.
+//
+// 1999-09-27 Espen Sand <espensa@online.no>
+// KColorDialog is now subclassed from KDialogBase. I have also extended
+// KColorDialog::getColor() so that in contains a parent argument. This
+// improves centering capability.
+//
+// layout management added Oct 1997 by Mario Weilguni
+// <mweilguni@sime.com>
+//
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <qdrawutil.h>
+#include <qevent.h>
+#include <qfile.h>
+#include <qimage.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qvalidator.h>
+#include <qpainter.h>
+#include <qpushbutton.h>
+#include <qtimer.h>
+
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+#include <kiconloader.h>
+#include <klistbox.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kseparator.h>
+#include <kpalette.h>
+#include <kimageeffect.h>
+
+//#include "kcolordialog.h"
+//#include "kcolordrag.h"
+#include "kcolorcombo.h"
+
+// This is repeated from the KColorDlg, but I didn't
+// want to make it public BL.
+// We define it out when compiling with --enable-final in which case
+// we use the version defined in KColorDlg
+
+#ifndef KDE_USE_FINAL
+#define STANDARD_PAL_SIZE 17
+
+static QColor *standardPalette = 0;
+
+static void createStandardPalette()
+{
+ if ( standardPalette )
+ return;
+
+ standardPalette = new QColor [STANDARD_PAL_SIZE];
+
+ int i = 0;
+
+ standardPalette[i++] = Qt::red;
+ standardPalette[i++] = Qt::green;
+ standardPalette[i++] = Qt::blue;
+ standardPalette[i++] = Qt::cyan;
+ standardPalette[i++] = Qt::magenta;
+ standardPalette[i++] = Qt::yellow;
+ standardPalette[i++] = Qt::darkRed;
+ standardPalette[i++] = Qt::darkGreen;
+ standardPalette[i++] = Qt::darkBlue;
+ standardPalette[i++] = Qt::darkCyan;
+ standardPalette[i++] = Qt::darkMagenta;
+ standardPalette[i++] = Qt::darkYellow;
+ standardPalette[i++] = Qt::white;
+ standardPalette[i++] = Qt::lightGray;
+ standardPalette[i++] = Qt::gray;
+ standardPalette[i++] = Qt::darkGray;
+ standardPalette[i++] = Qt::black;
+}
+#endif
+
+class KColorCombo::KColorComboPrivate
+{
+ protected:
+ friend class KColorCombo;
+ KColorComboPrivate(){}
+ ~KColorComboPrivate(){}
+ bool showEmptyList;
+};
+
+KColorCombo::KColorCombo( QWidget *parent, const char *name )
+ : QComboBox( parent, name )
+{
+ d=new KColorComboPrivate();
+ d->showEmptyList=false;
+
+ customColor.setRgb( 255, 255, 255 );
+ internalcolor.setRgb( 255, 255, 255 );
+
+ createStandardPalette();
+
+ addColors();
+
+ connect( this, SIGNAL( activated(int) ), SLOT( slotActivated(int) ) );
+ connect( this, SIGNAL( highlighted(int) ), SLOT( slotHighlighted(int) ) );
+}
+
+
+KColorCombo::~KColorCombo()
+{
+ delete d;
+}
+/**
+ Sets the current color
+ */
+void KColorCombo::setColor( const QColor &col )
+{
+ internalcolor = col;
+ d->showEmptyList=false;
+ addColors();
+}
+
+
+/**
+ Returns the currently selected color
+ */
+QColor KColorCombo::color() const {
+ return internalcolor;
+}
+
+void KColorCombo::resizeEvent( QResizeEvent *re )
+{
+ QComboBox::resizeEvent( re );
+
+ addColors();
+}
+
+/**
+ Show an empty list, till the next color is set with setColor
+ */
+void KColorCombo::showEmptyList()
+{
+ d->showEmptyList=true;
+ addColors();
+}
+
+void KColorCombo::slotActivated( int index )
+{
+ if ( index == 0 )
+ {
+ if ( KColorDialog::getColor( customColor, this ) == QDialog::Accepted )
+ {
+ QPainter painter;
+ QPen pen;
+ QRect rect( 0, 0, width(), QFontMetrics(painter.font()).height()+4);
+ QPixmap pixmap( rect.width(), rect.height() );
+
+ if ( qGray( customColor.rgb() ) < 128 )
+ pen.setColor( white );
+ else
+ pen.setColor( black );
+
+ painter.begin( &pixmap );
+ QBrush brush( customColor );
+ painter.fillRect( rect, brush );
+ painter.setPen( pen );
+ painter.drawText( 2, QFontMetrics(painter.font()).ascent()+2, i18n("Custom...") );
+ painter.end();
+
+ changeItem( pixmap, 0 );
+ pixmap.detach();
+ }
+
+ internalcolor = customColor;
+ }
+ else
+ internalcolor = standardPalette[ index - 1 ];
+
+ emit activated( internalcolor );
+}
+
+void KColorCombo::slotHighlighted( int index )
+{
+ if ( index == 0 )
+ internalcolor = customColor;
+ else
+ internalcolor = standardPalette[ index - 1 ];
+
+ emit highlighted( internalcolor );
+}
+
+void KColorCombo::addColors()
+{
+ QPainter painter;
+ QPen pen;
+ QRect rect( 0, 0, width(), QFontMetrics(painter.font()).height()+4 );
+ QPixmap pixmap( rect.width(), rect.height() );
+ int i;
+
+ clear();
+ if (d->showEmptyList) return;
+
+ createStandardPalette();
+
+ for ( i = 0; i < STANDARD_PAL_SIZE; i++ )
+ if ( standardPalette[i] == internalcolor ) break;
+
+ if ( i == STANDARD_PAL_SIZE )
+ customColor = internalcolor;
+
+ if ( qGray( customColor.rgb() ) < 128 )
+ pen.setColor( white );
+ else
+ pen.setColor( black );
+
+ painter.begin( &pixmap );
+ QBrush brush( customColor );
+ painter.fillRect( rect, brush );
+ painter.setPen( pen );
+ painter.drawText( 2, QFontMetrics(painter.font()).ascent()+2, i18n("Custom...") );
+ painter.end();
+
+ insertItem( pixmap );
+ pixmap.detach();
+
+ for ( i = 0; i < STANDARD_PAL_SIZE; i++ )
+ {
+ painter.begin( &pixmap );
+ QBrush brush( standardPalette[i] );
+ painter.fillRect( rect, brush );
+ painter.end();
+
+ insertItem( pixmap );
+ pixmap.detach();
+
+ if ( standardPalette[i] == internalcolor )
+ setCurrentItem( i + 1 );
+ }
+}
+
+void KColorCombo::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "kcolorcombo.moc"
diff --git a/kdeui/kcolorcombo.h b/kdeui/kcolorcombo.h
new file mode 100644
index 000000000..c4754c55f
--- /dev/null
+++ b/kdeui/kcolorcombo.h
@@ -0,0 +1,95 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Martin Jones (mjones@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+//-----------------------------------------------------------------------------
+// KDE color selection combo box
+
+// layout management added Oct 1997 by Mario Weilguni
+// <mweilguni@sime.com>
+
+
+#ifndef _KCOLORCOMBO_H__
+#define _KCOLORCOMBO_H__
+
+#include <qcombobox.h>
+#include <kcolordialog.h>
+#include "kselect.h"
+
+
+class KColorComboInternal;
+
+/**
+ * Combobox for colors.
+ */
+class KDEUI_EXPORT KColorCombo : public QComboBox
+{
+ Q_OBJECT
+ Q_PROPERTY( QColor color READ color WRITE setColor )
+
+public:
+ /**
+ * Constructs a color combo box.
+ */
+ KColorCombo( QWidget *parent, const char *name = 0L );
+ ~KColorCombo();
+
+ /**
+ * Selects the color @p col.
+ */
+ void setColor( const QColor &col );
+ /**
+ * Returns the currently selected color.
+ **/
+ QColor color() const;
+
+
+ /**
+ * Clear the color list and don't show it, till the next setColor() call
+ **/
+ void showEmptyList();
+
+signals:
+ /**
+ * Emitted when a new color box has been selected.
+ */
+ void activated( const QColor &col );
+ /**
+ * Emitted when a new item has been highlighted.
+ */
+ void highlighted( const QColor &col );
+
+protected:
+ virtual void resizeEvent( QResizeEvent *re );
+
+private slots:
+ void slotActivated( int index );
+ void slotHighlighted( int index );
+
+private:
+ void addColors();
+ QColor customColor;
+ QColor internalcolor;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KColorComboPrivate;
+ KColorComboPrivate *d;
+};
+
+#endif // __KCOLORCOMBO_H__
diff --git a/kdeui/kcolordialog.cpp b/kdeui/kcolordialog.cpp
new file mode 100644
index 000000000..6eb675977
--- /dev/null
+++ b/kdeui/kcolordialog.cpp
@@ -0,0 +1,1616 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Martin Jones (mjones@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+//-----------------------------------------------------------------------------
+// KDE color selection dialog.
+//
+// 1999-09-27 Espen Sand <espensa@online.no>
+// KColorDialog is now subclassed from KDialogBase. I have also extended
+// KColorDialog::getColor() so that it contains a parent argument. This
+// improves centering capability.
+//
+// layout management added Oct 1997 by Mario Weilguni
+// <mweilguni@sime.com>
+//
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qdrawutil.h>
+#include <qevent.h>
+#include <qfile.h>
+#include <qimage.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qvalidator.h>
+#include <qpainter.h>
+#include <qpushbutton.h>
+#include <qspinbox.h>
+#include <qtimer.h>
+
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+#include <kiconloader.h>
+#include <klineedit.h>
+#include <klistbox.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kseparator.h>
+#include <kpalette.h>
+#include <kimageeffect.h>
+
+#include "kcolordialog.h"
+#include "kcolordrag.h"
+#include "kstaticdeleter.h"
+#include <config.h>
+#include <kdebug.h>
+
+#include "config.h"
+#ifdef Q_WS_X11
+#include <X11/Xlib.h>
+
+// defined in qapplication_x11.cpp
+typedef int (*QX11EventFilter) (XEvent*);
+extern QX11EventFilter qt_set_x11_event_filter (QX11EventFilter filter);
+#endif
+
+struct ColorPaletteNameType
+{
+ const char* m_fileName;
+ const char* m_displayName;
+};
+
+const ColorPaletteNameType colorPaletteName[]=
+{
+ { "Recent_Colors", I18N_NOOP2( "palette name", "* Recent Colors *" ) },
+ { "Custom_Colors", I18N_NOOP2( "palette name", "* Custom Colors *" ) },
+ { "40.colors", I18N_NOOP2( "palette name", "Forty Colors" ) },
+ { "Rainbow.colors",I18N_NOOP2( "palette name", "Rainbow Colors" ) },
+ { "Royal.colors", I18N_NOOP2( "palette name", "Royal Colors" ) },
+ { "Web.colors", I18N_NOOP2( "palette name", "Web Colors" ) },
+ { 0, 0 } // end of data
+};
+
+const int recentColorIndex = 0;
+const int customColorIndex = 1;
+
+class KColorSpinBox : public QSpinBox
+{
+public:
+ KColorSpinBox(int minValue, int maxValue, int step, QWidget* parent)
+ : QSpinBox(minValue, maxValue, step, parent, "kcolorspinbox")
+ { }
+
+ // Override Qt's braindead auto-selection.
+ virtual void valueChange()
+ {
+ updateDisplay();
+ emit valueChanged( value() );
+ emit valueChanged( currentValueText() );
+ }
+
+};
+
+
+#define STANDARD_PAL_SIZE 17
+
+KColor::KColor()
+: QColor()
+{
+ r = 0; g = 0; b = 0; h = 0; s = 0; v = 0;
+}
+
+KColor::KColor( const KColor &col)
+: QColor( col )
+{
+ h = col.h; s = col.s; v = col.v;
+ r = col.r; g = col.g; b = col.b;
+}
+
+KColor::KColor( const QColor &col)
+: QColor( col )
+{
+ QColor::getRgb(&r, &g, &b);
+ QColor::getHsv(&h, &s, &v);
+}
+
+bool KColor::operator==(const KColor& col) const
+{
+ return (h == col.h) && (s == col.s) && (v == col.v) &&
+ (r == col.r) && (g == col.g) && (b == col.b);
+}
+
+KColor& KColor::operator=(const KColor& col)
+{
+ *(QColor *)this = col;
+ h = col.h; s = col.s; v = col.v;
+ r = col.r; g = col.g; b = col.b;
+ return *this;
+}
+
+void
+KColor::setHsv(int _h, int _s, int _v)
+{
+ h = _h; s = _s; v = _v;
+ QColor::setHsv(h, s, v);
+ QColor::rgb(&r, &g, &b);
+}
+
+void
+KColor::setRgb(int _r, int _g, int _b)
+{
+ r = _r; g = _g; b = _b;
+ QColor::setRgb(r, g, b);
+ QColor::hsv(&h, &s, &v);
+}
+
+void
+KColor::rgb(int *_r, int *_g, int *_b) const
+{
+ *_r = r; *_g = g; *_b = b;
+}
+
+void
+KColor::hsv(int *_h, int *_s, int *_v) const
+{
+ *_h = h; *_s = s; *_v = v;
+}
+
+
+static QColor *standardPalette = 0;
+static KStaticDeleter<QColor> spd;
+
+static void createStandardPalette()
+{
+ if ( standardPalette )
+ return;
+
+ spd.setObject(standardPalette, new QColor [STANDARD_PAL_SIZE], true/*array*/);
+
+ int i = 0;
+
+ standardPalette[i++] = Qt::red;
+ standardPalette[i++] = Qt::green;
+ standardPalette[i++] = Qt::blue;
+ standardPalette[i++] = Qt::cyan;
+ standardPalette[i++] = Qt::magenta;
+ standardPalette[i++] = Qt::yellow;
+ standardPalette[i++] = Qt::darkRed;
+ standardPalette[i++] = Qt::darkGreen;
+ standardPalette[i++] = Qt::darkBlue;
+ standardPalette[i++] = Qt::darkCyan;
+ standardPalette[i++] = Qt::darkMagenta;
+ standardPalette[i++] = Qt::darkYellow;
+ standardPalette[i++] = Qt::white;
+ standardPalette[i++] = Qt::lightGray;
+ standardPalette[i++] = Qt::gray;
+ standardPalette[i++] = Qt::darkGray;
+ standardPalette[i++] = Qt::black;
+}
+
+
+KHSSelector::KHSSelector( QWidget *parent, const char *name )
+ : KXYSelector( parent, name )
+{
+ setRange( 0, 0, 359, 255 );
+}
+
+void KHSSelector::updateContents()
+{
+ drawPalette(&pixmap);
+}
+
+void KHSSelector::resizeEvent( QResizeEvent * )
+{
+ updateContents();
+}
+
+void KHSSelector::drawContents( QPainter *painter )
+{
+ painter->drawPixmap( contentsRect().x(), contentsRect().y(), pixmap );
+}
+
+void KHSSelector::drawPalette( QPixmap *pixmap )
+{
+ int xSize = contentsRect().width(), ySize = contentsRect().height();
+ QImage image( xSize, ySize, 32 );
+ QColor col;
+ int h, s;
+ uint *p;
+
+ for ( s = ySize-1; s >= 0; s-- )
+ {
+ p = (uint *) image.scanLine( ySize - s - 1 );
+ for( h = 0; h < xSize; h++ )
+ {
+ col.setHsv( 359*h/(xSize-1), 255*s/((ySize == 1) ? 1 : ySize-1), 192 );
+ *p = col.rgb();
+ p++;
+ }
+ }
+
+ if ( QColor::numBitPlanes() <= 8 )
+ {
+ createStandardPalette();
+ KImageEffect::dither( image, standardPalette, STANDARD_PAL_SIZE );
+ }
+ pixmap->convertFromImage( image );
+}
+
+
+//-----------------------------------------------------------------------------
+
+KValueSelector::KValueSelector( QWidget *parent, const char *name )
+ : KSelector( KSelector::Vertical, parent, name ), _hue(0), _sat(0)
+{
+ setRange( 0, 255 );
+ pixmap.setOptimization( QPixmap::BestOptim );
+}
+
+KValueSelector::KValueSelector(Orientation o, QWidget *parent, const char *name
+ )
+ : KSelector( o, parent, name), _hue(0), _sat(0)
+{
+ setRange( 0, 255 );
+ pixmap.setOptimization( QPixmap::BestOptim );
+}
+
+void KValueSelector::updateContents()
+{
+ drawPalette(&pixmap);
+}
+
+void KValueSelector::resizeEvent( QResizeEvent * )
+{
+ updateContents();
+}
+
+void KValueSelector::drawContents( QPainter *painter )
+{
+ painter->drawPixmap( contentsRect().x(), contentsRect().y(), pixmap );
+}
+
+void KValueSelector::drawPalette( QPixmap *pixmap )
+{
+ int xSize = contentsRect().width(), ySize = contentsRect().height();
+ QImage image( xSize, ySize, 32 );
+ QColor col;
+ uint *p;
+ QRgb rgb;
+
+ if ( orientation() == KSelector::Horizontal )
+ {
+ for ( int v = 0; v < ySize; v++ )
+ {
+ p = (uint *) image.scanLine( ySize - v - 1 );
+
+ for( int x = 0; x < xSize; x++ )
+ {
+ col.setHsv( _hue, _sat, 255*x/((xSize == 1) ? 1 : xSize-1) );
+ rgb = col.rgb();
+ *p++ = rgb;
+ }
+ }
+ }
+
+ if( orientation() == KSelector::Vertical )
+ {
+ for ( int v = 0; v < ySize; v++ )
+ {
+ p = (uint *) image.scanLine( ySize - v - 1 );
+ col.setHsv( _hue, _sat, 255*v/((ySize == 1) ? 1 : ySize-1) );
+ rgb = col.rgb();
+ for ( int i = 0; i < xSize; i++ )
+ *p++ = rgb;
+ }
+ }
+
+ if ( QColor::numBitPlanes() <= 8 )
+ {
+ createStandardPalette();
+ KImageEffect::dither( image, standardPalette, STANDARD_PAL_SIZE );
+ }
+ pixmap->convertFromImage( image );
+}
+
+//-----------------------------------------------------------------------------
+
+KColorCells::KColorCells( QWidget *parent, int rows, int cols )
+ : QGridView( parent )
+{
+ shade = true;
+ setNumRows( rows );
+ setNumCols( cols );
+ colors = new QColor [ rows * cols ];
+
+ for ( int i = 0; i < rows * cols; i++ )
+ colors[i] = QColor();
+
+ selected = 0;
+ inMouse = false;
+
+ // Drag'n'Drop
+ setAcceptDrops( true);
+
+ setHScrollBarMode( AlwaysOff );
+ setVScrollBarMode( AlwaysOff );
+ viewport()->setBackgroundMode( PaletteBackground );
+ setBackgroundMode( PaletteBackground );
+}
+
+KColorCells::~KColorCells()
+{
+ delete [] colors;
+}
+
+void KColorCells::setColor( int colNum, const QColor &col )
+{
+ colors[colNum] = col;
+ updateCell( colNum/numCols(), colNum%numCols() );
+}
+
+void KColorCells::paintCell( QPainter *painter, int row, int col )
+{
+ QBrush brush;
+ int w = 1;
+
+ if (shade)
+ {
+ qDrawShadePanel( painter, 1, 1, cellWidth()-2,
+ cellHeight()-2, colorGroup(), true, 1, &brush );
+ w = 2;
+ }
+ QColor color = colors[ row * numCols() + col ];
+ if (!color.isValid())
+ {
+ if (!shade) return;
+ color = backgroundColor();
+ }
+
+ painter->setPen( color );
+ painter->setBrush( QBrush( color ) );
+ painter->drawRect( w, w, cellWidth()-w*2, cellHeight()-w*2 );
+
+ if ( row * numCols() + col == selected )
+ painter->drawWinFocusRect( w, w, cellWidth()-w*2, cellHeight()-w*2 );
+}
+
+void KColorCells::resizeEvent( QResizeEvent * )
+{
+ setCellWidth( width() / numCols() );
+ setCellHeight( height() / numRows() );
+}
+
+void KColorCells::mousePressEvent( QMouseEvent *e )
+{
+ inMouse = true;
+ mPos = e->pos();
+}
+
+int KColorCells::posToCell(const QPoint &pos, bool ignoreBorders)
+{
+ int row = pos.y() / cellHeight();
+ int col = pos.x() / cellWidth();
+ int cell = row * numCols() + col;
+
+ if (!ignoreBorders)
+ {
+ int border = 2;
+ int x = pos.x() - col * cellWidth();
+ int y = pos.y() - row * cellHeight();
+ if ( (x < border) || (x > cellWidth()-border) ||
+ (y < border) || (y > cellHeight()-border))
+ return -1;
+ }
+ return cell;
+}
+
+void KColorCells::mouseMoveEvent( QMouseEvent *e )
+{
+ if( !(e->state() & LeftButton)) return;
+
+ if(inMouse) {
+ int delay = KGlobalSettings::dndEventDelay();
+ if(e->x() > mPos.x()+delay || e->x() < mPos.x()-delay ||
+ e->y() > mPos.y()+delay || e->y() < mPos.y()-delay){
+ // Drag color object
+ int cell = posToCell(mPos);
+ if ((cell != -1) && colors[cell].isValid())
+ {
+ KColorDrag *d = new KColorDrag( colors[cell], this);
+ d->dragCopy();
+ }
+ }
+ }
+}
+
+void KColorCells::dragEnterEvent( QDragEnterEvent *event)
+{
+ event->accept( acceptDrags && KColorDrag::canDecode( event));
+}
+
+void KColorCells::dropEvent( QDropEvent *event)
+{
+ QColor c;
+ if( KColorDrag::decode( event, c)) {
+ int cell = posToCell(event->pos(), true);
+ setColor(cell,c);
+ }
+}
+
+void KColorCells::mouseReleaseEvent( QMouseEvent *e )
+{
+ int cell = posToCell(mPos);
+ int currentCell = posToCell(e->pos());
+
+ // If we release the mouse in another cell and we don't have
+ // a drag we should ignore this event.
+ if (currentCell != cell)
+ cell = -1;
+
+ if ( (cell != -1) && (selected != cell) )
+ {
+ int prevSel = selected;
+ selected = cell;
+ updateCell( prevSel/numCols(), prevSel%numCols() );
+ updateCell( cell/numCols(), cell%numCols() );
+ }
+
+ inMouse = false;
+ if (cell != -1)
+ emit colorSelected( cell );
+}
+
+void KColorCells::mouseDoubleClickEvent( QMouseEvent * /*e*/ )
+{
+ int cell = posToCell(mPos);
+
+ if (cell != -1)
+ emit colorDoubleClicked( cell );
+}
+
+
+//-----------------------------------------------------------------------------
+
+KColorPatch::KColorPatch( QWidget *parent ) : QFrame( parent )
+{
+ setFrameStyle( QFrame::Panel | QFrame::Sunken );
+ colContext = 0;
+ setAcceptDrops( true);
+}
+
+KColorPatch::~KColorPatch()
+{
+ if ( colContext )
+ QColor::destroyAllocContext( colContext );
+}
+
+void KColorPatch::setColor( const QColor &col )
+{
+ if ( colContext )
+ QColor::destroyAllocContext( colContext );
+ colContext = QColor::enterAllocContext();
+ color.setRgb( col.rgb() );
+ color.alloc();
+ QColor::leaveAllocContext();
+
+ QPainter painter;
+
+ painter.begin( this );
+ drawContents( &painter );
+ painter.end();
+}
+
+void KColorPatch::drawContents( QPainter *painter )
+{
+ painter->setPen( color );
+ painter->setBrush( QBrush( color ) );
+ painter->drawRect( contentsRect() );
+}
+
+void KColorPatch::mouseMoveEvent( QMouseEvent *e )
+{
+ // Drag color object
+ if( !(e->state() & LeftButton)) return;
+ KColorDrag *d = new KColorDrag( color, this);
+ d->dragCopy();
+}
+
+void KColorPatch::dragEnterEvent( QDragEnterEvent *event)
+{
+ event->accept( KColorDrag::canDecode( event));
+}
+
+void KColorPatch::dropEvent( QDropEvent *event)
+{
+ QColor c;
+ if( KColorDrag::decode( event, c)) {
+ setColor( c);
+ emit colorChanged( c);
+ }
+}
+
+class KPaletteTable::KPaletteTablePrivate
+{
+public:
+ QMap<QString,QColor> m_namedColorMap;
+};
+
+KPaletteTable::KPaletteTable( QWidget *parent, int minWidth, int cols)
+ : QWidget( parent ), cells(0), mPalette(0), mMinWidth(minWidth), mCols(cols)
+{
+ d = new KPaletteTablePrivate;
+
+ i18n_namedColors = i18n("Named Colors");
+
+ QStringList diskPaletteList = KPalette::getPaletteList();
+ QStringList paletteList;
+
+ // We must replace the untranslated file names by translate names (of course only for KDE's standard palettes)
+ for ( int i = 0; colorPaletteName[i].m_fileName; ++i )
+ {
+ diskPaletteList.remove( colorPaletteName[i].m_fileName );
+ paletteList.append( i18n( "palette name", colorPaletteName[i].m_displayName ) );
+ }
+ paletteList += diskPaletteList;
+ paletteList.append( i18n_namedColors );
+
+ QVBoxLayout *layout = new QVBoxLayout( this );
+
+ combo = new QComboBox( false, this );
+ combo->insertStringList( paletteList );
+ layout->addWidget(combo);
+
+ sv = new QScrollView( this );
+ QSize cellSize = QSize( mMinWidth, 120);
+ sv->setHScrollBarMode( QScrollView::AlwaysOff);
+ sv->setVScrollBarMode( QScrollView::AlwaysOn);
+ QSize minSize = QSize(sv->verticalScrollBar()->width(), 0);
+ minSize += QSize(sv->frameWidth(), 0);
+ minSize += QSize(cellSize);
+ sv->setFixedSize(minSize);
+ layout->addWidget(sv);
+
+ mNamedColorList = new KListBox( this, "namedColorList", 0 );
+ mNamedColorList->setFixedSize(minSize);
+ mNamedColorList->hide();
+ layout->addWidget(mNamedColorList);
+ connect( mNamedColorList, SIGNAL(highlighted( const QString & )),
+ this, SLOT( slotColorTextSelected( const QString & )) );
+
+ setFixedSize( sizeHint());
+ connect( combo, SIGNAL(activated(const QString &)),
+ this, SLOT(slotSetPalette( const QString &)));
+}
+
+KPaletteTable::~KPaletteTable()
+{
+ delete mPalette;
+ delete d;
+}
+
+QString
+KPaletteTable::palette() const
+{
+ return combo->currentText();
+}
+
+
+static const char * const *namedColorFilePath( void )
+{
+ //
+ // 2000-02-05 Espen Sand.
+ // Add missing filepaths here. Make sure the last entry is 0!
+ //
+ static const char * const path[] =
+ {
+#ifdef X11_RGBFILE
+ X11_RGBFILE,
+#endif
+ "/usr/share/X11/rgb.txt",
+ "/usr/X11R6/lib/X11/rgb.txt",
+ "/usr/openwin/lib/X11/rgb.txt", // for Solaris.
+ 0
+ };
+ return path;
+}
+
+
+
+
+void
+KPaletteTable::readNamedColor( void )
+{
+ if( mNamedColorList->count() != 0 )
+ {
+ return; // Strings already present
+ }
+
+ KGlobal::locale()->insertCatalogue("kdelibs_colors");
+
+ //
+ // Code somewhat inspired by KPalette.
+ //
+
+ const char * const *path = namedColorFilePath();
+ for( int i=0; path[i]; ++i )
+ {
+ QFile paletteFile( path[i] );
+ if( !paletteFile.open( IO_ReadOnly ) )
+ {
+ continue;
+ }
+
+ QString line;
+ QStringList list;
+ while( paletteFile.readLine( line, 100 ) != -1 )
+ {
+ int red, green, blue;
+ int pos = 0;
+
+ if( sscanf(line.ascii(), "%d %d %d%n", &red, &green, &blue, &pos ) == 3 )
+ {
+ //
+ // Remove duplicates. Every name with a space and every name
+ // that start with "gray".
+ //
+ QString name = line.mid(pos).stripWhiteSpace();
+ if( name.isNull() || name.find(' ') != -1 ||
+ name.find( "gray" ) != -1 || name.find( "grey" ) != -1 )
+ {
+ continue;
+ }
+
+ const QColor color ( red, green, blue );
+ if ( color.isValid() )
+ {
+ const QString colorName( i18n("color", name.latin1() ) );
+ list.append( colorName );
+ d->m_namedColorMap[ colorName ] = color;
+ }
+ }
+ }
+
+ list.sort();
+ mNamedColorList->insertStringList( list );
+ break;
+ }
+
+ if( mNamedColorList->count() == 0 )
+ {
+ //
+ // Give the error dialog box a chance to center above the
+ // widget (or dialog). If we had displayed it now we could get a
+ // situation where the (modal) error dialog box pops up first
+ // preventing the real dialog to become visible until the
+ // error dialog box is removed (== bad UI).
+ //
+ QTimer::singleShot( 10, this, SLOT(slotShowNamedColorReadError()) );
+ }
+}
+
+
+void
+KPaletteTable::slotShowNamedColorReadError( void )
+{
+ if( mNamedColorList->count() == 0 )
+ {
+ QString msg = i18n(""
+ "Unable to read X11 RGB color strings. The following "
+ "file location(s) were examined:\n");
+
+ const char * const *path = namedColorFilePath();
+ for( int i=0; path[i]; ++i )
+ {
+ msg += path[i];
+ msg += "\n";
+ }
+ KMessageBox::sorry( this, msg );
+ }
+}
+
+
+//
+// 2000-02-12 Espen Sand
+// Set the color in two steps. The setPalette() slot will not emit a signal
+// with the current color setting. The reason is that setPalette() is used
+// by the color selector dialog on startup. In the color selector dialog
+// we normally want to display a startup color which we specify
+// when the dialog is started. The slotSetPalette() slot below will
+// set the palette and then use the information to emit a signal with the
+// new color setting. It is only used by the combobox widget.
+//
+void
+KPaletteTable::slotSetPalette( const QString &_paletteName )
+{
+ setPalette( _paletteName );
+ if( mNamedColorList->isVisible() )
+ {
+ int item = mNamedColorList->currentItem();
+ mNamedColorList->setCurrentItem( item < 0 ? 0 : item );
+ slotColorTextSelected( mNamedColorList->currentText() );
+ }
+ else
+ {
+ slotColorCellSelected(0); // FIXME: We need to save the current value!!
+ }
+}
+
+
+void
+KPaletteTable::setPalette( const QString &_paletteName )
+{
+ QString paletteName( _paletteName);
+ if (paletteName.isEmpty())
+ paletteName = i18n_recentColors;
+
+ if (combo->currentText() != paletteName)
+ {
+ bool found = false;
+ for(int i = 0; i < combo->count(); i++)
+ {
+ if (combo->text(i) == paletteName)
+ {
+ combo->setCurrentItem(i);
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ {
+ combo->insertItem(paletteName);
+ combo->setCurrentItem(combo->count()-1);
+ }
+ }
+
+ // We must again find the file name of the palette from the eventual translation
+ for ( int i = 0; colorPaletteName[i].m_fileName; ++i )
+ {
+ if ( paletteName == i18n( "palette name", colorPaletteName[i].m_displayName ) )
+ {
+ paletteName = colorPaletteName[i].m_fileName;
+ break;
+ }
+ }
+
+
+ //
+ // 2000-02-12 Espen Sand
+ // The palette mode "i18n_namedColors" does not use the KPalette class.
+ // In fact, 'mPalette' and 'cells' are 0 when in this mode. The reason
+ // for this is maninly that KPalette reads from and writes to files using
+ // "locate()". The colors used in "i18n_namedColors" mode comes from the
+ // X11 diretory and is not writable. I don't think this fit in KPalette.
+ //
+ if( !mPalette || mPalette->name() != paletteName )
+ {
+ if( paletteName == i18n_namedColors )
+ {
+ sv->hide();
+ mNamedColorList->show();
+ readNamedColor();
+
+ delete cells; cells = 0;
+ delete mPalette; mPalette = 0;
+ }
+ else
+ {
+ mNamedColorList->hide();
+ sv->show();
+
+ delete cells;
+ delete mPalette;
+ mPalette = new KPalette(paletteName);
+ int rows = (mPalette->nrColors()+mCols-1) / mCols;
+ if (rows < 1) rows = 1;
+ cells = new KColorCells( sv->viewport(), rows, mCols);
+ cells->setShading(false);
+ cells->setAcceptDrags(false);
+ QSize cellSize = QSize( mMinWidth, mMinWidth * rows / mCols);
+ cells->setFixedSize( cellSize );
+ for( int i = 0; i < mPalette->nrColors(); i++)
+ {
+ cells->setColor( i, mPalette->color(i) );
+ }
+ connect( cells, SIGNAL( colorSelected( int ) ),
+ SLOT( slotColorCellSelected( int ) ) );
+ connect( cells, SIGNAL( colorDoubleClicked( int ) ),
+ SLOT( slotColorCellDoubleClicked( int ) ) );
+ sv->addChild( cells );
+ cells->show();
+ sv->updateScrollBars();
+ }
+ }
+}
+
+
+
+void
+KPaletteTable::slotColorCellSelected( int col )
+{
+ if (!mPalette || (col >= mPalette->nrColors()))
+ return;
+ emit colorSelected( mPalette->color(col), mPalette->colorName(col) );
+}
+
+void
+KPaletteTable::slotColorCellDoubleClicked( int col )
+{
+ if (!mPalette || (col >= mPalette->nrColors()))
+ return;
+ emit colorDoubleClicked( mPalette->color(col), mPalette->colorName(col) );
+}
+
+
+void
+KPaletteTable::slotColorTextSelected( const QString &colorText )
+{
+ emit colorSelected( d->m_namedColorMap[ colorText ], colorText );
+}
+
+
+void
+KPaletteTable::addToCustomColors( const QColor &color)
+{
+ setPalette(i18n( "palette name", colorPaletteName[ customColorIndex ].m_displayName ));
+ mPalette->addColor( color );
+ mPalette->save();
+ delete mPalette;
+ mPalette = 0;
+ setPalette(i18n( "palette name", colorPaletteName[ customColorIndex ].m_displayName ));
+}
+
+void
+KPaletteTable::addToRecentColors( const QColor &color)
+{
+ //
+ // 2000-02-12 Espen Sand.
+ // The 'mPalette' is always 0 when current mode is i18n_namedColors
+ //
+ bool recentIsSelected = false;
+ if ( mPalette && mPalette->name() == colorPaletteName[ recentColorIndex ].m_fileName )
+ {
+ delete mPalette;
+ mPalette = 0;
+ recentIsSelected = true;
+ }
+ KPalette *recentPal = new KPalette( colorPaletteName[ recentColorIndex ].m_fileName );
+ if (recentPal->findColor(color) == -1)
+ {
+ recentPal->addColor( color );
+ recentPal->save();
+ }
+ delete recentPal;
+ if (recentIsSelected)
+ setPalette( i18n( "palette name", colorPaletteName[ recentColorIndex ].m_displayName ) );
+}
+
+class KColorDialog::KColorDialogPrivate {
+public:
+ KPaletteTable *table;
+ QString originalPalette;
+ bool bRecursion;
+ bool bEditRgb;
+ bool bEditHsv;
+ bool bEditHtml;
+ bool bColorPicking;
+ QLabel *colorName;
+ KLineEdit *htmlName;
+ KColorSpinBox *hedit;
+ KColorSpinBox *sedit;
+ KColorSpinBox *vedit;
+ KColorSpinBox *redit;
+ KColorSpinBox *gedit;
+ KColorSpinBox *bedit;
+ KColorPatch *patch;
+ KHSSelector *hsSelector;
+ KPalette *palette;
+ KValueSelector *valuePal;
+ QVBoxLayout* l_right;
+ QGridLayout* tl_layout;
+ QCheckBox *cbDefaultColor;
+ KColor defaultColor;
+ KColor selColor;
+#ifdef Q_WS_X11
+ QX11EventFilter oldfilter;
+#endif
+};
+
+
+KColorDialog::KColorDialog( QWidget *parent, const char *name, bool modal )
+ :KDialogBase( parent, name, modal, i18n("Select Color"),
+ modal ? Ok|Cancel : Close,
+ Ok, true )
+{
+ d = new KColorDialogPrivate;
+ d->bRecursion = true;
+ d->bColorPicking = false;
+#ifdef Q_WS_X11
+ d->oldfilter = 0;
+#endif
+ d->cbDefaultColor = 0L;
+ connect( this, SIGNAL(okClicked(void)),this,SLOT(slotWriteSettings(void)));
+ connect( this, SIGNAL(closeClicked(void)),this,SLOT(slotWriteSettings(void)));
+
+ QLabel *label;
+
+ //
+ // Create the top level page and its layout
+ //
+ QWidget *page = new QWidget( this );
+ setMainWidget( page );
+
+ QGridLayout *tl_layout = new QGridLayout( page, 3, 3, 0, spacingHint() );
+ d->tl_layout = tl_layout;
+ tl_layout->addColSpacing( 1, spacingHint() * 2 );
+
+ //
+ // the more complicated part: the left side
+ // add a V-box
+ //
+ QVBoxLayout *l_left = new QVBoxLayout();
+ tl_layout->addLayout(l_left, 0, 0);
+
+ //
+ // add a H-Box for the XY-Selector and a grid for the
+ // entry fields
+ //
+ QHBoxLayout *l_ltop = new QHBoxLayout();
+ l_left->addLayout(l_ltop);
+
+ // a little space between
+ l_left->addSpacing(10);
+
+ QGridLayout *l_lbot = new QGridLayout(3, 6);
+ l_left->addLayout(l_lbot);
+
+ //
+ // the palette and value selector go into the H-box
+ //
+ d->hsSelector = new KHSSelector( page );
+ d->hsSelector->setMinimumSize(140, 70);
+ l_ltop->addWidget(d->hsSelector, 8);
+ connect( d->hsSelector, SIGNAL( valueChanged( int, int ) ),
+ SLOT( slotHSChanged( int, int ) ) );
+
+ d->valuePal = new KValueSelector( page );
+ d->valuePal->setMinimumSize(26, 70);
+ l_ltop->addWidget(d->valuePal, 1);
+ connect( d->valuePal, SIGNAL( valueChanged( int ) ),
+ SLOT( slotVChanged( int ) ) );
+
+
+ //
+ // add the HSV fields
+ //
+ label = new QLabel( i18n("H:"), page );
+ label->setAlignment(AlignRight | AlignVCenter);
+ l_lbot->addWidget(label, 0, 2);
+ d->hedit = new KColorSpinBox( 0, 359, 1, page );
+ d->hedit->setValidator( new QIntValidator( d->hedit ) );
+ l_lbot->addWidget(d->hedit, 0, 3);
+ connect( d->hedit, SIGNAL( valueChanged(int) ),
+ SLOT( slotHSVChanged() ) );
+
+ label = new QLabel( i18n("S:"), page );
+ label->setAlignment(AlignRight | AlignVCenter);
+ l_lbot->addWidget(label, 1, 2);
+ d->sedit = new KColorSpinBox( 0, 255, 1, page );
+ d->sedit->setValidator( new QIntValidator( d->sedit ) );
+ l_lbot->addWidget(d->sedit, 1, 3);
+ connect( d->sedit, SIGNAL( valueChanged(int) ),
+ SLOT( slotHSVChanged() ) );
+
+ label = new QLabel( i18n("V:"), page );
+ label->setAlignment(AlignRight | AlignVCenter);
+ l_lbot->addWidget(label, 2, 2);
+ d->vedit = new KColorSpinBox( 0, 255, 1, page );
+ d->vedit->setValidator( new QIntValidator( d->vedit ) );
+ l_lbot->addWidget(d->vedit, 2, 3);
+ connect( d->vedit, SIGNAL( valueChanged(int) ),
+ SLOT( slotHSVChanged() ) );
+
+ //
+ // add the RGB fields
+ //
+ label = new QLabel( i18n("R:"), page );
+ label->setAlignment(AlignRight | AlignVCenter);
+ l_lbot->addWidget(label, 0, 4);
+ d->redit = new KColorSpinBox( 0, 255, 1, page );
+ d->redit->setValidator( new QIntValidator( d->redit ) );
+ l_lbot->addWidget(d->redit, 0, 5);
+ connect( d->redit, SIGNAL( valueChanged(int) ),
+ SLOT( slotRGBChanged() ) );
+
+ label = new QLabel( i18n("G:"), page );
+ label->setAlignment(AlignRight | AlignVCenter);
+ l_lbot->addWidget( label, 1, 4);
+ d->gedit = new KColorSpinBox( 0, 255,1, page );
+ d->gedit->setValidator( new QIntValidator( d->gedit ) );
+ l_lbot->addWidget(d->gedit, 1, 5);
+ connect( d->gedit, SIGNAL( valueChanged(int) ),
+ SLOT( slotRGBChanged() ) );
+
+ label = new QLabel( i18n("B:"), page );
+ label->setAlignment(AlignRight | AlignVCenter);
+ l_lbot->addWidget(label, 2, 4);
+ d->bedit = new KColorSpinBox( 0, 255, 1, page );
+ d->bedit->setValidator( new QIntValidator( d->bedit ) );
+ l_lbot->addWidget(d->bedit, 2, 5);
+ connect( d->bedit, SIGNAL( valueChanged(int) ),
+ SLOT( slotRGBChanged() ) );
+
+ //
+ // the entry fields should be wide enough to hold 8888888
+ //
+ int w = d->hedit->fontMetrics().width("8888888");
+ d->hedit->setFixedWidth(w);
+ d->sedit->setFixedWidth(w);
+ d->vedit->setFixedWidth(w);
+
+ d->redit->setFixedWidth(w);
+ d->gedit->setFixedWidth(w);
+ d->bedit->setFixedWidth(w);
+
+ //
+ // add a layout for the right side
+ //
+ d->l_right = new QVBoxLayout;
+ tl_layout->addLayout(d->l_right, 0, 2);
+
+ //
+ // Add the palette table
+ //
+ d->table = new KPaletteTable( page );
+ d->l_right->addWidget(d->table, 10);
+
+ connect( d->table, SIGNAL( colorSelected( const QColor &, const QString & ) ),
+ SLOT( slotColorSelected( const QColor &, const QString & ) ) );
+
+ connect(
+ d->table,
+ SIGNAL( colorDoubleClicked( const QColor &, const QString & ) ),
+ SLOT( slotColorDoubleClicked( const QColor &, const QString & ) )
+ );
+ // Store the default value for saving time.
+ d->originalPalette = d->table->palette();
+
+ //
+ // a little space between
+ //
+ d->l_right->addSpacing(10);
+
+ QHBoxLayout *l_hbox = new QHBoxLayout( d->l_right );
+
+ //
+ // The add to custom colors button
+ //
+ QPushButton *button = new QPushButton( page );
+ button->setText(i18n("&Add to Custom Colors"));
+ l_hbox->addWidget(button, 0, AlignLeft);
+ connect( button, SIGNAL( clicked()), SLOT( slotAddToCustomColors()));
+
+ //
+ // The color picker button
+ //
+ button = new QPushButton( page );
+ button->setPixmap( BarIcon("colorpicker"));
+ l_hbox->addWidget(button, 0, AlignHCenter );
+ connect( button, SIGNAL( clicked()), SLOT( slotColorPicker()));
+
+ //
+ // a little space between
+ //
+ d->l_right->addSpacing(10);
+
+ //
+ // and now the entry fields and the patch (=colored box)
+ //
+ QGridLayout *l_grid = new QGridLayout( d->l_right, 2, 3);
+
+ l_grid->setColStretch(2, 1);
+
+ label = new QLabel( page );
+ label->setText(i18n("Name:"));
+ l_grid->addWidget(label, 0, 1, AlignLeft);
+
+ d->colorName = new QLabel( page );
+ l_grid->addWidget(d->colorName, 0, 2, AlignLeft);
+
+ label = new QLabel( page );
+ label->setText(i18n("HTML:"));
+ l_grid->addWidget(label, 1, 1, AlignLeft);
+
+ d->htmlName = new KLineEdit( page );
+ d->htmlName->setMaxLength( 13 ); // Qt's QColor allows 12 hexa-digits
+ d->htmlName->setText("#FFFFFF"); // But HTML uses only 6, so do not worry about the size
+ w = d->htmlName->fontMetrics().width(QString::fromLatin1("#DDDDDDD"));
+ d->htmlName->setFixedWidth(w);
+ l_grid->addWidget(d->htmlName, 1, 2, AlignLeft);
+
+ connect( d->htmlName, SIGNAL( textChanged(const QString &) ),
+ SLOT( slotHtmlChanged() ) );
+
+ d->patch = new KColorPatch( page );
+ d->patch->setFixedSize(48, 48);
+ l_grid->addMultiCellWidget(d->patch, 0, 1, 0, 0, AlignHCenter | AlignVCenter);
+ connect( d->patch, SIGNAL( colorChanged( const QColor&)),
+ SLOT( setColor( const QColor&)));
+
+ tl_layout->activate();
+ page->setMinimumSize( page->sizeHint() );
+
+ readSettings();
+ d->bRecursion = false;
+ d->bEditHsv = false;
+ d->bEditRgb = false;
+ d->bEditHtml = false;
+
+ disableResize();
+ KColor col;
+ col.setHsv( 0, 0, 255 );
+ _setColor( col );
+
+ d->htmlName->installEventFilter(this);
+ d->hsSelector->installEventFilter(this);
+ d->hsSelector->setAcceptDrops(true);
+}
+
+KColorDialog::~KColorDialog()
+{
+#ifdef Q_WS_X11
+ if (d->bColorPicking)
+ qt_set_x11_event_filter(d->oldfilter);
+#endif
+ delete d;
+}
+
+bool
+KColorDialog::eventFilter( QObject *obj, QEvent *ev )
+{
+ if ((obj == d->htmlName) || (obj == d->hsSelector))
+ switch(ev->type())
+ {
+ case QEvent::DragEnter:
+ case QEvent::DragMove:
+ case QEvent::DragLeave:
+ case QEvent::Drop:
+ case QEvent::DragResponse:
+ qApp->sendEvent(d->patch, ev);
+ return true;
+ default:
+ break;
+ }
+ return KDialogBase::eventFilter(obj, ev);
+}
+
+void
+KColorDialog::setDefaultColor( const QColor& col )
+{
+ if ( !d->cbDefaultColor )
+ {
+ //
+ // a little space between
+ //
+ d->l_right->addSpacing(10);
+
+ //
+ // and the "default color" checkbox, under all items on the right side
+ //
+ d->cbDefaultColor = new QCheckBox( i18n( "Default color" ), mainWidget() );
+ d->cbDefaultColor->setChecked(true);
+
+ d->l_right->addWidget( d->cbDefaultColor );
+
+ mainWidget()->setMaximumSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX ); // cancel setFixedSize()
+ d->tl_layout->activate();
+ mainWidget()->setMinimumSize( mainWidget()->sizeHint() );
+ disableResize();
+
+ connect( d->cbDefaultColor, SIGNAL( clicked() ), SLOT( slotDefaultColorClicked() ) );
+ }
+
+ d->defaultColor = col;
+
+ slotDefaultColorClicked();
+}
+
+QColor KColorDialog::defaultColor() const
+{
+ return d->defaultColor;
+}
+
+void KColorDialog::slotDefaultColorClicked()
+{
+ if ( d->cbDefaultColor->isChecked() )
+ {
+ d->selColor = d->defaultColor;
+ showColor( d->selColor, i18n( "-default-" ) );
+ } else
+ {
+ showColor( d->selColor, QString::null );
+ }
+}
+
+void
+KColorDialog::readSettings()
+{
+ KConfigGroup group( KGlobal::config(), "Colors" );
+
+ QString palette = group.readEntry("CurrentPalette");
+ d->table->setPalette(palette);
+}
+
+void
+KColorDialog::slotWriteSettings()
+{
+ KConfigGroup group( KGlobal::config(), "Colors" );
+
+ QString palette = d->table->palette();
+ if (!group.hasDefault("CurrentPalette") &&
+ (d->table->palette() == d->originalPalette))
+ {
+ group.revertToDefault("CurrentPalette");
+ }
+ else
+ {
+ group.writeEntry("CurrentPalette", d->table->palette());
+ }
+}
+
+QColor
+KColorDialog::color() const
+{
+ if ( d->cbDefaultColor && d->cbDefaultColor->isChecked() )
+ return QColor();
+ if ( d->selColor.isValid() )
+ d->table->addToRecentColors( d->selColor );
+ return d->selColor;
+}
+
+void KColorDialog::setColor( const QColor &col )
+{
+ _setColor( col );
+}
+
+//
+// static function to display dialog and return color
+//
+int KColorDialog::getColor( QColor &theColor, QWidget *parent )
+{
+ KColorDialog dlg( parent, "Color Selector", true );
+ if ( theColor.isValid() )
+ dlg.setColor( theColor );
+ int result = dlg.exec();
+
+ if ( result == Accepted )
+ {
+ theColor = dlg.color();
+ }
+
+ return result;
+}
+
+//
+// static function to display dialog and return color
+//
+int KColorDialog::getColor( QColor &theColor, const QColor& defaultCol, QWidget *parent )
+{
+ KColorDialog dlg( parent, "Color Selector", true );
+ dlg.setDefaultColor( defaultCol );
+ dlg.setColor( theColor );
+ int result = dlg.exec();
+
+ if ( result == Accepted )
+ theColor = dlg.color();
+
+ return result;
+}
+
+void KColorDialog::slotRGBChanged( void )
+{
+ if (d->bRecursion) return;
+ int red = d->redit->value();
+ int grn = d->gedit->value();
+ int blu = d->bedit->value();
+
+ if ( red > 255 || red < 0 ) return;
+ if ( grn > 255 || grn < 0 ) return;
+ if ( blu > 255 || blu < 0 ) return;
+
+ KColor col;
+ col.setRgb( red, grn, blu );
+ d->bEditRgb = true;
+ _setColor( col );
+ d->bEditRgb = false;
+}
+
+void KColorDialog::slotHtmlChanged( void )
+{
+ if (d->bRecursion || d->htmlName->text().isEmpty()) return;
+
+ QString strColor( d->htmlName->text() );
+
+ // Assume that a user does not want to type the # all the time
+ if ( strColor[0] != '#' )
+ {
+ bool signalsblocked = d->htmlName->signalsBlocked();
+ d->htmlName->blockSignals(true);
+ strColor.prepend("#");
+ d->htmlName->setText(strColor);
+ d->htmlName->blockSignals(signalsblocked);
+ }
+
+ const QColor color( strColor );
+
+ if ( color.isValid() )
+ {
+ KColor col( color );
+ d->bEditHtml = true;
+ _setColor( col );
+ d->bEditHtml = false;
+ }
+}
+
+void KColorDialog::slotHSVChanged( void )
+{
+ if (d->bRecursion) return;
+ int hue = d->hedit->value();
+ int sat = d->sedit->value();
+ int val = d->vedit->value();
+
+ if ( hue > 359 || hue < 0 ) return;
+ if ( sat > 255 || sat < 0 ) return;
+ if ( val > 255 || val < 0 ) return;
+
+ KColor col;
+ col.setHsv( hue, sat, val );
+ d->bEditHsv = true;
+ _setColor( col );
+ d->bEditHsv = false;
+}
+
+void KColorDialog::slotHSChanged( int h, int s )
+{
+ int _h, _s, v;
+ d->selColor.hsv(&_h, &_s, &v);
+ if (v < 0)
+ v = 0;
+ KColor col;
+ col.setHsv( h, s, v );
+ _setColor( col );
+}
+
+void KColorDialog::slotVChanged( int v )
+{
+ int h, s, _v;
+ d->selColor.hsv(&h, &s, &_v);
+ KColor col;
+ col.setHsv( h, s, v );
+ _setColor( col );
+}
+
+void KColorDialog::slotColorSelected( const QColor &color )
+{
+ _setColor( color );
+}
+
+void KColorDialog::slotAddToCustomColors( )
+{
+ d->table->addToCustomColors( d->selColor );
+}
+
+void KColorDialog::slotColorSelected( const QColor &color, const QString &name )
+{
+ _setColor( color, name);
+}
+
+void KColorDialog::slotColorDoubleClicked
+(
+ const QColor & color,
+ const QString & name
+)
+{
+ _setColor(color, name);
+ accept();
+}
+
+void KColorDialog::_setColor(const KColor &color, const QString &name)
+{
+ if (color.isValid())
+ {
+ if (d->cbDefaultColor && d->cbDefaultColor->isChecked())
+ d->cbDefaultColor->setChecked(false);
+ d->selColor = color;
+ }
+ else
+ {
+ if (d->cbDefaultColor && d->cbDefaultColor->isChecked())
+ d->cbDefaultColor->setChecked(true);
+ d->selColor = d->defaultColor;
+ }
+
+ showColor( d->selColor, name );
+
+ emit colorSelected( d->selColor );
+}
+
+// show but don't set into selColor, nor emit colorSelected
+void KColorDialog::showColor( const KColor &color, const QString &name )
+{
+ d->bRecursion = true;
+
+ if (name.isEmpty())
+ d->colorName->setText( i18n("-unnamed-"));
+ else
+ d->colorName->setText( name );
+
+ d->patch->setColor( color );
+
+ setRgbEdit( color );
+ setHsvEdit( color );
+ setHtmlEdit( color );
+
+ int h, s, v;
+ color.hsv( &h, &s, &v );
+ d->hsSelector->setValues( h, s );
+ d->valuePal->blockSignals(true);
+ d->valuePal->setHue( h );
+ d->valuePal->setSaturation( s );
+ d->valuePal->setValue( v );
+ d->valuePal->updateContents();
+ d->valuePal->blockSignals(false);
+ d->valuePal->repaint( false );
+ d->bRecursion = false;
+}
+
+
+static QWidget *kde_color_dlg_widget = 0;
+
+#ifdef Q_WS_X11
+static int kde_color_dlg_handler(XEvent *event)
+{
+ if (event->type == ButtonRelease)
+ {
+ QMouseEvent e( QEvent::MouseButtonRelease, QPoint(),
+ QPoint(event->xmotion.x_root, event->xmotion.y_root) , 0, 0 );
+ QApplication::sendEvent( kde_color_dlg_widget, &e );
+ return true;
+ }
+ return false;
+}
+#endif
+void
+KColorDialog::slotColorPicker()
+{
+ d->bColorPicking = true;
+#ifdef Q_WS_X11
+ d->oldfilter = qt_set_x11_event_filter(kde_color_dlg_handler);
+#endif
+ kde_color_dlg_widget = this;
+ grabMouse( crossCursor );
+ grabKeyboard();
+}
+
+void
+KColorDialog::mouseReleaseEvent( QMouseEvent *e )
+{
+ if (d->bColorPicking)
+ {
+ d->bColorPicking = false;
+#ifdef Q_WS_X11
+ qt_set_x11_event_filter(d->oldfilter);
+ d->oldfilter = 0;
+#endif
+ releaseMouse();
+ releaseKeyboard();
+ _setColor( grabColor( e->globalPos() ) );
+ return;
+ }
+ KDialogBase::mouseReleaseEvent( e );
+}
+
+QColor
+KColorDialog::grabColor(const QPoint &p)
+{
+ QWidget *desktop = QApplication::desktop();
+ QPixmap pm = QPixmap::grabWindow( desktop->winId(), p.x(), p.y(), 1, 1);
+ QImage i = pm.convertToImage();
+ return i.pixel(0,0);
+}
+
+void
+KColorDialog::keyPressEvent( QKeyEvent *e )
+{
+ if (d->bColorPicking)
+ {
+ if (e->key() == Key_Escape)
+ {
+ d->bColorPicking = false;
+#ifdef Q_WS_X11
+ qt_set_x11_event_filter(d->oldfilter);
+ d->oldfilter = 0;
+#endif
+ releaseMouse();
+ releaseKeyboard();
+ }
+ e->accept();
+ return;
+ }
+ KDialogBase::keyPressEvent( e );
+}
+
+void KColorDialog::setRgbEdit( const KColor &col )
+{
+ if (d->bEditRgb) return;
+ int r, g, b;
+ col.rgb( &r, &g, &b );
+
+ d->redit->setValue( r );
+ d->gedit->setValue( g );
+ d->bedit->setValue( b );
+}
+
+void KColorDialog::setHtmlEdit( const KColor &col )
+{
+ if (d->bEditHtml) return;
+ int r, g, b;
+ col.rgb( &r, &g, &b );
+ QString num;
+
+ num.sprintf("#%02X%02X%02X", r,g,b);
+ d->htmlName->setText( num );
+}
+
+
+void KColorDialog::setHsvEdit( const KColor &col )
+{
+ if (d->bEditHsv) return;
+ int h, s, v;
+ col.hsv( &h, &s, &v );
+
+ d->hedit->setValue( h );
+ d->sedit->setValue( s );
+ d->vedit->setValue( v );
+}
+
+void KHSSelector::virtual_hook( int id, void* data )
+{ KXYSelector::virtual_hook( id, data ); }
+
+void KValueSelector::virtual_hook( int id, void* data )
+{ KSelector::virtual_hook( id, data ); }
+
+void KPaletteTable::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void KColorCells::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void KColorPatch::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void KColorDialog::virtual_hook( int id, void* data )
+{ KDialogBase::virtual_hook( id, data ); }
+
+
+#include "kcolordialog.moc"
+//#endif
diff --git a/kdeui/kcolordialog.h b/kdeui/kcolordialog.h
new file mode 100644
index 000000000..357efe038
--- /dev/null
+++ b/kdeui/kcolordialog.h
@@ -0,0 +1,496 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Martin Jones (mjones@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+//----------------------------------------------------------------------
+// KDE color selection dialog.
+
+// layout management added Oct 1997 by Mario Weilguni
+// <mweilguni@sime.com>
+
+#ifndef KDELIBS_KCOLORDIALOG_H
+#define KDELIBS_KCOLORDIALOG_H
+
+#ifdef Q_WS_QWS
+// FIXME(E): Do we need the KColorDialog extra functionality in Qt Embedded?
+#include <qcolordialog.h>
+#define KColorDialog QColorDialog
+#else //UNIX, WIN32
+#include <kdialogbase.h>
+#include <qframe.h>
+#include <qpixmap.h>
+#include <qgridview.h>
+
+#include "kselect.h"
+
+class QComboBox;
+class QLineEdit;
+class KListBox;
+class KPalette;
+class KColorCells;
+
+
+/**
+ * Widget for Hue/Saturation colour selection.
+ *
+ * The actual values can be fetched using the inherited xValue and yValue
+ * methods.
+ *
+ * \image html khsselector.png "KDE Hue/Saturation Selection Widget"
+ *
+ * @see KXYSelector, KValueSelector, KColorDialog
+ * @author Martin Jones (mjones@kde.org)
+*/
+class KDEUI_EXPORT KHSSelector : public KXYSelector
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Constructs a hue/saturation selection widget.
+ */
+ KHSSelector( QWidget *parent=0, const char *name=0 );
+
+protected:
+ /**
+ * Draws the contents of the widget on a pixmap,
+ * which is used for buffering.
+ */
+ virtual void drawPalette( QPixmap *pixmap );
+ virtual void resizeEvent( QResizeEvent * );
+
+ /**
+ * Reimplemented from KXYSelector. This drawing is
+ * buffered in a pixmap here. As real drawing
+ * routine, drawPalette() is used.
+ */
+ virtual void drawContents( QPainter *painter );
+
+private:
+ void updateContents();
+ QPixmap pixmap;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KHSSelectorPrivate;
+ KHSSelectorPrivate *d;
+};
+
+
+class KValueSelectorPrivate;
+/**
+ * Widget for color value selection.
+ *
+ * @see KHSSelector, KColorDialog
+ * @author Martin Jones (mjones@kde.org)
+ */
+class KDEUI_EXPORT KValueSelector : public KSelector
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Constructs a widget for color selection.
+ */
+ KValueSelector( QWidget *parent=0, const char *name=0 );
+ /**
+ * Constructs a widget for color selection with a given orientation
+ */
+ KValueSelector( Orientation o, QWidget *parent = 0, const char *name = 0 );
+
+ int hue() const
+ { return _hue; }
+ void setHue( int h )
+ { _hue = h; }
+ int saturation() const
+ { return _sat; }
+ void setSaturation( int s )
+ { _sat = s; }
+
+ void updateContents();
+protected:
+ /**
+ * Draws the contents of the widget on a pixmap,
+ * which is used for buffering.
+ */
+ virtual void drawPalette( QPixmap *pixmap );
+ virtual void resizeEvent( QResizeEvent * );
+
+ /**
+ * Reimplemented from KSelector. The drawing is
+ * buffered in a pixmap here. As real drawing
+ * routine, drawPalette() is used.
+ */
+ virtual void drawContents( QPainter *painter );
+
+private:
+ int _hue;
+ int _sat;
+ QPixmap pixmap;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KValueSelectorPrivate;
+ KValueSelectorPrivate *d;
+};
+
+
+/**
+ * A color class that preserves both RGB and HSV values.
+ *
+ * This is
+ * unlike QColor which only preserves RGB values and recalculates HSV
+ * values. The QColor behavior leads to an accumulation of rounding
+ * errors when working in the HSV color space.
+ *
+ * @author Waldo Bastian <bastian@kde.org>
+ **/
+class KDEUI_EXPORT KColor : public QColor
+{
+public:
+ KColor();
+ KColor( const KColor &col);
+ KColor( const QColor &col);
+
+ KColor& operator=( const KColor& col);
+
+ bool operator==( const KColor& col) const;
+
+ void setHsv(int _h, int _s, int _v);
+ void setRgb(int _r, int _g, int _b);
+
+ void rgb(int *_r, int *_g, int *_b) const;
+ void hsv(int *_h, int *_s, int *_v) const;
+protected:
+ int h;
+ int s;
+ int v;
+ int r;
+ int g;
+ int b;
+
+private:
+ class KColorPrivate;
+ KColorPrivate *d;
+};
+
+/**
+ * A color palette in table form.
+ *
+ * @author Waldo Bastian <bastian@kde.org>
+ **/
+class KDEUI_EXPORT KPaletteTable : public QWidget
+{
+ Q_OBJECT
+public:
+ KPaletteTable( QWidget *parent, int minWidth=210, int cols = 16);
+ ~KPaletteTable();
+ void addToCustomColors( const QColor &);
+ void addToRecentColors( const QColor &);
+ QString palette() const;
+public slots:
+ void setPalette(const QString &paletteName);
+signals:
+ void colorSelected( const QColor &, const QString & );
+ void colorDoubleClicked( const QColor &, const QString & );
+
+protected slots:
+ void slotColorCellSelected( int );
+ void slotColorCellDoubleClicked( int );
+ void slotColorTextSelected( const QString &colorText );
+ void slotSetPalette( const QString &_paletteName );
+ void slotShowNamedColorReadError( void );
+
+protected:
+ void readNamedColor( void );
+
+protected:
+ /// \deprecated
+ QString i18n_customColors; /// ### KDE4: remove
+ /// \deprecated
+ QString i18n_recentColors; /// ### KDE4: remove
+ QString i18n_namedColors;
+ QComboBox *combo;
+ KColorCells *cells;
+ QScrollView *sv;
+ KListBox *mNamedColorList;
+ KPalette *mPalette;
+ int mMinWidth;
+ int mCols;
+
+private:
+
+ virtual void setPalette(const QPalette& p) { QWidget::setPalette(p); }
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KPaletteTablePrivate;
+ KPaletteTablePrivate *d;
+};
+
+
+/**
+* A table of editable color cells.
+*
+* @author Martin Jones <mjones@kde.org>
+*/
+class KDEUI_EXPORT KColorCells : public QGridView
+{
+ Q_OBJECT
+public:
+ KColorCells( QWidget *parent, int rows, int cols );
+ ~KColorCells();
+
+ void setColor( int colNum, const QColor &col );
+ QColor color( int indx ) const
+ { return colors[indx]; }
+ int numCells() const
+ { return numRows() * numCols(); }
+
+ void setShading(bool _shade) { shade = _shade; }
+
+ void setAcceptDrags(bool _acceptDrags) { acceptDrags = _acceptDrags; }
+
+ int getSelected() const
+ { return selected; }
+
+ signals:
+ void colorSelected( int col );
+ void colorDoubleClicked( int col );
+
+protected:
+ virtual void paintCell( QPainter *painter, int row, int col );
+ virtual void resizeEvent( QResizeEvent * );
+ virtual void mouseReleaseEvent( QMouseEvent * );
+ virtual void mousePressEvent( QMouseEvent * );
+ virtual void mouseMoveEvent( QMouseEvent * );
+ virtual void dragEnterEvent( QDragEnterEvent *);
+ virtual void dropEvent( QDropEvent *);
+ virtual void mouseDoubleClickEvent( QMouseEvent * );
+
+ int posToCell(const QPoint &pos, bool ignoreBorders=false);
+
+ QColor *colors;
+ bool inMouse;
+ QPoint mPos;
+ int selected;
+ bool shade;
+ bool acceptDrags;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KColorCellsPrivate;
+ KColorCellsPrivate *d;
+};
+
+/**
+ * @short A color displayer.
+ *
+ * The KColorPatch widget is a (usually small) widget showing
+ * a selected color e. g. in the KColorDialog. It
+ * automatically handles drag and drop from and on the widget.
+ *
+ */
+class KDEUI_EXPORT KColorPatch : public QFrame
+{
+ Q_OBJECT
+public:
+ KColorPatch( QWidget *parent );
+ virtual ~KColorPatch();
+
+ void setColor( const QColor &col );
+
+signals:
+ void colorChanged( const QColor&);
+
+protected:
+ virtual void drawContents( QPainter *painter );
+ virtual void mouseMoveEvent( QMouseEvent * );
+ virtual void dragEnterEvent( QDragEnterEvent *);
+ virtual void dropEvent( QDropEvent *);
+
+private:
+ QColor color;
+ uint pixel;
+ int colContext;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KColorPatchPrivate;
+ KColorPatchPrivate *d;
+};
+
+/**
+ * @short A color selection dialog.
+ *
+ * <b>Features:</b>\n
+ *
+ * @li Color selection from a wide range of palettes.
+ * @li Color selection from a palette of H vs S and V selectors.
+ * @li Direct input of HSV or RGB values.
+ * @li Saving of custom colors
+ *
+ * In most cases, you will want to use the static method KColorDialog::getColor().
+ * This pops up the dialog (with an initial selection provided by you), lets the
+ * user choose a color, and returns.
+ *
+ * Example:
+ *
+ * \code
+ * QColor myColor;
+ * int result = KColorDialog::getColor( myColor );
+ * if ( result == KColorDialog::Accepted )
+ * ...
+ * \endcode
+ *
+ * @image html kcolordialog.png "KDE Color Dialog"
+ *
+ * The color dialog is really a collection of several widgets which can
+ * you can also use separately: the quadratic plane in the top left of
+ * the dialog is a KXYSelector. Right next to it is a KHSSelector
+ * for choosing hue/saturation.
+ *
+ * On the right side of the dialog you see a KPaletteTable showing
+ * up to 40 colors with a combo box which offers several predefined
+ * palettes or a palette configured by the user. The small field showing
+ * the currently selected color is a KColorPatch.
+ *
+ **/
+class KDEUI_EXPORT KColorDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Constructs a color selection dialog.
+ */
+ KColorDialog( QWidget *parent = 0L, const char *name = 0L,
+ bool modal = false );
+ /**
+ * Destroys the color selection dialog.
+ */
+ ~KColorDialog();
+
+ /**
+ * Returns the currently selected color.
+ **/
+ QColor color() const;
+
+ /**
+ * Creates a modal color dialog, let the user choose a
+ * color, and returns when the dialog is closed.
+ *
+ * The selected color is returned in the argument @p theColor.
+ *
+ * @returns QDialog::result().
+ */
+ static int getColor( QColor &theColor, QWidget *parent=0L );
+
+ /**
+ * Creates a modal color dialog, lets the user choose a
+ * color, and returns when the dialog is closed.
+ *
+ * The selected color is returned in the argument @p theColor.
+ *
+ * This version takes a @p defaultColor argument, which sets the color
+ * selected by the "default color" checkbox. When this checkbox is checked,
+ * the invalid color (QColor()) is returned into @p theColor.
+ *
+ * @returns QDialog::result().
+ */
+ static int getColor( QColor &theColor, const QColor& defaultColor, QWidget *parent=0L );
+
+ /**
+ * Gets the color from the pixel at point p on the screen.
+ */
+ static QColor grabColor(const QPoint &p);
+
+ /**
+ * Call this to make the dialog show a "Default Color" checkbox.
+ * If this checkbox is selected, the dialog will return an "invalid" color (QColor()).
+ * This can be used to mean "the default text color", for instance,
+ * the one with the KDE text color on screen, but black when printing.
+ */
+ void setDefaultColor( const QColor& defaultCol );
+
+ /**
+ * @return the value passed to setDefaultColor
+ */
+ QColor defaultColor() const;
+
+ public slots:
+ /**
+ * Preselects a color.
+ */
+ void setColor( const QColor &col );
+
+ signals:
+ /**
+ * Emitted when a color is selected.
+ * Connect to this to monitor the color as it as selected if you are
+ * not running modal.
+ */
+ void colorSelected( const QColor &col );
+
+ private slots:
+ void slotRGBChanged( void );
+ void slotHSVChanged( void );
+ void slotHtmlChanged( void );
+ void slotHSChanged( int, int );
+ void slotVChanged( int );
+ void slotColorSelected( const QColor &col );
+ void slotColorSelected( const QColor &col, const QString &name );
+ void slotColorDoubleClicked( const QColor &col, const QString &name );
+ void slotColorPicker();
+ void slotAddToCustomColors();
+ void slotDefaultColorClicked();
+ /**
+ * Write the settings of the dialog to config file.
+ **/
+ void slotWriteSettings();
+
+ private:
+ /**
+ * Read the settings for the dialog from config file.
+ **/
+ void readSettings();
+
+ void setRgbEdit( const KColor &col );
+ void setHsvEdit( const KColor &col );
+ void setHtmlEdit( const KColor &col );
+ void _setColor( const KColor &col, const QString &name=QString::null );
+ void showColor( const KColor &color, const QString &name );
+
+ protected:
+ virtual void mouseReleaseEvent( QMouseEvent * );
+ virtual void keyPressEvent( QKeyEvent * );
+ virtual bool eventFilter( QObject *obj, QEvent *ev );
+
+ protected:
+ virtual void virtual_hook( int id, void* data );
+ private:
+ class KColorDialogPrivate;
+ KColorDialogPrivate *d;
+};
+
+#endif // !Q_WS_QWS
+#endif // KDELIBS_KCOLORDIALOG_H
+
diff --git a/kdeui/kcolordlg.h b/kdeui/kcolordlg.h
new file mode 100644
index 000000000..48b1a8938
--- /dev/null
+++ b/kdeui/kcolordlg.h
@@ -0,0 +1,6 @@
+#ifndef KDE_NO_COMPAT
+#ifndef __KCOLORDLG_H_
+#define __KCOLORDLG_H_
+#include <kcolordialog.h>
+#endif
+#endif
diff --git a/kdeui/kcolordrag.cpp b/kdeui/kcolordrag.cpp
new file mode 100644
index 000000000..61eb15ba1
--- /dev/null
+++ b/kdeui/kcolordrag.cpp
@@ -0,0 +1,112 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Steffen Hansen (hansen@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qpainter.h>
+#include "kcolordrag.h"
+
+static const char * const color_mime_string = "application/x-color";
+static const char * const text_mime_string = "text/plain";
+
+KColorDrag::KColorDrag( const QColor &color, QWidget *dragsource,
+ const char *name)
+ : QStoredDrag( color_mime_string, dragsource, name)
+{
+ setColor( color);
+}
+
+KColorDrag::KColorDrag( QWidget *dragsource, const char *name)
+ : QStoredDrag( color_mime_string, dragsource, name)
+{
+ setColor( white );
+}
+
+void
+KColorDrag::setColor( const QColor &color)
+{
+ QColorDrag tmp(color, 0, 0);
+ setEncodedData(tmp.encodedData(color_mime_string));
+
+ QPixmap colorpix( 25, 20);
+ colorpix.fill( color);
+ QPainter p( &colorpix );
+ p.setPen( black );
+ p.drawRect(0,0,25,20);
+ p.end();
+ setPixmap(colorpix, QPoint(-5,-7));
+}
+
+const char *KColorDrag::format(int i) const
+{
+ if (i==1)
+ return text_mime_string;
+ else
+ return QStoredDrag::format(i);
+}
+
+QByteArray KColorDrag::encodedData ( const char * m ) const
+{
+ if (!qstrcmp(m, text_mime_string) )
+ {
+ QColor color;
+ QColorDrag::decode(const_cast<KColorDrag *>(this), color);
+ QCString result = color.name().latin1();
+ ((QByteArray&)result).resize(result.length());
+ return result;
+ }
+ return QStoredDrag::encodedData(m);
+}
+
+bool
+KColorDrag::canDecode( QMimeSource *e)
+{
+ if (e->provides(color_mime_string))
+ return true;
+ if (e->provides(text_mime_string))
+ {
+ QColor dummy;
+ return decode(e, dummy);
+ }
+ return false;
+}
+
+bool
+KColorDrag::decode( QMimeSource *e, QColor &color)
+{
+ if (QColorDrag::decode(e, color))
+ return true;
+
+ QByteArray data = e->encodedData( text_mime_string);
+ QString colorName = QString::fromLatin1(data.data(), data.size());
+ if ((colorName.length() < 4) || (colorName[0] != '#'))
+ return false;
+ color.setNamedColor(colorName);
+ return color.isValid();
+}
+
+
+KColorDrag*
+KColorDrag::makeDrag( const QColor &color,QWidget *dragsource)
+{
+ return new KColorDrag( color, dragsource);
+}
+
+void KColorDrag::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "kcolordrag.moc"
diff --git a/kdeui/kcolordrag.h b/kdeui/kcolordrag.h
new file mode 100644
index 000000000..696d8a7ab
--- /dev/null
+++ b/kdeui/kcolordrag.h
@@ -0,0 +1,79 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Steffen Hansen (hansen@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+/*
+ * $Id$
+ */
+#ifndef _KCOLORDRAG_H
+#define _KCOLORDRAG_H
+
+#include <qdragobject.h>
+#include <qcolor.h>
+#include <kdelibs_export.h>
+
+class KColorDragPrivate;
+/**
+ * A drag-and-drop object for colors. The according MIME type
+ * is set to application/x-color.
+ *
+ * See the Qt drag'n'drop documentation.
+ */
+class KDEUI_EXPORT KColorDrag : public QStoredDrag {
+ Q_OBJECT
+
+public:
+ /**
+ * Constructs a color drag with a white color.
+ */
+ KColorDrag( QWidget *dragsource = 0, const char *name = 0 );
+ /**
+ * Constructs a color drag with the color @p col.
+ */
+ KColorDrag( const QColor &col, QWidget *dragsource = 0, const char *name = 0 );
+ virtual ~KColorDrag() {}
+
+ virtual const char *format(int i) const;
+ virtual QByteArray encodedData ( const char * m ) const;
+
+ /**
+ * Sets the color of the drag to @p col.
+ */
+ void setColor(const QColor &col);
+ /**
+ * Returns true if the MIME source @p e contains a color object.
+ */
+ static bool canDecode(QMimeSource *e);
+ /**
+ * Decodes the MIME source @p e and puts the resulting color into @p col.
+ */
+ static bool decode(QMimeSource *e, QColor &col);
+ /**
+ * @deprecated This is equivalent with "new KColorDrag(color, dragsource)".
+ */
+ static KColorDrag* makeDrag( const QColor&,QWidget *dragsource) KDE_DEPRECATED;
+
+private:
+ QColor m_color; // unused
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KColorDragPrivate *d;
+};
+
+
+#endif // _KCOLORDRAG_H
diff --git a/kdeui/kcombobox.cpp b/kdeui/kcombobox.cpp
new file mode 100644
index 000000000..602228c48
--- /dev/null
+++ b/kdeui/kcombobox.cpp
@@ -0,0 +1,686 @@
+/* This file is part of the KDE libraries
+
+ Copyright (c) 2000,2001 Dawit Alemayehu <adawit@kde.org>
+ Copyright (c) 2000,2001 Carsten Pfeiffer <pfeiffer@kde.org>
+ Copyright (c) 2000 Stefan Schimanski <1Stein@gmx.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License (LGPL) as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qclipboard.h>
+#include <qlistbox.h>
+#include <qpopupmenu.h>
+#include <qapplication.h>
+
+#include <kcompletionbox.h>
+#include <kcursor.h>
+#include <kiconloader.h>
+#include <kicontheme.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <knotifyclient.h>
+#include <kpixmapprovider.h>
+#include <kstdaccel.h>
+#include <kurl.h>
+#include <kurldrag.h>
+
+#include <kdebug.h>
+
+#include "kcombobox.h"
+
+#include <stdlib.h> // getenv
+
+class KComboBox::KComboBoxPrivate
+{
+public:
+ KComboBoxPrivate() : klineEdit(0L)
+ {
+ }
+ ~KComboBoxPrivate()
+ {
+ }
+
+ KLineEdit *klineEdit;
+};
+
+KComboBox::KComboBox( QWidget *parent, const char *name )
+ : QComboBox( parent, name ), d(new KComboBoxPrivate)
+{
+ init();
+}
+
+KComboBox::KComboBox( bool rw, QWidget *parent, const char *name )
+ : QComboBox( rw, parent, name ), d(new KComboBoxPrivate)
+{
+ init();
+
+ if ( rw )
+ {
+ KLineEdit *edit = new KLineEdit( this, "combo lineedit" );
+ setLineEdit( edit );
+ }
+}
+
+KComboBox::~KComboBox()
+{
+ delete d;
+}
+
+void KComboBox::init()
+{
+ // Permanently set some parameters in the parent object.
+ QComboBox::setAutoCompletion( false );
+
+ // Enable context menu by default if widget
+ // is editable.
+ setContextMenuEnabled( true );
+}
+
+
+bool KComboBox::contains( const QString& _text ) const
+{
+ if ( _text.isEmpty() )
+ return false;
+
+ const int itemCount = count();
+ for (int i = 0; i < itemCount; ++i )
+ {
+ if ( text(i) == _text )
+ return true;
+ }
+ return false;
+}
+
+void KComboBox::setAutoCompletion( bool autocomplete )
+{
+ if ( d->klineEdit )
+ {
+ if ( autocomplete )
+ {
+ d->klineEdit->setCompletionMode( KGlobalSettings::CompletionAuto );
+ setCompletionMode( KGlobalSettings::CompletionAuto );
+ }
+ else
+ {
+ d->klineEdit->setCompletionMode( KGlobalSettings::completionMode() );
+ setCompletionMode( KGlobalSettings::completionMode() );
+ }
+ }
+}
+
+void KComboBox::setContextMenuEnabled( bool showMenu )
+{
+ if( d->klineEdit )
+ d->klineEdit->setContextMenuEnabled( showMenu );
+}
+
+
+void KComboBox::setURLDropsEnabled( bool enable )
+{
+ if ( d->klineEdit )
+ d->klineEdit->setURLDropsEnabled( enable );
+}
+
+bool KComboBox::isURLDropsEnabled() const
+{
+ return d->klineEdit && d->klineEdit->isURLDropsEnabled();
+}
+
+
+void KComboBox::setCompletedText( const QString& text, bool marked )
+{
+ if ( d->klineEdit )
+ d->klineEdit->setCompletedText( text, marked );
+}
+
+void KComboBox::setCompletedText( const QString& text )
+{
+ if ( d->klineEdit )
+ d->klineEdit->setCompletedText( text );
+}
+
+void KComboBox::makeCompletion( const QString& text )
+{
+ if( d->klineEdit )
+ d->klineEdit->makeCompletion( text );
+
+ else // read-only combo completion
+ {
+ if( text.isNull() || !listBox() )
+ return;
+
+ const int index = listBox()->index( listBox()->findItem( text ) );
+ if( index >= 0 )
+ setCurrentItem( index );
+ }
+}
+
+void KComboBox::rotateText( KCompletionBase::KeyBindingType type )
+{
+ if ( d->klineEdit )
+ d->klineEdit->rotateText( type );
+}
+
+// not needed anymore
+bool KComboBox::eventFilter( QObject* o, QEvent* ev )
+{
+ return QComboBox::eventFilter( o, ev );
+}
+
+void KComboBox::setTrapReturnKey( bool grab )
+{
+ if ( d->klineEdit )
+ d->klineEdit->setTrapReturnKey( grab );
+ else
+ qWarning("KComboBox::setTrapReturnKey not supported with a non-KLineEdit.");
+}
+
+bool KComboBox::trapReturnKey() const
+{
+ return d->klineEdit && d->klineEdit->trapReturnKey();
+}
+
+
+void KComboBox::setEditURL( const KURL& url )
+{
+ QComboBox::setEditText( url.prettyURL() );
+}
+
+void KComboBox::insertURL( const KURL& url, int index )
+{
+ QComboBox::insertItem( url.prettyURL(), index );
+}
+
+void KComboBox::insertURL( const QPixmap& pixmap, const KURL& url, int index )
+{
+ QComboBox::insertItem( pixmap, url.prettyURL(), index );
+}
+
+void KComboBox::changeURL( const KURL& url, int index )
+{
+ QComboBox::changeItem( url.prettyURL(), index );
+}
+
+void KComboBox::changeURL( const QPixmap& pixmap, const KURL& url, int index )
+{
+ QComboBox::changeItem( pixmap, url.prettyURL(), index );
+}
+
+void KComboBox::setCompletedItems( const QStringList& items )
+{
+ if ( d->klineEdit )
+ d->klineEdit->setCompletedItems( items );
+}
+
+KCompletionBox * KComboBox::completionBox( bool create )
+{
+ if ( d->klineEdit )
+ return d->klineEdit->completionBox( create );
+ return 0;
+}
+
+// QWidget::create() turns off mouse-Tracking which would break auto-hiding
+void KComboBox::create( WId id, bool initializeWindow, bool destroyOldWindow )
+{
+ QComboBox::create( id, initializeWindow, destroyOldWindow );
+ KCursor::setAutoHideCursor( lineEdit(), true, true );
+}
+
+void KComboBox::wheelEvent( QWheelEvent *ev )
+{
+ // Not necessary anymore
+ QComboBox::wheelEvent( ev );
+}
+
+void KComboBox::setLineEdit( QLineEdit *edit )
+{
+ if ( !editable() && edit &&
+ !qstrcmp( edit->className(), "QLineEdit" ) )
+ {
+ // uic generates code that creates a read-only KComboBox and then
+ // calls combo->setEditable( true ), which causes QComboBox to set up
+ // a dumb QLineEdit instead of our nice KLineEdit.
+ // As some KComboBox features rely on the KLineEdit, we reject
+ // this order here.
+ delete edit;
+ edit = new KLineEdit( this, "combo edit" );
+ }
+
+ QComboBox::setLineEdit( edit );
+ d->klineEdit = dynamic_cast<KLineEdit*>( edit );
+ setDelegate( d->klineEdit );
+
+ // Connect the returnPressed signal for both Q[K]LineEdits'
+ if (edit)
+ connect( edit, SIGNAL( returnPressed() ), SIGNAL( returnPressed() ));
+
+ if ( d->klineEdit )
+ {
+ // someone calling KComboBox::setEditable( false ) destroys our
+ // lineedit without us noticing. And KCompletionBase::delegate would
+ // be a dangling pointer then, so prevent that. Note: only do this
+ // when it is a KLineEdit!
+ connect( edit, SIGNAL( destroyed() ), SLOT( lineEditDeleted() ));
+
+ connect( d->klineEdit, SIGNAL( returnPressed( const QString& )),
+ SIGNAL( returnPressed( const QString& ) ));
+
+ connect( d->klineEdit, SIGNAL( completion( const QString& )),
+ SIGNAL( completion( const QString& )) );
+
+ connect( d->klineEdit, SIGNAL( substringCompletion( const QString& )),
+ SIGNAL( substringCompletion( const QString& )) );
+
+ connect( d->klineEdit,
+ SIGNAL( textRotation( KCompletionBase::KeyBindingType )),
+ SIGNAL( textRotation( KCompletionBase::KeyBindingType )) );
+
+ connect( d->klineEdit,
+ SIGNAL( completionModeChanged( KGlobalSettings::Completion )),
+ SIGNAL( completionModeChanged( KGlobalSettings::Completion)));
+
+ connect( d->klineEdit,
+ SIGNAL( aboutToShowContextMenu( QPopupMenu * )),
+ SIGNAL( aboutToShowContextMenu( QPopupMenu * )) );
+
+ connect( d->klineEdit,
+ SIGNAL( completionBoxActivated( const QString& )),
+ SIGNAL( activated( const QString& )) );
+ }
+}
+
+void KComboBox::setCurrentItem( const QString& item, bool insert, int index )
+{
+ int sel = -1;
+
+ const int itemCount = count();
+ for (int i = 0; i < itemCount; ++i)
+ {
+ if (text(i) == item)
+ {
+ sel = i;
+ break;
+ }
+ }
+
+ if (sel == -1 && insert)
+ {
+ insertItem(item, index);
+ if (index >= 0)
+ sel = index;
+ else
+ sel = count() - 1;
+ }
+ setCurrentItem(sel);
+}
+
+void KComboBox::lineEditDeleted()
+{
+ // yes, we need those ugly casts due to the multiple inheritance
+ // sender() is guaranteed to be a KLineEdit (see the connect() to the
+ // destroyed() signal
+ const KCompletionBase *base = static_cast<const KCompletionBase*>( static_cast<const KLineEdit*>( sender() ));
+
+ // is it our delegate, that is destroyed?
+ if ( base == delegate() )
+ setDelegate( 0L );
+}
+
+
+// *********************************************************************
+// *********************************************************************
+
+
+// we are always read-write
+KHistoryCombo::KHistoryCombo( QWidget *parent, const char *name )
+ : KComboBox( true, parent, name ), d(0)
+{
+ init( true ); // using completion
+}
+
+// we are always read-write
+KHistoryCombo::KHistoryCombo( bool useCompletion,
+ QWidget *parent, const char *name )
+ : KComboBox( true, parent, name ), d(0)
+{
+ init( useCompletion );
+}
+
+void KHistoryCombo::init( bool useCompletion )
+{
+ // Set a default history size to something reasonable, Qt sets it to INT_MAX by default
+ setMaxCount( 50 );
+
+ if ( useCompletion )
+ completionObject()->setOrder( KCompletion::Weighted );
+
+ setInsertionPolicy( NoInsertion );
+ myIterateIndex = -1;
+ myRotated = false;
+ myPixProvider = 0L;
+
+ // obey HISTCONTROL setting
+ QCString histControl = getenv("HISTCONTROL");
+ if ( histControl == "ignoredups" || histControl == "ignoreboth" )
+ setDuplicatesEnabled( false );
+
+ connect( this, SIGNAL(aboutToShowContextMenu(QPopupMenu*)),
+ SLOT(addContextMenuItems(QPopupMenu*)) );
+ connect( this, SIGNAL( activated(int) ), SLOT( slotReset() ));
+ connect( this, SIGNAL( returnPressed(const QString&) ), SLOT(slotReset()));
+}
+
+KHistoryCombo::~KHistoryCombo()
+{
+ delete myPixProvider;
+}
+
+void KHistoryCombo::setHistoryItems( QStringList items,
+ bool setCompletionList )
+{
+ KComboBox::clear();
+
+ // limit to maxCount()
+ const int itemCount = items.count();
+ const int toRemove = itemCount - maxCount();
+
+ if (toRemove >= itemCount) {
+ items.clear();
+ } else {
+ for (int i = 0; i < toRemove; ++i)
+ items.pop_front();
+ }
+
+ insertItems( items );
+
+ if ( setCompletionList && useCompletion() ) {
+ // we don't have any weighting information here ;(
+ KCompletion *comp = completionObject();
+ comp->setOrder( KCompletion::Insertion );
+ comp->setItems( items );
+ comp->setOrder( KCompletion::Weighted );
+ }
+
+ clearEdit();
+}
+
+QStringList KHistoryCombo::historyItems() const
+{
+ QStringList list;
+ const int itemCount = count();
+ for ( int i = 0; i < itemCount; ++i )
+ list.append( text( i ) );
+
+ return list;
+}
+
+void KHistoryCombo::clearHistory()
+{
+ const QString temp = currentText();
+ KComboBox::clear();
+ if ( useCompletion() )
+ completionObject()->clear();
+ setEditText( temp );
+}
+
+void KHistoryCombo::addContextMenuItems( QPopupMenu* menu )
+{
+ if ( menu )
+ {
+ menu->insertSeparator();
+ int id = menu->insertItem( SmallIconSet("history_clear"), i18n("Clear &History"), this, SLOT( slotClear()));
+ if (!count())
+ menu->setItemEnabled(id, false);
+ }
+}
+
+void KHistoryCombo::addToHistory( const QString& item )
+{
+ if ( item.isEmpty() || (count() > 0 && item == text(0) )) {
+ return;
+ }
+
+ bool wasCurrent = false;
+ // remove all existing items before adding
+ if ( !duplicatesEnabled() ) {
+ int i = 0;
+ int itemCount = count();
+ while ( i < itemCount ) {
+ if ( text( i ) == item ) {
+ if ( !wasCurrent )
+ wasCurrent = ( i == currentItem() );
+ removeItem( i );
+ --itemCount;
+ } else {
+ ++i;
+ }
+ }
+ }
+
+ // now add the item
+ if ( myPixProvider )
+ insertItem( myPixProvider->pixmapFor(item, KIcon::SizeSmall), item, 0);
+ else
+ insertItem( item, 0 );
+
+ if ( wasCurrent )
+ setCurrentItem( 0 );
+
+ const bool useComp = useCompletion();
+
+ const int last = count() - 1; // last valid index
+ const int mc = maxCount();
+ const int stopAt = QMAX(mc, 0);
+
+ for (int rmIndex = last; rmIndex >= stopAt; --rmIndex) {
+ // remove the last item, as long as we are longer than maxCount()
+ // remove the removed item from the completionObject if it isn't
+ // anymore available at all in the combobox.
+ const QString rmItem = text( rmIndex );
+ removeItem( rmIndex );
+ if ( useComp && !contains( rmItem ) )
+ completionObject()->removeItem( rmItem );
+ }
+
+ if ( useComp )
+ completionObject()->addItem( item );
+}
+
+bool KHistoryCombo::removeFromHistory( const QString& item )
+{
+ if ( item.isEmpty() )
+ return false;
+
+ bool removed = false;
+ const QString temp = currentText();
+ int i = 0;
+ int itemCount = count();
+ while ( i < itemCount ) {
+ if ( item == text( i ) ) {
+ removed = true;
+ removeItem( i );
+ --itemCount;
+ } else {
+ ++i;
+ }
+ }
+
+ if ( removed && useCompletion() )
+ completionObject()->removeItem( item );
+
+ setEditText( temp );
+ return removed;
+}
+
+void KHistoryCombo::rotateUp()
+{
+ // save the current text in the lineedit
+ if ( myIterateIndex == -1 )
+ myText = currentText();
+
+ ++myIterateIndex;
+
+ // skip duplicates/empty items
+ const int last = count() - 1; // last valid index
+ const QString currText = currentText();
+
+ while ( myIterateIndex < last &&
+ (currText == text( myIterateIndex ) ||
+ text( myIterateIndex ).isEmpty()) )
+ ++myIterateIndex;
+
+ if ( myIterateIndex >= count() ) {
+ myRotated = true;
+ myIterateIndex = -1;
+
+ // if the typed text is the same as the first item, skip the first
+ if ( count() > 0 && myText == text(0) )
+ myIterateIndex = 0;
+
+ setEditText( myText );
+ }
+ else
+ setEditText( text( myIterateIndex ));
+}
+
+void KHistoryCombo::rotateDown()
+{
+ // save the current text in the lineedit
+ if ( myIterateIndex == -1 )
+ myText = currentText();
+
+ --myIterateIndex;
+
+ const QString currText = currentText();
+ // skip duplicates/empty items
+ while ( myIterateIndex >= 0 &&
+ (currText == text( myIterateIndex ) ||
+ text( myIterateIndex ).isEmpty()) )
+ --myIterateIndex;
+
+
+ if ( myIterateIndex < 0 ) {
+ if ( myRotated && myIterateIndex == -2 ) {
+ myRotated = false;
+ myIterateIndex = count() - 1;
+ setEditText( text(myIterateIndex) );
+ }
+ else { // bottom of history
+ if ( myIterateIndex == -2 ) {
+ KNotifyClient::event( (int)winId(), KNotifyClient::notification,
+ i18n("No further item in the history."));
+ }
+
+ myIterateIndex = -1;
+ if ( currentText() != myText )
+ setEditText( myText );
+ }
+ }
+ else
+ setEditText( text( myIterateIndex ));
+
+}
+
+void KHistoryCombo::keyPressEvent( QKeyEvent *e )
+{
+ KKey event_key( e );
+
+ // going up in the history, rotating when reaching QListBox::count()
+ if ( KStdAccel::rotateUp().contains(event_key) )
+ rotateUp();
+
+ // going down in the history, no rotation possible. Last item will be
+ // the text that was in the lineedit before Up was called.
+ else if ( KStdAccel::rotateDown().contains(event_key) )
+ rotateDown();
+ else
+ KComboBox::keyPressEvent( e );
+}
+
+void KHistoryCombo::wheelEvent( QWheelEvent *ev )
+{
+ // Pass to poppable listbox if it's up
+ QListBox* const lb = listBox();
+ if ( lb && lb->isVisible() )
+ {
+ QApplication::sendEvent( lb, ev );
+ return;
+ }
+ // Otherwise make it change the text without emitting activated
+ if ( ev->delta() > 0 ) {
+ rotateUp();
+ } else {
+ rotateDown();
+ }
+ ev->accept();
+}
+
+void KHistoryCombo::slotReset()
+{
+ myIterateIndex = -1;
+ myRotated = false;
+}
+
+
+void KHistoryCombo::setPixmapProvider( KPixmapProvider *prov )
+{
+ if ( myPixProvider == prov )
+ return;
+
+ delete myPixProvider;
+ myPixProvider = prov;
+
+ // re-insert all the items with/without pixmap
+ // I would prefer to use changeItem(), but that doesn't honor the pixmap
+ // when using an editable combobox (what we do)
+ if ( count() > 0 ) {
+ QStringList items( historyItems() );
+ clear();
+ insertItems( items );
+ }
+}
+
+void KHistoryCombo::insertItems( const QStringList& items )
+{
+ QStringList::ConstIterator it = items.constBegin();
+ const QStringList::ConstIterator itEnd = items.constEnd();
+
+ while ( it != itEnd ) {
+ const QString item = *it;
+ if ( !item.isEmpty() ) { // only insert non-empty items
+ if ( myPixProvider )
+ insertItem( myPixProvider->pixmapFor(item, KIcon::SizeSmall),
+ item );
+ else
+ insertItem( item );
+ }
+ ++it;
+ }
+}
+
+void KHistoryCombo::slotClear()
+{
+ clearHistory();
+ emit cleared();
+}
+
+void KComboBox::virtual_hook( int id, void* data )
+{ KCompletionBase::virtual_hook( id, data ); }
+
+void KHistoryCombo::virtual_hook( int id, void* data )
+{ KComboBox::virtual_hook( id, data ); }
+
+#include "kcombobox.moc"
diff --git a/kdeui/kcombobox.h b/kdeui/kcombobox.h
new file mode 100644
index 000000000..47f76a59e
--- /dev/null
+++ b/kdeui/kcombobox.h
@@ -0,0 +1,779 @@
+/* This file is part of the KDE libraries
+
+ Copyright (c) 2000,2001 Dawit Alemayehu <adawit@kde.org>
+ Copyright (c) 2000,2001 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License (LGPL) as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _KCOMBOBOX_H
+#define _KCOMBOBOX_H
+
+#include <qlineedit.h>
+#include <qcombobox.h>
+
+#include <kcompletion.h>
+
+class QListBoxItem;
+class QPopupMenu;
+class QLineEdit;
+
+class KCompletionBox;
+class KURL;
+
+/**
+ * @short An enhanced combo box.
+ *
+ * A combined button, line-edit and a popup list widget.
+ *
+ * \b Detail \n
+ *
+ * This widget inherits from QComboBox and implements the following
+ * additional functionalities: a completion object that provides both automatic
+ * and manual text completion as well as text rotation features, configurable
+ * key-bindings to activate these features, and a popup-menu item that can be
+ * used to allow the user to change the text completion mode on the fly.
+ *
+ * To support these new features KComboBox emits a few additional signals
+ * such as completion( const QString& ) and textRotation( KeyBindgingType ).
+ * The completion signal can be connected to a slot that will assist the user in
+ * filling out the remaining text while the rotation signal can be used to traverse
+ * through all possible matches whenever text completion results in multiple matches.
+ * Additionally, a returnPressed() and a returnPressed( const QString& )
+ * signals are emitted when the user presses the Enter/Return key.
+ *
+ * KCombobox by default creates a completion object when you invoke the
+ * completionObject( bool ) member function for the first time or
+ * explicitly use setCompletionObject( KCompletion*, bool ) to assign your
+ * own completion object. Additionally, to make this widget more functional,
+ * KComboBox will by default handle text rotation and completion events
+ * internally whenever a completion object is created through either one of the
+ * methods mentioned above. If you do not need this functionality, simply use
+ * @p setHandleSignals(bool) or alternatively set the boolean parameter in the
+ * @p setCompletionObject call to false.
+ *
+ * Beware: The completion object can be deleted on you, especially if a call
+ * such as setEditable(false) is made. Store the pointer at your own risk,
+ * and consider using QGuardedPtr<KCompletion>.
+ *
+ * The default key-bindings for completion and rotation is determined from the
+ * global settings in KStdAccel. These values, however, can be overridden
+ * locally by invoking KCompletionBase::setKeyBinding(). The values can
+ * easily be reverted back to the default setting, by simply calling
+ * useGlobalSettings(). An alternate method would be to default individual
+ * key-bindings by usning setKeyBinding() with the default second argument.
+ *
+ * A non-editable combobox only has one completion mode, @p CompletionAuto.
+ * Unlike an editable combobox the CompletionAuto mode, works by matching
+ * any typed key with the first letter of entries in the combobox. Please note
+ * that if you call setEditable( false ) to change an editable combobox to a
+ * non-editable one, the text completion object associated with the combobox will
+ * no longer exist unless you created the completion object yourself and assigned
+ * it to this widget or you called setAutoDeleteCompletionObject( false ). In other
+ * words do not do the following:
+ *
+ * \code
+ * KComboBox* combo = new KCompletionBox(true, this, "mywidget");
+ * KCompletion* comp = combo->completionObject();
+ * combo->setEditable( false );
+ * comp->clear(); // CRASH: completion object does not exist anymore.
+ * \endcode
+ *
+ *
+ * A read-only KComboBox will have the same background color as a
+ * disabled KComboBox, but its foreground color will be the one used for
+ * the read-write mode. This differs from QComboBox's implementation
+ * and is done to give visual distinction between the three different modes:
+ * disabled, read-only, and read-write.
+ *
+ * \b Usage \n
+ *
+ * To enable the basic completion feature:
+ *
+ * \code
+ * KComboBox *combo = new KComboBox( true, this, "mywidget" );
+ * KCompletion *comp = combo->completionObject();
+ * // Connect to the return pressed signal - optional
+ * connect(combo,SIGNAL(returnPressed(const QString&)),comp,SLOT(addItem(const QString&)));
+ *
+ * // Provide the to be completed strings. Note that those are separate from the combo's
+ * // contents.
+ * comp->insertItems( someQStringList );
+ * \endcode
+ *
+ * To use your own completion object:
+ *
+ * \code
+ * KComboBox *combo = new KComboBox( this,"mywidget" );
+ * KURLCompletion *comp = new KURLCompletion();
+ * combo->setCompletionObject( comp );
+ * // Connect to the return pressed signal - optional
+ * connect(combo,SIGNAL(returnPressed(const QString&)),comp,SLOT(addItem(const QString&)));
+ * \endcode
+ *
+ * Note that you have to either delete the allocated completion object
+ * when you don't need it anymore, or call
+ * setAutoDeleteCompletionObject( true );
+ *
+ * Miscellaneous function calls:
+ *
+ * \code
+ * // Tell the widget not to handle completion and rotation
+ * combo->setHandleSignals( false );
+ * // Set your own completion key for manual completions.
+ * combo->setKeyBinding( KCompletionBase::TextCompletion, Qt::End );
+ * // Hide the context (popup) menu
+ * combo->setContextMenuEnabled( false );
+ * \endcode
+ *
+ * @author Dawit Alemayehu <adawit@kde.org>
+ */
+class KDEUI_EXPORT KComboBox : public QComboBox, public KCompletionBase
+{
+ Q_OBJECT
+ Q_PROPERTY( bool autoCompletion READ autoCompletion WRITE setAutoCompletion )
+ Q_PROPERTY( bool contextMenuEnabled READ isContextMenuEnabled WRITE setContextMenuEnabled )
+ Q_PROPERTY( bool urlDropsEnabled READ isURLDropsEnabled WRITE setURLDropsEnabled )
+ Q_PROPERTY( bool trapReturnKey READ trapReturnKey WRITE setTrapReturnKey )
+
+public:
+
+ /**
+ * Constructs a read-only or rather select-only combo box with a
+ * parent object and a name.
+ *
+ * @param parent The parent object of this widget
+ * @param name The name of this widget
+ */
+ KComboBox( QWidget *parent=0, const char *name=0 );
+
+ /**
+ * Constructs a "read-write" or "read-only" combo box depending on
+ * the value of the first argument( @p rw ) with a parent, a
+ * name.
+ *
+ * @param rw When @p true, widget will be editable.
+ * @param parent The parent object of this widget.
+ * @param name The name of this widget.
+ */
+ KComboBox( bool rw, QWidget *parent=0, const char *name=0 );
+
+ /**
+ * Destructor.
+ */
+ virtual ~KComboBox();
+
+ /**
+ * Sets @p url into the edit field of the combobox. It uses
+ * KURL::prettyURL() so that the url is properly decoded for
+ * displaying.
+ */
+ void setEditURL( const KURL& url );
+
+ /**
+ * Inserts @p url at position @p index into the combobox. The item will
+ * be appended if @p index is negative. KURL::prettyURL() is used
+ * so that the url is properly decoded for displaying.
+ */
+ void insertURL( const KURL& url, int index = -1 );
+
+ /**
+ * Inserts @p url with the pixmap &p pixmap at position @p index into
+ * the combobox. The item will be appended if @p index is negative.
+ * KURL::prettyURL() is used so that the url is properly decoded
+ * for displaying.
+ */
+ void insertURL( const QPixmap& pixmap, const KURL& url, int index = -1 );
+
+ /**
+ * Replaces the item at position @p index with @p url.
+ * KURL::prettyURL() is used so that the url is properly decoded
+ * for displaying.
+ */
+ void changeURL( const KURL& url, int index );
+
+ /**
+ * Replaces the item at position @p index with @p url and pixmap @p pixmap.
+ * KURL::prettyURL() is used so that the url is properly decoded
+ * for displaying.
+ */
+ void changeURL( const QPixmap& pixmap, const KURL& url, int index );
+
+ /**
+ * Returns the current cursor position.
+ *
+ * This method always returns a -1 if the combo-box is @em not
+ * editable (read-write).
+ *
+ * @return Current cursor position.
+ */
+ int cursorPosition() const { return ( lineEdit() ) ? lineEdit()->cursorPosition() : -1; }
+
+ /**
+ * Re-implemented from QComboBox.
+ *
+ * If @p true, the completion mode will be set to automatic.
+ * Otherwise, it is defaulted to the global setting. This
+ * method has been replaced by the more comprehensive
+ * setCompletionMode().
+ *
+ * @param autocomplete Flag to enable/disable automatic completion mode.
+ */
+ virtual void setAutoCompletion( bool autocomplete );
+
+ /**
+ * Re-implemented from QComboBox.
+ *
+ * Returns @p true if the current completion mode is set
+ * to automatic. See its more comprehensive replacement
+ * completionMode().
+ *
+ * @return @p true when completion mode is automatic.
+ */
+ bool autoCompletion() const {
+ return completionMode() == KGlobalSettings::CompletionAuto;
+ }
+
+ /**
+ * Enables or disable the popup (context) menu.
+ *
+ * This method only works if this widget is editable, i.e.
+ * read-write and allows you to enable/disable the context
+ * menu. It does nothing if invoked for a none-editable
+ * combo-box. Note that by default the mode changer item
+ * is made visiable whenever the context menu is enabled.
+ * Use hideModechanger() if you want to hide this
+ * item. Also by default, the context menu is created if
+ * this widget is editable. Call this function with the
+ * argument set to false to disable the popup menu.
+ *
+ * @param showMenu If @p true, show the context menu.
+ */
+ virtual void setContextMenuEnabled( bool showMenu );
+
+ /**
+ * Returns @p true when the context menu is enabled.
+ */
+ bool isContextMenuEnabled() const { return m_bEnableMenu; }
+
+ /**
+ * Enables/Disables handling of URL drops. If enabled and the user
+ * drops an URL, the decoded URL will be inserted. Otherwise the default
+ * behavior of QComboBox is used, which inserts the encoded URL.
+ *
+ * @param enable If @p true, insert decoded URLs
+ */
+ void setURLDropsEnabled( bool enable );
+
+ /**
+ * Returns @p true when decoded URL drops are enabled
+ */
+ bool isURLDropsEnabled() const;
+
+ /**
+ * Convenience method which iterates over all items and checks if
+ * any of them is equal to @p text.
+ *
+ * If @p text is an empty string, @p false
+ * is returned.
+ *
+ * @return @p true if an item with the string @p text is in the combobox.
+ */
+ bool contains( const QString& text ) const;
+
+ /**
+ * By default, KComboBox recognizes Key_Return and Key_Enter
+ * and emits the returnPressed() signals, but it also lets the
+ * event pass, for example causing a dialog's default-button to
+ * be called.
+ *
+ * Call this method with @p trap equal to true to make KComboBox
+ * stop these events. The signals will still be emitted of course.
+ *
+ * Only affects read-writable comboboxes.
+ *
+ * @see setTrapReturnKey()
+ */
+ void setTrapReturnKey( bool trap );
+
+ /**
+ * @return @p true if keyevents of Key_Return or Key_Enter will
+ * be stopped or if they will be propagated.
+ *
+ * @see setTrapReturnKey ()
+ */
+ bool trapReturnKey() const;
+
+ /**
+ * Re-implemented for internal reasons. API not affected.
+ */
+ virtual bool eventFilter( QObject *, QEvent * );
+
+ /**
+ * @returns the completion-box, that is used in completion mode
+ * KGlobalSettings::CompletionPopup and KGlobalSettings::CompletionPopupAuto.
+ * This method will create a completion-box by calling
+ * KLineEdit::completionBox, if none is there, yet.
+ *
+ * @param create Set this to false if you don't want the box to be created
+ * i.e. to test if it is available.
+ */
+ KCompletionBox * completionBox( bool create = true );
+
+ /**
+ * Re-implemented for internal reasons. API remains unaffected.
+ * NOTE: Only editable comboboxes can have a line editor. As such
+ * any attempt to assign a line-edit to a non-editable combobox will
+ * simply be ignored.
+ */
+ virtual void setLineEdit( QLineEdit * );
+
+signals:
+ /**
+ * Emitted when the user presses the Enter key.
+ *
+ * Note that this signal is only emitted when the widget is editable.
+ */
+ void returnPressed();
+
+ /**
+ * Emitted when the user presses the Enter key.
+ *
+ * The argument is the current text being edited. This signal is just like
+ * returnPressed() except it contains the current text as its argument.
+ *
+ * Note that this signal is only emitted when the
+ * widget is editable.
+ */
+ void returnPressed( const QString& );
+
+ /**
+ * Emitted when the completion key is pressed.
+ *
+ * The argument is the current text being edited.
+ *
+ * Note that this signal is @em not available when the widget is non-editable
+ * or the completion mode is set to @p KGlobalSettings::CompletionNone.
+ */
+ void completion( const QString& );
+
+ /**
+ * Emitted when the shortcut for substring completion is pressed.
+ */
+ void substringCompletion( const QString& );
+
+ /**
+ * Emitted when the text rotation key-bindings are pressed.
+ *
+ * The argument indicates which key-binding was pressed. In this
+ * case this can be either one of four values: @p PrevCompletionMatch,
+ * @p NextCompletionMatch, @p RotateUp or @p RotateDown. See
+ * @p setKeyBinding() for details.
+ *
+ * Note that this signal is @em NOT emitted if the completion
+ * mode is set to CompletionNone.
+ */
+ void textRotation( KCompletionBase::KeyBindingType );
+
+ /**
+ * Emitted whenever the completion mode is changed by the user
+ * through the context menu.
+ */
+ void completionModeChanged( KGlobalSettings::Completion );
+
+ /**
+ * Emitted before the context menu is displayed.
+ *
+ * The signal allows you to add your own entries into the context menu.
+ * Note that you MUST NOT store the pointer to the QPopupMenu since it is
+ * created and deleted on demand. Otherwise, you can crash your app.
+ *
+ * @param p the context menu about to be displayed
+ */
+ void aboutToShowContextMenu( QPopupMenu * p );
+
+public slots:
+
+ /**
+ * Iterates through all possible matches of the completed text
+ * or the history list.
+ *
+ * Depending on the value of the argument, this function either
+ * iterates through the history list of this widget or the all
+ * possible matches in whenever multiple matches result from a
+ * text completion request. Note that the all-possible-match
+ * iteration will not work if there are no previous matches, i.e.
+ * no text has been completed and the *nix shell history list
+ * rotation is only available if the insertion policy for this
+ * widget is set either @p QComobBox::AtTop or @p QComboBox::AtBottom.
+ * For other insertion modes whatever has been typed by the user
+ * when the rotation event was initiated will be lost.
+ *
+ * @param type The key-binding invoked.
+ */
+ void rotateText( KCompletionBase::KeyBindingType type );
+
+ /**
+ * Sets the completed text in the line-edit appropriately.
+ *
+ * This function is a re-implementation of @p setCompletedText.
+ */
+ virtual void setCompletedText( const QString& );
+
+ /**
+ * Sets @p items into the completion-box if completionMode() is
+ * CompletionPopup. The popup will be shown immediately.
+ */
+ void setCompletedItems( const QStringList& items );
+
+ /**
+ * Selects the first item that matches @p item. If there is no such item,
+ * it is inserted at position @p index if @p insert is true. Otherwise,
+ * no item is selected.
+ */
+ void setCurrentItem( const QString& item, bool insert = false, int index = -1 );
+
+ /**
+ * Simply calls QComboBox' implementation. Only here to not become
+ * shadowed.
+ */
+ void setCurrentItem(int index) { QComboBox::setCurrentItem(index); }
+
+protected slots:
+
+ /**
+ * @deprecated
+ */
+ virtual void itemSelected( QListBoxItem* ) {}
+
+ /**
+ * Completes text according to the completion mode.
+ *
+ * Note: this method is @p not invoked if the completion mode is
+ * set to CompletionNone. Also if the mode is set to @p CompletionShell
+ * and multiple matches are found, this method will complete the
+ * text to the first match with a beep to inidicate that there are
+ * more matches. Then any successive completion key event iterates
+ * through the remaining matches. This way the rotation functionality
+ * is left to iterate through the list as usual.
+ */
+ virtual void makeCompletion( const QString& );
+
+protected:
+ /*
+ * This function simply sets the lineedit text and
+ * highlights the text appropriately if the boolean
+ * value is set to true.
+ *
+ * @param
+ * @param
+ */
+ virtual void setCompletedText( const QString& /* */, bool /*marked*/ );
+
+ /**
+ * Reimplemented for internal reasons, the API is not affected.
+ */
+ virtual void create( WId = 0, bool initializeWindow = true,
+ bool destroyOldWindow = true );
+
+ virtual void wheelEvent( QWheelEvent *ev );
+
+private slots:
+ void lineEditDeleted();
+
+private:
+ /**
+ * Initializes the variables upon construction.
+ */
+ void init();
+ bool m_bEnableMenu; // ### BCI: unused, remove in KDE4
+ bool m_trapReturnKey; // ### BCI: unused, remove in KDE4
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+
+private:
+ class KComboBoxPrivate;
+ KComboBoxPrivate* const d;
+};
+
+
+class KPixmapProvider;
+
+/**
+ * @short A combobox for offering a history and completion
+ *
+ * A combobox which implements a history like a unix shell. You can navigate
+ * through all the items by using the Up or Down arrows (configurable of
+ * course). Additionally, weighted completion is available. So you should
+ * load and save the completion list to preserve the weighting between
+ * sessions.
+ *
+ * KHistoryCombo obeys the HISTCONTROL environment variable to determine
+ * whether duplicates in the history should be tolerated in
+ * addToHistory() or not. During construction of KHistoryCombo,
+ * duplicates will be disabled when HISTCONTROL is set to "ignoredups" or
+ * "ignoreboth". Otherwise, duplicates are enabled by default.
+ *
+ * @author Carsten Pfeiffer <pfeiffer@kde.org>
+ */
+class KDEUI_EXPORT KHistoryCombo : public KComboBox
+{
+ Q_OBJECT
+ Q_PROPERTY( QStringList historyItems READ historyItems WRITE setHistoryItems )
+
+public:
+ /**
+ * Constructs a "read-write" combobox. A read-only history combobox
+ * doesn't make much sense, so it is only available as read-write.
+ * Completion will be used automatically for the items in the combo.
+ *
+ * The insertion-policy is set to NoInsertion, you have to add the items
+ * yourself via the slot addToHistory. If you want every item added,
+ * use
+ *
+ * \code
+ * connect( combo, SIGNAL( activated( const QString& )),
+ * combo, SLOT( addToHistory( const QString& )));
+ * \endcode
+ *
+ * Use QComboBox::setMaxCount() to limit the history.
+ *
+ * @p parent the parent object of this widget.
+ * @p name the name of this widget.
+ */
+ KHistoryCombo( QWidget *parent = 0L, const char *name = 0L );
+
+ // ### merge these two constructors
+ /**
+ * Same as the previous constructor, but additionally has the option
+ * to specify whether you want to let KHistoryCombo handle completion
+ * or not. If set to @p true, KHistoryCombo will sync the completion to the
+ * contents of the combobox.
+ */
+ KHistoryCombo( bool useCompletion,
+ QWidget *parent = 0L, const char *name = 0L );
+
+ /**
+ * Destructs the combo, the completion-object and the pixmap-provider
+ */
+ ~KHistoryCombo();
+
+ /**
+ * Inserts @p items into the combobox. @p items might get
+ * truncated if it is longer than maxCount()
+ *
+ * @see historyItems
+ */
+ inline void setHistoryItems( QStringList items ) {
+ setHistoryItems(items, false);
+ }
+
+ /**
+ * Inserts @p items into the combobox. @p items might get
+ * truncated if it is longer than maxCount()
+ *
+ * Set @p setCompletionList to true, if you don't have a list of
+ * completions. This tells KHistoryCombo to use all the items for the
+ * completion object as well.
+ * You won't have the benefit of weighted completion though, so normally
+ * you should do something like
+ * \code
+ * KConfig *config = kapp->config();
+ * QStringList list;
+ *
+ * // load the history and completion list after creating the history combo
+ * list = config->readListEntry( "Completion list" );
+ * combo->completionObject()->setItems( list );
+ * list = config->readListEntry( "History list" );
+ * combo->setHistoryItems( list );
+ *
+ * [...]
+ *
+ * // save the history and completion list when the history combo is
+ * // destroyed
+ * list = combo->completionObject()->items()
+ * config->writeEntry( "Completion list", list );
+ * list = combo->historyItems();
+ * config->writeEntry( "History list", list );
+ * \endcode
+ *
+ * Be sure to use different names for saving with KConfig if you have more
+ * than one KHistoryCombo.
+ *
+ * Note: When @p setCompletionList is true, the items are inserted into the
+ * KCompletion object with mode KCompletion::Insertion and the mode is set
+ * to KCompletion::Weighted afterwards.
+ *
+ * @see historyItems
+ * @see KComboBox::completionObject
+ * @see KCompletion::setItems
+ * @see KCompletion::items
+ */
+ void setHistoryItems( QStringList items, bool setCompletionList );
+
+ /**
+ * Returns the list of history items. Empty, when this is not a read-write
+ * combobox.
+ *
+ * @see setHistoryItems
+ */
+ QStringList historyItems() const;
+
+ /**
+ * Removes all items named @p item.
+ *
+ * @return @p true if at least one item was removed.
+ *
+ * @see addToHistory
+ */
+ bool removeFromHistory( const QString& item );
+
+ /**
+ * Sets a pixmap provider, so that items in the combobox can have a pixmap.
+ * KPixmapProvider is just an abstract class with the one pure virtual
+ * method KPixmapProvider::pixmapFor(). This method is called whenever
+ * an item is added to the KHistoryComboBox. Implement it to return your
+ * own custom pixmaps, or use the KURLPixmapProvider from libkio,
+ * which uses KMimeType::pixmapForURL to resolve icons.
+ *
+ * Set @p prov to 0L if you want to disable pixmaps. Default no pixmaps.
+ *
+ * @see pixmapProvider
+ */
+ void setPixmapProvider( KPixmapProvider *prov );
+
+ /**
+ * @returns the current pixmap provider.
+ * @see setPixmapProvider
+ * @see KPixmapProvider
+ */
+ KPixmapProvider * pixmapProvider() const { return myPixProvider; }
+
+ /**
+ * Resets the current position of the up/down history. Call this
+ * when you manually call setCurrentItem() or clearEdit().
+ */
+ void reset() { slotReset(); }
+
+public slots:
+ /**
+ * Adds an item to the end of the history list and to the completion list.
+ * If maxCount() is reached, the first item of the list will be
+ * removed.
+ *
+ * If the last inserted item is the same as @p item, it will not be
+ * inserted again.
+ *
+ * If duplicatesEnabled() is false, any equal existing item will be
+ * removed before @p item is added.
+ *
+ * Note: By using this method and not the Q and KComboBox insertItem()
+ * methods, you make sure that the combobox stays in sync with the
+ * completion. It would be annoying if completion would give an item
+ * not in the combobox, and vice versa.
+ *
+ * @see removeFromHistory
+ * @see QComboBox::setDuplicatesEnabled
+ */
+ void addToHistory( const QString& item );
+
+ /**
+ * Clears the history and the completion list.
+ */
+ void clearHistory();
+
+signals:
+ /**
+ * Emitted when the history was cleared by the entry in the popup menu.
+ */
+ void cleared();
+
+protected:
+ /**
+ * Handling key-events, the shortcuts to rotate the items.
+ */
+ virtual void keyPressEvent( QKeyEvent * );
+
+ /**
+ * Handling wheel-events, to rotate the items.
+ */
+ virtual void wheelEvent( QWheelEvent *ev );
+
+ /**
+ * Inserts @p items into the combo, honoring pixmapProvider()
+ * Does not update the completionObject.
+ *
+ * Note: duplicatesEnabled() is not honored here.
+ *
+ * Called from setHistoryItems() and setPixmapProvider()
+ */
+ void insertItems( const QStringList& items );
+
+ /**
+ * @returns if we can modify the completion object or not.
+ */
+ bool useCompletion() const { return compObj(); }
+
+private slots:
+ /**
+ * Resets the iterate index to -1
+ */
+ void slotReset();
+
+ /**
+ * Called from the popupmenu,
+ * calls clearHistory() and emits cleared()
+ */
+ void slotClear();
+
+ /**
+ * Appends our own context menu entry.
+ */
+ void addContextMenuItems( QPopupMenu* );
+
+private:
+ void init( bool useCompletion );
+ void rotateUp();
+ void rotateDown();
+
+ /**
+ * The current position (index) in the combobox, used for Up and Down
+ */
+ int myIterateIndex;
+
+ /**
+ * The text typed before Up or Down was pressed.
+ */
+ QString myText;
+
+ /**
+ * Indicates that the user at least once rotated Up through the entire list
+ * Needed to allow going back after rotation.
+ */
+ bool myRotated;
+ KPixmapProvider *myPixProvider;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KHistoryComboPrivate;
+ KHistoryComboPrivate* const d;
+};
+
+
+#endif
+
diff --git a/kdeui/kcommand.cpp b/kdeui/kcommand.cpp
new file mode 100644
index 000000000..bf133c609
--- /dev/null
+++ b/kdeui/kcommand.cpp
@@ -0,0 +1,379 @@
+/* This file is part of the KDE project
+ Copyright (C) 2000 Werner Trobin <trobin@kde.org>
+ Copyright (C) 2000 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kcommand.h"
+#include <kaction.h>
+#include <kstdaccel.h>
+#include <kstdaction.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kpopupmenu.h>
+
+KCommand::~KCommand()
+{
+}
+
+KMacroCommand::KMacroCommand( const QString & name ) : KNamedCommand(name)
+{
+ m_commands.setAutoDelete(true);
+}
+
+void KMacroCommand::addCommand(KCommand *command)
+{
+ m_commands.append(command);
+}
+
+void KMacroCommand::execute()
+{
+ QPtrListIterator<KCommand> it(m_commands);
+ for ( ; it.current() ; ++it )
+ it.current()->execute();
+}
+
+void KMacroCommand::unexecute()
+{
+ QPtrListIterator<KCommand> it(m_commands);
+ it.toLast();
+ for ( ; it.current() ; --it )
+ it.current()->unexecute();
+}
+
+
+class KCommandHistory::KCommandHistoryPrivate {
+public:
+ KCommandHistoryPrivate() {
+ m_savedAt=-1;
+ m_present=0;
+ }
+ ~KCommandHistoryPrivate() {}
+ int m_savedAt;
+ KCommand *m_present;
+};
+
+////////////
+
+KCommandHistory::KCommandHistory() :
+ m_undo(0), m_redo(0), m_undoLimit(50), m_redoLimit(30), m_first(false)
+{
+ d=new KCommandHistoryPrivate();
+ m_commands.setAutoDelete(true);
+ clear();
+}
+
+KCommandHistory::KCommandHistory(KActionCollection * actionCollection, bool withMenus) :
+ m_undoLimit(50), m_redoLimit(30), m_first(false)
+{
+ d=new KCommandHistoryPrivate();
+ if (withMenus)
+ {
+ KToolBarPopupAction * undo = new KToolBarPopupAction( i18n("&Undo"), "undo",
+ KStdAccel::shortcut(KStdAccel::Undo), this, SLOT( undo() ),
+ actionCollection, KStdAction::stdName( KStdAction::Undo ) );
+ connect( undo->popupMenu(), SIGNAL( aboutToShow() ), this, SLOT( slotUndoAboutToShow() ) );
+ connect( undo->popupMenu(), SIGNAL( activated( int ) ), this, SLOT( slotUndoActivated( int ) ) );
+ m_undo = undo;
+ m_undoPopup = undo->popupMenu();
+
+ KToolBarPopupAction * redo = new KToolBarPopupAction( i18n("&Redo"), "redo",
+ KStdAccel::shortcut(KStdAccel::Redo), this, SLOT( redo() ),
+ actionCollection, KStdAction::stdName( KStdAction::Redo ) );
+ connect( redo->popupMenu(), SIGNAL( aboutToShow() ), this, SLOT( slotRedoAboutToShow() ) );
+ connect( redo->popupMenu(), SIGNAL( activated( int ) ), this, SLOT( slotRedoActivated( int ) ) );
+ m_redo = redo;
+ m_redoPopup = redo->popupMenu();
+ }
+ else
+ {
+ m_undo = KStdAction::undo( this, SLOT( undo() ), actionCollection );
+ m_redo = KStdAction::redo( this, SLOT( redo() ), actionCollection );
+ m_undoPopup = 0L;
+ m_redoPopup = 0L;
+ }
+ m_commands.setAutoDelete(true);
+ clear();
+}
+
+KCommandHistory::~KCommandHistory() {
+ delete d;
+}
+
+void KCommandHistory::clear() {
+ if (m_undo) {
+ m_undo->setEnabled(false);
+ m_undo->setText(i18n("&Undo"));
+ }
+ if (m_redo) {
+ m_redo->setEnabled(false);
+ m_redo->setText(i18n("&Redo"));
+ }
+ d->m_present = 0L;
+ d->m_savedAt=-42;
+}
+
+void KCommandHistory::addCommand(KCommand *command, bool execute) {
+
+ if(!command)
+ return;
+
+ int index;
+ if(d->m_present && (index=m_commands.findRef(d->m_present))!=-1) {
+ if (m_first)
+ --index;
+ m_commands.insert(index+1, command);
+ // truncate history
+ unsigned int count=m_commands.count();
+ for(unsigned int i=index+2; i<count; ++i)
+ m_commands.removeLast();
+ // check whether we still can reach savedAt
+ if(index<d->m_savedAt)
+ d->m_savedAt=-1;
+ d->m_present=command;
+ m_first=false;
+ if (m_undo) {
+ m_undo->setEnabled(true);
+ m_undo->setText(i18n("&Undo: %1").arg(d->m_present->name()));
+ }
+ if((m_redo) && m_redo->isEnabled()) {
+ m_redo->setEnabled(false);
+ m_redo->setText(i18n("&Redo"));
+ }
+ clipCommands();
+ }
+ else { // either this is the first time we add a Command or something has gone wrong
+ kdDebug(230) << "Initializing the Command History" << endl;
+ m_commands.clear();
+ m_commands.append(command);
+ d->m_present=command;
+ if (m_undo) {
+ m_undo->setEnabled(true);
+ m_undo->setText(i18n("&Undo: %1").arg(d->m_present->name()));
+ }
+ if (m_redo) {
+ m_redo->setEnabled(false);
+ m_redo->setText(i18n("&Redo"));
+ }
+ m_first=false; // Michael B: yes, that *is* correct :-)
+ }
+ if ( execute )
+ {
+ command->execute();
+ emit commandExecuted();
+ emit commandExecuted(command);
+ }
+}
+
+void KCommandHistory::undo() {
+
+ if (m_first || !d->m_present)
+ return;
+
+ d->m_present->unexecute();
+ emit commandExecuted();
+ emit commandExecuted(d->m_present);
+ if (m_redo) {
+ m_redo->setEnabled(true);
+ m_redo->setText(i18n("&Redo: %1").arg(d->m_present->name()));
+ }
+ int index;
+ if((index=m_commands.findRef(d->m_present))!=-1 && m_commands.prev()) {
+ d->m_present=m_commands.current();
+ if (m_undo) {
+ m_undo->setEnabled(true);
+ m_undo->setText(i18n("&Undo: %1").arg(d->m_present->name()));
+ }
+ --index;
+ if(index==d->m_savedAt)
+ emit documentRestored();
+ }
+ else {
+ if (m_undo) {
+ m_undo->setEnabled(false);
+ m_undo->setText(i18n("&Undo"));
+ }
+ if(d->m_savedAt==-42)
+ emit documentRestored();
+ m_first=true;
+ }
+ clipCommands(); // only needed here and in addCommand, NOT in redo
+}
+
+void KCommandHistory::redo() {
+
+ int index;
+ if(m_first) {
+ d->m_present->execute();
+ emit commandExecuted();
+ emit commandExecuted(d->m_present);
+ m_first=false;
+ m_commands.first();
+ if(!d->m_savedAt)
+ emit documentRestored();
+ }
+ else if((index=m_commands.findRef(d->m_present))!=-1 && m_commands.next()) {
+ d->m_present=m_commands.current();
+ d->m_present->execute();
+ emit commandExecuted();
+ emit commandExecuted(d->m_present);
+ ++index;
+ if(index==d->m_savedAt)
+ emit documentRestored();
+ }
+
+ if (m_undo) {
+ m_undo->setEnabled(true);
+ m_undo->setText(i18n("&Undo: %1").arg(d->m_present->name()));
+ }
+
+ if(m_commands.next()) {
+ if (m_redo) {
+ m_redo->setEnabled(true);
+ m_redo->setText(i18n("&Redo: %1").arg(m_commands.current()->name()));
+ }
+ }
+ else {
+ if((m_redo) && m_redo->isEnabled()) {
+ m_redo->setEnabled(false);
+ m_redo->setText(i18n("&Redo"));
+ }
+ }
+}
+
+void KCommandHistory::documentSaved() {
+ if(d->m_present && !m_first)
+ d->m_savedAt=m_commands.findRef(d->m_present);
+ else if(!d->m_present && !m_first)
+ d->m_savedAt=-42; // this value signals that the document has
+ // been saved with an empty history.
+ else if(m_first)
+ d->m_savedAt=-42;
+}
+
+void KCommandHistory::setUndoLimit(int limit) {
+
+ if(limit>0 && limit!=m_undoLimit) {
+ m_undoLimit=limit;
+ clipCommands();
+ }
+}
+
+void KCommandHistory::setRedoLimit(int limit) {
+
+ if(limit>0 && limit!=m_redoLimit) {
+ m_redoLimit=limit;
+ clipCommands();
+ }
+}
+
+void KCommandHistory::clipCommands() {
+
+ int count=m_commands.count();
+ if(count<=m_undoLimit && count<=m_redoLimit)
+ return;
+
+ int index=m_commands.findRef(d->m_present);
+ if(index>=m_undoLimit) {
+ for(int i=0; i<=(index-m_undoLimit); ++i) {
+ m_commands.removeFirst();
+ --d->m_savedAt;
+ if(d->m_savedAt==-1)
+ d->m_savedAt=-42;
+ }
+ index=m_commands.findRef(d->m_present); // calculate the new
+ count=m_commands.count(); // values (for the redo-branch :)
+ // make it easier for us... d->m_savedAt==-1 -> invalid
+ if(d->m_savedAt!=-42 && d->m_savedAt<-1)
+ d->m_savedAt=-1;
+ }
+ // adjust the index if it's the first command
+ if(m_first)
+ index=-1;
+ if((index+m_redoLimit+1)<count) {
+ if(d->m_savedAt>(index+m_redoLimit))
+ d->m_savedAt=-1;
+ for(int i=0; i<(count-(index+m_redoLimit+1)); ++i)
+ m_commands.removeLast();
+ }
+}
+
+void KCommandHistory::slotUndoAboutToShow()
+{
+ m_undoPopup->clear();
+ int i = 0;
+ if (m_commands.findRef(d->m_present)!=-1)
+ while ( m_commands.current() && i<10 ) // TODO make number of items configurable ?
+ {
+ m_undoPopup->insertItem( i18n("Undo: %1").arg(m_commands.current()->name()), i++ );
+ m_commands.prev();
+ }
+}
+
+void KCommandHistory::slotUndoActivated( int pos )
+{
+ kdDebug(230) << "KCommandHistory::slotUndoActivated " << pos << endl;
+ for ( int i = 0 ; i < pos+1; ++i )
+ undo();
+}
+
+void KCommandHistory::slotRedoAboutToShow()
+{
+ m_redoPopup->clear();
+ int i = 0;
+ if (m_first)
+ {
+ d->m_present = m_commands.first();
+ m_redoPopup->insertItem( i18n("Redo: %1").arg(d->m_present->name()), i++ );
+ }
+ if (m_commands.findRef(d->m_present)!=-1 && m_commands.next())
+ while ( m_commands.current() && i<10 ) // TODO make number of items configurable ?
+ {
+ m_redoPopup->insertItem( i18n("Redo: %1").arg(m_commands.current()->name()), i++ );
+ m_commands.next();
+ }
+}
+
+void KCommandHistory::slotRedoActivated( int pos )
+{
+ kdDebug(230) << "KCommandHistory::slotRedoActivated " << pos << endl;
+ for ( int i = 0 ; i < pos+1; ++i )
+ redo();
+}
+
+void KCommandHistory::updateActions()
+{
+ if ( m_undo && m_redo )
+ {
+ m_undo->setEnabled( !m_first && ( d->m_present ) );
+ m_redo->setEnabled(m_first || (m_commands.findRef(d->m_present)!=-1 && m_commands.next()));
+ }
+}
+
+void KCommand::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void KNamedCommand::virtual_hook( int id, void* data )
+{ KCommand::virtual_hook( id, data ); }
+
+void KMacroCommand::virtual_hook( int id, void* data )
+{ KNamedCommand::virtual_hook( id, data ); }
+
+void KCommandHistory::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "kcommand.moc"
diff --git a/kdeui/kcommand.h b/kdeui/kcommand.h
new file mode 100644
index 000000000..c47838fb4
--- /dev/null
+++ b/kdeui/kcommand.h
@@ -0,0 +1,289 @@
+/* This file is part of the KDE project
+ Copyright (C) 2000 Werner Trobin <trobin@kde.org>
+ Copyright (C) 2000 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef kcommand_h
+#define kcommand_h
+
+#include <qptrlist.h>
+#include <qstring.h>
+#include <qobject.h>
+#include <kdelibs_export.h>
+
+class KAction;
+class KActionCollection;
+class QPopupMenu;
+
+/**
+ * The abstract base class for all Commands. Commands are used to
+ * store information needed for Undo/Redo functionality...
+ */
+class KDEUI_EXPORT KCommand
+{
+protected:
+ /**
+ * Creates a command.
+ */
+ KCommand() {}
+
+public:
+ virtual ~KCommand();
+
+ /**
+ * The main method: executes this command.
+ * Implement here what this command is about, and remember to
+ * record any information that will be helpful for #unexecute.
+ */
+ virtual void execute() = 0;
+ /**
+ * Unexecutes (undo) this command.
+ * Implement here the steps to take for undoing the command.
+ * If your application uses actions for everything (it should),
+ * and if you implement unexecute correctly, the application is in the same
+ * state after unexecute as it was before execute. This means, the next
+ * call to execute will do the same thing as it did the first time.
+ */
+ virtual void unexecute() = 0;
+
+ /**
+ * @return the name of this command, translated, since it will appear
+ * in the menus.
+ */
+ virtual QString name() const = 0;
+protected:
+ virtual void virtual_hook( int id, void* data );
+};
+
+/**
+ * A command which stores its name.
+ * It is more memory-efficient to use KCommand and to implement the name() method,
+ * but in some cases it's more simple or more flexible to store the name at creation time.
+ */
+class KDEUI_EXPORT KNamedCommand : public KCommand
+{
+protected:
+ /**
+ * Creates a command.
+ * @param name the name of this command, translated, since it will appear
+ * in the menus.
+ */
+ KNamedCommand(const QString &name) : KCommand(), m_name(name) {}
+
+public:
+ /**
+ * @return the name of this command
+ */
+ virtual QString name() const { return m_name; }
+ /**
+ * Updates the name of this command.
+ * Rarely necessary.
+ */
+ void setName(const QString &name) { m_name=name; }
+
+private:
+ QString m_name;
+protected:
+ virtual void virtual_hook( int id, void* data );
+};
+
+/**
+ * A Macro Command is a command that holds several sub-commands.
+ * It will appear as one to the user and in the command history,
+ * but it can use the implementation of multiple commands internally.
+ */
+class KDEUI_EXPORT KMacroCommand : public KNamedCommand
+{
+public:
+ /**
+ * Creates a macro command. You will then need to call addCommand
+ * for each subcommand to be added to this macro command.
+ * @param name the name of this command, translated, since it will appear
+ * in the menus.
+ */
+ KMacroCommand( const QString & name );
+ virtual ~KMacroCommand() {}
+
+ /**
+ * Appends a command to this macro command.
+ * The ownership is transfered to the macro command.
+ */
+ void addCommand(KCommand *command);
+
+ /**
+ * Executes this command, i.e. execute all the sub-commands
+ * in the order in which they were added.
+ */
+ virtual void execute();
+ /**
+ * Undoes the execution of this command, i.e. #unexecute all the sub-commands
+ * in the _reverse_ order to the one in which they were added.
+ */
+ virtual void unexecute();
+
+protected:
+ QPtrList<KCommand> m_commands;
+protected:
+ virtual void virtual_hook( int id, void* data );
+};
+
+
+/**
+ * The command history stores a (user) configurable amount of
+ * Commands. It keeps track of its size and deletes commands
+ * if it gets too large. The user can set a maximum undo and
+ * a maximum redo limit (e.g. max. 50 undo / 30 redo commands).
+ * The KCommandHistory keeps track of the "borders" and deletes
+ * commands, if appropriate. It also activates/deactivates the
+ * undo/redo actions in the menu and changes the text according
+ * to the name of the command.
+ */
+class KDEUI_EXPORT KCommandHistory : public QObject {
+ Q_OBJECT
+public:
+ /**
+ * Creates a command history, to store commands.
+ * This constructor doesn't create actions, so you need to call
+ * #undo and #redo yourself.
+ */
+ KCommandHistory();
+
+ /**
+ * Creates a command history, to store commands.
+ * This also creates an undo and a redo action, in the @p actionCollection,
+ * using the standard names ("edit_undo" and "edit_redo").
+ * @param withMenus if true, the actions will display a menu when plugged
+ * into a toolbar.
+ * @param actionCollection the parent collection
+ */
+ KCommandHistory(KActionCollection *actionCollection, bool withMenus = true);
+
+ /**
+ * Destructs the command history object.
+ */
+ virtual ~KCommandHistory();
+
+ /**
+ * Erases all the undo/redo history.
+ * Use this when reloading the data, for instance, since this invalidates
+ * all the commands.
+ */
+ void clear();
+
+ /**
+ * Adds a command to the history. Call this for each @p command you create.
+ * Unless you set @p execute to false, this will also execute the command.
+ * This means, most of the application's code will look like
+ * MyCommand * cmd = new MyCommand(i18n("Capitalized Name"), parameters);
+ * m_historyCommand.addCommand( cmd );
+ */
+ void addCommand(KCommand *command, bool execute=true);
+
+ /**
+ * @return the maximum number of items in the undo history
+ */
+ int undoLimit() const { return m_undoLimit; }
+ /**
+ * Sets the maximum number of items in the undo history.
+ */
+ void setUndoLimit(int limit);
+ /**
+ * @return the maximum number of items in the redo history
+ */
+ int redoLimit() const { return m_redoLimit; }
+ /**
+ * Sets the maximum number of items in the redo history.
+ */
+ void setRedoLimit(int limit);
+
+ /**
+ * Enable or disable the undo and redo actions.
+ * This isn't usually necessary, but this method can be useful if
+ * you disable all actions (to go to a "readonly" state), and then
+ * want to come back to a readwrite mode.
+ */
+ void updateActions();
+
+public slots:
+ /**
+ * Undoes the last action.
+ * Call this if you don't use the builtin KActions.
+ */
+ virtual void undo();
+ /**
+ * Redoes the last undone action.
+ * Call this if you don't use the builtin KActions.
+ */
+ virtual void redo();
+ /**
+ * Remembers when you saved the document.
+ * Call this right after saving the document. As soon as
+ * the history reaches the current index again (via some
+ * undo/redo operations) it will emit documentRestored
+ * If you implemented undo/redo properly the document is
+ * the same you saved before.
+ */
+ virtual void documentSaved();
+
+protected slots:
+ void slotUndoAboutToShow();
+ void slotUndoActivated( int );
+ void slotRedoAboutToShow();
+ void slotRedoActivated( int );
+
+signals:
+ /**
+ * Emitted every time a command is executed
+ * (whether by addCommand, undo or redo).
+ * You can use this to update the GUI, for instance.
+ *
+ * KDE4 TODO: remove
+ */
+ void commandExecuted();
+
+ /**
+ * Emitted every time a command is executed
+ * (whether by addCommand, undo or redo).
+ * You can use this to update the GUI, for instance.
+ * @param command was executed
+ * @since 3.5
+ */
+ void commandExecuted(KCommand *command);
+
+ /**
+ * Emitted every time we reach the index where you
+ * saved the document for the last time. See documentSaved
+ */
+ void documentRestored();
+
+private:
+ void clipCommands(); // ensures that the limits are kept
+
+ QPtrList<KCommand> m_commands;
+ KAction *m_undo, *m_redo;
+ QPopupMenu *m_undoPopup, *m_redoPopup;
+ int m_undoLimit, m_redoLimit;
+ bool m_first; // attention: it's the first command in the list!
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KCommandHistoryPrivate;
+ KCommandHistoryPrivate *d;
+};
+
+#endif
diff --git a/kdeui/kcompletionbox.cpp b/kdeui/kcompletionbox.cpp
new file mode 100644
index 000000000..63791724b
--- /dev/null
+++ b/kdeui/kcompletionbox.cpp
@@ -0,0 +1,562 @@
+/* This file is part of the KDE libraries
+
+ Copyright (c) 2000,2001,2002 Carsten Pfeiffer <pfeiffer@kde.org>
+ Copyright (c) 2000 Stefan Schimanski <1Stein@gmx.de>
+ Copyright (c) 2000,2001,2002,2003,2004 Dawit Alemayehu <adawit@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License (LGPL) as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#include <qapplication.h>
+#include <qcombobox.h>
+#include <qevent.h>
+#include <qstyle.h>
+
+#include <kdebug.h>
+#include <kconfig.h>
+#include <knotifyclient.h>
+#include <kglobalsettings.h>
+
+#include "kcompletionbox.h"
+
+class KCompletionBox::KCompletionBoxPrivate
+{
+public:
+ QWidget *m_parent; // necessary to set the focus back
+ QString cancelText;
+ bool tabHandling;
+ bool down_workaround;
+ bool upwardBox;
+ bool emitSelected;
+};
+
+KCompletionBox::KCompletionBox( QWidget *parent, const char *name )
+ :KListBox( parent, name, WType_Popup ), d(new KCompletionBoxPrivate)
+{
+
+ d->m_parent = parent;
+ d->tabHandling = true;
+ d->down_workaround = false;
+ d->upwardBox = false;
+ d->emitSelected = true;
+
+ setColumnMode( 1 );
+ setLineWidth( 1 );
+ setFrameStyle( QFrame::Box | QFrame::Plain );
+
+ if ( parent )
+ setFocusProxy( parent );
+ else
+ setFocusPolicy( NoFocus );
+
+ setVScrollBarMode( Auto );
+ setHScrollBarMode( AlwaysOff );
+
+ connect( this, SIGNAL( doubleClicked( QListBoxItem * )),
+ SLOT( slotActivated( QListBoxItem * )) );
+
+ // grmbl, just QListBox workarounds :[ Thanks Volker.
+ connect( this, SIGNAL( currentChanged( QListBoxItem * )),
+ SLOT( slotCurrentChanged() ));
+ connect( this, SIGNAL( clicked( QListBoxItem * )),
+ SLOT( slotItemClicked( QListBoxItem * )) );
+}
+
+KCompletionBox::~KCompletionBox()
+{
+ d->m_parent = 0L;
+ delete d;
+}
+
+QStringList KCompletionBox::items() const
+{
+ QStringList list;
+
+ const QListBoxItem* currItem = firstItem();
+
+ while (currItem) {
+ list.append(currItem->text());
+ currItem = currItem->next();
+ }
+
+ return list;
+}
+
+void KCompletionBox::slotActivated( QListBoxItem *item )
+{
+ if ( !item )
+ return;
+
+ hide();
+ emit activated( item->text() );
+}
+
+bool KCompletionBox::eventFilter( QObject *o, QEvent *e )
+{
+ int type = e->type();
+
+ if ( o == d->m_parent ) {
+ if ( isVisible() ) {
+ if ( type == QEvent::KeyPress ) {
+ QKeyEvent *ev = static_cast<QKeyEvent *>( e );
+ switch ( ev->key() ) {
+ case Key_BackTab:
+ if ( d->tabHandling && (ev->state() == NoButton ||
+ (ev->state() & ShiftButton)) ) {
+ up();
+ ev->accept();
+ return true;
+ }
+ break;
+ case Key_Tab:
+ if ( d->tabHandling && (ev->state() == NoButton) ) {
+ down(); // Only on TAB!!
+ ev->accept();
+ return true;
+ }
+ break;
+ case Key_Down:
+ down();
+ ev->accept();
+ return true;
+ case Key_Up:
+ // If there is no selected item and we've popped up above
+ // our parent, select the first item when they press up.
+ if ( selectedItem() ||
+ mapToGlobal( QPoint( 0, 0 ) ).y() >
+ d->m_parent->mapToGlobal( QPoint( 0, 0 ) ).y() )
+ up();
+ else
+ down();
+ ev->accept();
+ return true;
+ case Key_Prior:
+ pageUp();
+ ev->accept();
+ return true;
+ case Key_Next:
+ pageDown();
+ ev->accept();
+ return true;
+ case Key_Escape:
+ canceled();
+ ev->accept();
+ return true;
+ case Key_Enter:
+ case Key_Return:
+ if ( ev->state() & ShiftButton ) {
+ hide();
+ ev->accept(); // Consume the Enter event
+ return true;
+ }
+ break;
+ case Key_End:
+ if ( ev->state() & ControlButton )
+ {
+ end();
+ ev->accept();
+ return true;
+ }
+ case Key_Home:
+ if ( ev->state() & ControlButton )
+ {
+ home();
+ ev->accept();
+ return true;
+ }
+ default:
+ break;
+ }
+ }
+ else if ( type == QEvent::AccelOverride ) {
+ // Override any acceleartors that match
+ // the key sequences we use here...
+ QKeyEvent *ev = static_cast<QKeyEvent *>( e );
+ switch ( ev->key() ) {
+ case Key_Down:
+ case Key_Up:
+ case Key_Prior:
+ case Key_Next:
+ case Key_Escape:
+ case Key_Enter:
+ case Key_Return:
+ ev->accept();
+ return true;
+ break;
+ case Key_Tab:
+ case Key_BackTab:
+ if ( ev->state() == NoButton ||
+ (ev->state() & ShiftButton))
+ {
+ ev->accept();
+ return true;
+ }
+ break;
+ case Key_Home:
+ case Key_End:
+ if ( ev->state() & ControlButton )
+ {
+ ev->accept();
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ // parent loses focus or gets a click -> we hide
+ else if ( type == QEvent::FocusOut || type == QEvent::Resize ||
+ type == QEvent::Close || type == QEvent::Hide ||
+ type == QEvent::Move ) {
+ hide();
+ }
+ }
+ }
+
+ // any mouse-click on something else than "this" makes us hide
+ else if ( type == QEvent::MouseButtonPress ) {
+ QMouseEvent *ev = static_cast<QMouseEvent *>( e );
+ if ( !rect().contains( ev->pos() )) // this widget
+ hide();
+
+ if ( !d->emitSelected && currentItem() && !::qt_cast<QScrollBar*>(o) )
+ {
+ emit highlighted( currentText() );
+ hide();
+ ev->accept(); // Consume the mouse click event...
+ return true;
+ }
+ }
+
+ return KListBox::eventFilter( o, e );
+}
+
+
+void KCompletionBox::popup()
+{
+ if ( count() == 0 )
+ hide();
+ else {
+ ensureCurrentVisible();
+ bool block = signalsBlocked();
+ blockSignals( true );
+ setCurrentItem( 0 );
+ blockSignals( block );
+ clearSelection();
+ if ( !isVisible() )
+ show();
+ else if ( size().height() != sizeHint().height() )
+ sizeAndPosition();
+ }
+}
+
+void KCompletionBox::sizeAndPosition()
+{
+ int currentGeom = height();
+ QPoint currentPos = pos();
+ QRect geom = calculateGeometry();
+ resize( geom.size() );
+
+ int x = currentPos.x(), y = currentPos.y();
+ if ( d->m_parent ) {
+ if ( !isVisible() ) {
+ QRect screenSize = KGlobalSettings::desktopGeometry(d->m_parent);
+
+ QPoint orig = d->m_parent->mapToGlobal( QPoint(0, d->m_parent->height()) );
+ x = orig.x() + geom.x();
+ y = orig.y() + geom.y();
+
+ if ( x + width() > screenSize.right() )
+ x = screenSize.right() - width();
+ if (y + height() > screenSize.bottom() ) {
+ y = y - height() - d->m_parent->height();
+ d->upwardBox = true;
+ }
+ }
+ else {
+ // Are we above our parent? If so we must keep bottom edge anchored.
+ if (d->upwardBox)
+ y += (currentGeom-height());
+ }
+ move( x, y);
+ }
+}
+
+void KCompletionBox::show()
+{
+ d->upwardBox = false;
+ if ( d->m_parent ) {
+ sizeAndPosition();
+ qApp->installEventFilter( this );
+ }
+
+ // ### we shouldn't need to call this, but without this, the scrollbars
+ // are pretty b0rked.
+ //triggerUpdate( true );
+
+ // Workaround for I'm not sure whose bug - if this KCompletionBox' parent
+ // is in a layout, that layout will detect inserting new child (posted
+ // ChildInserted event), and will trigger relayout (post LayoutHint event).
+ // QWidget::show() sends also posted ChildInserted events for the parent,
+ // and later all LayoutHint events, which causes layout updating.
+ // The problem is, KCompletionBox::eventFilter() detects resizing
+ // of the parent, and calls hide() - and this hide() happen in the middle
+ // of show(), causing inconsistent state. I'll try to submit a Qt patch too.
+ qApp->sendPostedEvents();
+ KListBox::show();
+}
+
+void KCompletionBox::hide()
+{
+ if ( d->m_parent )
+ qApp->removeEventFilter( this );
+ d->cancelText = QString::null;
+ KListBox::hide();
+}
+
+QRect KCompletionBox::calculateGeometry() const
+{
+ int x = 0, y = 0;
+ int ih = itemHeight();
+ int h = QMIN( 15 * ih, (int) count() * ih ) + 2*frameWidth();
+
+ int w = (d->m_parent) ? d->m_parent->width() : KListBox::minimumSizeHint().width();
+ w = QMAX( KListBox::minimumSizeHint().width(), w );
+
+ //If we're inside a combox, Qt by default makes the dropdown
+ // as wide as the combo, and gives the style a chance
+ // to adjust it. Do that here as well, for consistency
+ const QObject* combo;
+ if ( d->m_parent && (combo = d->m_parent->parent() ) &&
+ combo->inherits("QComboBox") )
+ {
+ const QComboBox* cb = static_cast<const QComboBox*>(combo);
+
+ //Expand to the combo width
+ w = QMAX( w, cb->width() );
+
+ QPoint parentCorner = d->m_parent->mapToGlobal(QPoint(0, 0));
+ QPoint comboCorner = cb->mapToGlobal(QPoint(0, 0));
+
+ //We need to adjust our horizontal position to also be WRT to the combo
+ x += comboCorner.x() - parentCorner.x();
+
+ //The same with vertical one
+ y += cb->height() - d->m_parent->height() +
+ comboCorner.y() - parentCorner.y();
+
+ //Ask the style to refine this a bit
+ QRect styleAdj = style().querySubControlMetrics(QStyle::CC_ComboBox,
+ cb, QStyle::SC_ComboBoxListBoxPopup,
+ QStyleOption(x, y, w, h));
+ //QCommonStyle returns QRect() by default, so this is what we get if the
+ //style doesn't implement this
+ if (!styleAdj.isNull())
+ return styleAdj;
+
+ }
+ return QRect(x, y, w, h);
+}
+
+QSize KCompletionBox::sizeHint() const
+{
+ return calculateGeometry().size();
+}
+
+void KCompletionBox::down()
+{
+ int i = currentItem();
+
+ if ( i == 0 && d->down_workaround ) {
+ d->down_workaround = false;
+ setCurrentItem( 0 );
+ setSelected( 0, true );
+ emit highlighted( currentText() );
+ }
+
+ else if ( i < (int) count() - 1 )
+ setCurrentItem( i + 1 );
+}
+
+void KCompletionBox::up()
+{
+ if ( currentItem() > 0 )
+ setCurrentItem( currentItem() - 1 );
+}
+
+void KCompletionBox::pageDown()
+{
+ int i = currentItem() + numItemsVisible();
+ i = i > (int)count() - 1 ? (int)count() - 1 : i;
+ setCurrentItem( i );
+}
+
+void KCompletionBox::pageUp()
+{
+ int i = currentItem() - numItemsVisible();
+ i = i < 0 ? 0 : i;
+ setCurrentItem( i );
+}
+
+void KCompletionBox::home()
+{
+ setCurrentItem( 0 );
+}
+
+void KCompletionBox::end()
+{
+ setCurrentItem( count() -1 );
+}
+
+void KCompletionBox::setTabHandling( bool enable )
+{
+ d->tabHandling = enable;
+}
+
+bool KCompletionBox::isTabHandling() const
+{
+ return d->tabHandling;
+}
+
+void KCompletionBox::setCancelledText( const QString& text )
+{
+ d->cancelText = text;
+}
+
+QString KCompletionBox::cancelledText() const
+{
+ return d->cancelText;
+}
+
+void KCompletionBox::canceled()
+{
+ if ( !d->cancelText.isNull() )
+ emit userCancelled( d->cancelText );
+ if ( isVisible() )
+ hide();
+}
+
+class KCompletionBoxItem : public QListBoxItem
+{
+public:
+ //Returns true if dirty.
+ bool reuse( const QString& newText )
+ {
+ if ( text() == newText )
+ return false;
+ setText( newText );
+ return true;
+ }
+};
+
+
+void KCompletionBox::insertItems( const QStringList& items, int index )
+{
+ bool block = signalsBlocked();
+ blockSignals( true );
+ insertStringList( items, index );
+ blockSignals( block );
+ d->down_workaround = true;
+}
+
+void KCompletionBox::setItems( const QStringList& items )
+{
+ bool block = signalsBlocked();
+ blockSignals( true );
+
+ QListBoxItem* item = firstItem();
+ if ( !item ) {
+ insertStringList( items );
+ }
+ else {
+ //Keep track of whether we need to change anything,
+ //so we can avoid a repaint for identical updates,
+ //to reduce flicker
+ bool dirty = false;
+
+ QStringList::ConstIterator it = items.constBegin();
+ const QStringList::ConstIterator itEnd = items.constEnd();
+
+ for ( ; it != itEnd; ++it) {
+ if ( item ) {
+ const bool changed = ((KCompletionBoxItem*)item)->reuse( *it );
+ dirty = dirty || changed;
+ item = item->next();
+ }
+ else {
+ dirty = true;
+ //Inserting an item is a way of making this dirty
+ insertItem( new QListBoxText( *it ) );
+ }
+ }
+
+ //If there is an unused item, mark as dirty -> less items now
+ if ( item ) {
+ dirty = true;
+ }
+
+ QListBoxItem* tmp = item;
+ while ( (item = tmp ) ) {
+ tmp = item->next();
+ delete item;
+ }
+
+ if (dirty)
+ triggerUpdate( false );
+ }
+
+ if ( isVisible() && size().height() != sizeHint().height() )
+ sizeAndPosition();
+
+ blockSignals( block );
+ d->down_workaround = true;
+}
+
+void KCompletionBox::slotCurrentChanged()
+{
+ d->down_workaround = false;
+}
+
+void KCompletionBox::slotItemClicked( QListBoxItem *item )
+{
+ if ( item )
+ {
+ if ( d->down_workaround ) {
+ d->down_workaround = false;
+ emit highlighted( item->text() );
+ }
+
+ hide();
+ emit activated( item->text() );
+ }
+}
+
+void KCompletionBox::setActivateOnSelect(bool state)
+{
+ d->emitSelected = state;
+}
+
+bool KCompletionBox::activateOnSelect() const
+{
+ return d->emitSelected;
+}
+
+void KCompletionBox::virtual_hook( int id, void* data )
+{ KListBox::virtual_hook( id, data ); }
+
+#include "kcompletionbox.moc"
diff --git a/kdeui/kcompletionbox.h b/kdeui/kcompletionbox.h
new file mode 100644
index 000000000..f7669802d
--- /dev/null
+++ b/kdeui/kcompletionbox.h
@@ -0,0 +1,246 @@
+/* This file is part of the KDE libraries
+
+ Copyright (c) 2000 Carsten Pfeiffer <pfeiffer@kde.org>
+ 2000 Stefan Schimanski <1Stein@gmx.de>
+ 2000,2001,2002,2003,2004 Dawit Alemayehu <adawit@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License (LGPL) as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCOMPLETIONBOX_H
+#define KCOMPLETIONBOX_H
+
+class QEvent;
+#include <qstringlist.h>
+#include <klistbox.h>
+
+/**
+ * @short A helper widget for "completion-widgets" (KLineEdit, KComboBox))
+ *
+ * A little utility class for "completion-widgets", like KLineEdit or
+ * KComboBox. KCompletionBox is a listbox, displayed as a rectangle without
+ * any window decoration, usually directly under the lineedit or combobox.
+ * It is filled with all possible matches for a completion, so the user
+ * can select the one he wants.
+ *
+ * It is used when KGlobalSettings::Completion == CompletionPopup or CompletionPopupAuto.
+ *
+ * @author Carsten Pfeiffer <pfeiffer@kde.org>
+ */
+class KDEUI_EXPORT KCompletionBox : public KListBox
+{
+ Q_OBJECT
+ Q_PROPERTY( bool isTabHandling READ isTabHandling WRITE setTabHandling )
+ Q_PROPERTY(QString cancelledText READ cancelledText WRITE setCancelledText)
+ Q_PROPERTY( bool activateOnSelect READ activateOnSelect WRITE setActivateOnSelect )
+
+public:
+ /**
+ * Constructs a KCompletionBox.
+ *
+ * The parent widget is used to give the focus back when pressing the
+ * up-button on the very first item.
+ */
+ KCompletionBox( QWidget *parent, const char *name = 0 );
+
+ /**
+ * Destroys the box
+ */
+ ~KCompletionBox();
+
+ virtual QSize sizeHint() const;
+
+ /**
+ * @returns true if selecting an item results in the emition of the selected signal.
+ *
+ * @since 3.4.1
+ */
+ bool activateOnSelect() const;
+
+public slots:
+ /**
+ * Returns a list of all items currently in the box.
+ */
+ QStringList items() const;
+
+ /**
+ * Inserts @p items into the box. Does not clear the items before.
+ * @p index determines at which position @p items will be inserted.
+ * (defaults to appending them at the end)
+ */
+ void insertItems( const QStringList& items, int index = -1 );
+
+ /**
+ * Clears the box and inserts @p items.
+ */
+ void setItems( const QStringList& items );
+
+ /**
+ * Adjusts the size of the box to fit the width of the parent given in the
+ * constructor and pops it up at the most appropriate place, relative to
+ * the parent.
+ *
+ * Depending on the screensize and the position of the parent, this may
+ * be a different place, however the default is to pop it up and the
+ * lower left corner of the parent.
+ *
+ * Make sure to hide() the box when appropriate.
+ */
+ virtual void popup();
+
+ /**
+ * Makes this widget (when visible) capture Tab-key events to traverse the
+ * items in the dropdown list.
+ *
+ * Default off, as it conflicts with the usual behavior of Tab to traverse
+ * widgets. It is useful for cases like Konqueror's Location Bar, though.
+ *
+ * @see isTabHandling
+ */
+ void setTabHandling( bool enable );
+
+ /**
+ * @returns true if this widget is handling Tab-key events to traverse the
+ * items in the dropdown list, otherwise false.
+ *
+ * Default is false.
+ *
+ * @see setTabHandling
+ */
+ bool isTabHandling() const;
+
+ /**
+ * Sets the text to be emitted if the user chooses not to
+ * pick from the available matches.
+ *
+ * If the canceled text is not set through this function, the
+ * userCancelled signal will not be emitted.
+ *
+ * @see userCancelled( const QString& )
+ * @param txt the text to be emitted if the user cancels this box
+ */
+ void setCancelledText( const QString& txt);
+
+ /**
+ * @returns the text set via setCancelledText() or QString::null.
+ */
+ QString cancelledText() const;
+
+ /**
+ * Set whether or not the selected signal should be emitted when an
+ * item is selected. By default the selected signal is emitted.
+ *
+ * @param state false if the signal should not be emitted.
+ * @since 3.4.1
+ */
+ void setActivateOnSelect(bool state);
+
+
+ /**
+ * Moves the selection one line down or select the first item if nothing is selected yet.
+ */
+ void down();
+
+ /**
+ * Moves the selection one line up or select the first item if nothing is selected yet.
+ */
+ void up();
+
+ /**
+ * Moves the selection one page down.
+ */
+ void pageDown();
+
+ /**
+ * Moves the selection one page up.
+ */
+ void pageUp();
+
+ /**
+ * Moves the selection up to the first item.
+ */
+ void home();
+
+ /**
+ * Moves the selection down to the last item.
+ */
+ void end();
+
+ /**
+ * Re-implemented for internal reasons. API is unaffected.
+ */
+ virtual void show();
+
+ /**
+ * Re-implemented for internal reasons. API is unaffected.
+ */
+ virtual void hide();
+
+signals:
+ /**
+ * Emitted when an item was selected, contains the text of
+ * the selected item.
+ */
+ void activated( const QString& );
+
+ /**
+ * Emitted whenever the user chooses to ignore the available
+ * selections and close the this box.
+ */
+ void userCancelled( const QString& );
+
+protected:
+ /**
+ * This calculates the size of the dropdown and the relative position of the top
+ * left corner with respect to the parent widget. This matches the geometry and position
+ * normally used by K/QComboBox when used with one.
+ */
+ QRect calculateGeometry() const;
+
+ /**
+ * This properly sizes and positions the listbox.
+ */
+ void sizeAndPosition();
+
+ /**
+ * Reimplemented from KListBox to get events from the viewport (to hide
+ * this widget on mouse-click, Escape-presses, etc.
+ */
+ virtual bool eventFilter( QObject *, QEvent * );
+
+protected slots:
+ /**
+ * Called when an item was activated. Emits
+ * activated() with the item.
+ */
+ virtual void slotActivated( QListBoxItem * );
+
+private slots:
+ void slotSetCurrentItem( QListBoxItem *i ) { setCurrentItem( i ); } // grrr
+ void slotCurrentChanged();
+ void canceled();
+ void slotItemClicked( QListBoxItem * );
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+
+private:
+ class KCompletionBoxPrivate;
+ KCompletionBoxPrivate* const d;
+};
+
+
+#endif // KCOMPLETIONBOX_H
diff --git a/kdeui/kconfigdialog.cpp b/kdeui/kconfigdialog.cpp
new file mode 100644
index 000000000..9410379d9
--- /dev/null
+++ b/kdeui/kconfigdialog.cpp
@@ -0,0 +1,259 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2003 Benjamin C Meyer (ben+kdelibs at meyerhome dot net)
+ * Copyright (C) 2003 Waldo Bastian <bastian@kde.org>
+ * Copyright (C) 2004 Michael Brade <brade@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#include "kconfigdialog.h"
+
+#include <kconfigskeleton.h>
+#include <kconfigdialogmanager.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+
+#include <qlayout.h>
+#include <qvbox.h>
+#include <qmap.h>
+
+QAsciiDict<KConfigDialog> KConfigDialog::openDialogs;
+
+// This class is here purly so we don't break binary compatibility down the road.
+class KConfigDialog::KConfigDialogPrivate
+{
+public:
+ KConfigDialogPrivate(KDialogBase::DialogType t)
+ : shown(false), type(t), manager(0) { }
+
+ bool shown;
+ KDialogBase::DialogType type;
+ KConfigDialogManager *manager;
+ QMap<QWidget *, KConfigDialogManager *> managerForPage;
+};
+
+KConfigDialog::KConfigDialog( QWidget *parent, const char *name,
+ KConfigSkeleton *config,
+ DialogType dialogType,
+ int dialogButtons,
+ ButtonCode defaultButton,
+ bool modal ) :
+ KDialogBase( dialogType, Qt::WStyle_DialogBorder,
+ parent, name, modal, i18n("Configure"), dialogButtons, defaultButton ),
+ d(new KConfigDialogPrivate(dialogType))
+{
+ if ( name ) {
+ openDialogs.insert(name, this);
+ } else {
+ QCString genericName;
+ genericName.sprintf("SettingsDialog-%p", this);
+ openDialogs.insert(genericName, this);
+ setName(genericName);
+ }
+
+ connect(this, SIGNAL(okClicked()), this, SLOT(updateSettings()));
+ connect(this, SIGNAL(applyClicked()), this, SLOT(updateSettings()));
+ connect(this, SIGNAL(applyClicked()), this, SLOT(updateButtons()));
+ connect(this, SIGNAL(defaultClicked()), this, SLOT(updateWidgetsDefault()));
+ connect(this, SIGNAL(defaultClicked()), this, SLOT(updateButtons()));
+
+ d->manager = new KConfigDialogManager(this, config);
+ setupManagerConnections(d->manager);
+
+ enableButton(Apply, false);
+}
+
+KConfigDialog::~KConfigDialog()
+{
+ openDialogs.remove(name());
+ delete d;
+}
+
+void KConfigDialog::addPage(QWidget *page,
+ const QString &itemName,
+ const QString &pixmapName,
+ const QString &header,
+ bool manage)
+{
+ addPageInternal(page, itemName, pixmapName, header);
+ if(manage)
+ d->manager->addWidget(page);
+}
+
+void KConfigDialog::addPage(QWidget *page,
+ KConfigSkeleton *config,
+ const QString &itemName,
+ const QString &pixmapName,
+ const QString &header)
+{
+ addPageInternal(page, itemName, pixmapName, header);
+ d->managerForPage[page] = new KConfigDialogManager(page, config);
+ setupManagerConnections(d->managerForPage[page]);
+}
+
+void KConfigDialog::addPageInternal(QWidget *page,
+ const QString &itemName,
+ const QString &pixmapName,
+ const QString &header)
+{
+ if(d->shown)
+ {
+ kdDebug(240) << "KConfigDialog::addPage: can not add a page after the dialog has been shown.";
+ return;
+ }
+ switch(d->type)
+ {
+ case TreeList:
+ case IconList:
+ case Tabbed: {
+ QVBox *frame = addVBoxPage(itemName, header, SmallIcon(pixmapName, 32));
+ frame->setSpacing( 0 );
+ frame->setMargin( 0 );
+ page->reparent(((QWidget*)frame), 0, QPoint());
+ }
+ break;
+
+ case Swallow:
+ {
+ page->reparent(this, 0, QPoint());
+ setMainWidget(page);
+ }
+ break;
+
+ case Plain:
+ {
+ QFrame *main = plainPage();
+ QVBoxLayout *topLayout = new QVBoxLayout( main, 0, 0 );
+ page->reparent(((QWidget*)main), 0, QPoint());
+ topLayout->addWidget( page );
+ }
+ break;
+
+ default:
+ kdDebug(240) << "KConfigDialog::addpage: unknown type.";
+ }
+}
+
+void KConfigDialog::setupManagerConnections(KConfigDialogManager *manager)
+{
+ connect(manager, SIGNAL(settingsChanged()), this, SLOT(settingsChangedSlot()));
+ connect(manager, SIGNAL(widgetModified()), this, SLOT(updateButtons()));
+
+ connect(this, SIGNAL(okClicked()), manager, SLOT(updateSettings()));
+ connect(this, SIGNAL(applyClicked()), manager, SLOT(updateSettings()));
+ connect(this, SIGNAL(defaultClicked()), manager, SLOT(updateWidgetsDefault()));
+}
+
+KConfigDialog* KConfigDialog::exists(const char* name)
+{
+ return openDialogs.find(name);
+}
+
+bool KConfigDialog::showDialog(const char* name)
+{
+ KConfigDialog *dialog = exists(name);
+ if(dialog)
+ dialog->show();
+ return (dialog != NULL);
+}
+
+void KConfigDialog::updateButtons()
+{
+ static bool only_once = false;
+ if (only_once) return;
+ only_once = true;
+
+ QMap<QWidget *, KConfigDialogManager *>::iterator it;
+
+ bool has_changed = d->manager->hasChanged() || hasChanged();
+ for (it = d->managerForPage.begin();
+ it != d->managerForPage.end() && !has_changed;
+ ++it)
+ {
+ has_changed |= (*it)->hasChanged();
+ }
+
+ enableButton(Apply, has_changed);
+
+ bool is_default = d->manager->isDefault() && isDefault();
+ for (it = d->managerForPage.begin();
+ it != d->managerForPage.end() && is_default;
+ ++it)
+ {
+ is_default &= (*it)->isDefault();
+ }
+
+ enableButton(Default, !is_default);
+
+ emit widgetModified();
+ only_once = false;
+}
+
+void KConfigDialog::settingsChangedSlot()
+{
+ // Update the buttons
+ updateButtons();
+ emit settingsChanged();
+ emit settingsChanged(name());
+}
+
+void KConfigDialog::show()
+{
+ QMap<QWidget *, KConfigDialogManager *>::iterator it;
+
+ updateWidgets();
+ d->manager->updateWidgets();
+ for (it = d->managerForPage.begin(); it != d->managerForPage.end(); ++it)
+ (*it)->updateWidgets();
+
+ bool has_changed = d->manager->hasChanged() || hasChanged();
+ for (it = d->managerForPage.begin();
+ it != d->managerForPage.end() && !has_changed;
+ ++it)
+ {
+ has_changed |= (*it)->hasChanged();
+ }
+
+ enableButton(Apply, has_changed);
+
+ bool is_default = d->manager->isDefault() && isDefault();
+ for (it = d->managerForPage.begin();
+ it != d->managerForPage.end() && is_default;
+ ++it)
+ {
+ is_default &= (*it)->isDefault();
+ }
+
+ enableButton(Default, !is_default);
+ d->shown = true;
+ KDialogBase::show();
+}
+
+void KConfigDialog::updateSettings()
+{
+}
+
+void KConfigDialog::updateWidgets()
+{
+}
+
+void KConfigDialog::updateWidgetsDefault()
+{
+}
+
+
+#include "kconfigdialog.moc"
diff --git a/kdeui/kconfigdialog.h b/kdeui/kconfigdialog.h
new file mode 100644
index 000000000..fa0409f29
--- /dev/null
+++ b/kdeui/kconfigdialog.h
@@ -0,0 +1,279 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2003 Benjamin C Meyer (ben+kdelibs at meyerhome dot net)
+ * Copyright (C) 2003 Waldo Bastian <bastian@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef KCONFIGDIALOG_H
+#define KCONFIGDIALOG_H
+
+class KConfig;
+class KConfigSkeleton;
+class KConfigDialogManager;
+#include <kdialogbase.h>
+#include <qasciidict.h>
+
+/**
+ * \short Standard %KDE configuration dialog class
+ *
+ * The KConfigDialog class provides an easy and uniform means of displaying
+ * a settings dialog using KDialogBase, KConfigDialogManager and a
+ * KConfigSkeleton derived settings class.
+ *
+ * KConfigDialog handles the enabling and disabling of buttons, creation
+ * of the dialog, and deletion of the widgets. Because of
+ * KConfigDialogManager, this class also manages: restoring
+ * the settings, reseting them to the default values, and saving them. This
+ * requires that the names of the widgets corresponding to configuration entries
+ * have to have the same name plus an additional "kcfg_" prefix. For example the
+ * widget named "kcfg_MyOption" would be associated with the configuration entry
+ * "MyOption".
+ *
+ * Here is an example usage of KConfigDialog:
+ *
+ * \code
+ * void KCoolApp::showSettings(){
+ * if(KConfigDialog::showDialog("settings"))
+ * return;
+ * KConfigDialog *dialog = new KConfigDialog(this, "settings", MySettings::self(), KDialogBase::IconList);
+ * dialog->addPage(new General(0, "General"), i18n("General") );
+ * dialog->addPage(new Appearance(0, "Style"), i18n("Appearance") );
+ * connect(dialog, SIGNAL(settingsChanged()), mainWidget, SLOT(loadSettings()));
+ * connect(dialog, SIGNAL(settingsChanged()), this, SLOT(loadSettings()));
+ * dialog->show();
+ * }
+ * \endcode
+ *
+ * Other than the above code, each class that has settings in the dialog should
+ * have a loadSettings() type slot to read settings and perform any
+ * necessary changes.
+ *
+ * Please note that using the setMainWidget method inherited from KDialogBase
+ * currently yields broken behaviour at runtime; use @ref addPage() instead.
+ *
+ * @see KConfigSkeleton
+ * @author Waldo Bastian <bastian@kde.org>
+ * @since 3.2
+ */
+class KDEUI_EXPORT KConfigDialog : public KDialogBase {
+Q_OBJECT
+
+signals:
+ /**
+ * A widget in the dialog was modified.
+ */
+ void widgetModified();
+
+ /**
+ * One or more of the settings have been permanently changed such as if
+ * the user clicked on the Apply or Ok button.
+ */
+ void settingsChanged();
+
+ /**
+ * One or more of the settings have been permanently changed such as if
+ * the user clicked on the Apply or Ok button.
+ * This signal is useful when using KConfigDialog to configure
+ * items in a list. When emitted the main class would then know what
+ * item in the list was actually changed.
+ * @param dialogName the name of the dialog.
+ */
+ void settingsChanged(const char *dialogName);
+
+public:
+ /**
+ * @param parent - The parent of this object. Even though the class
+ * deletes itself the parent should be set so the dialog can be centered
+ * with the application on the screen.
+ *
+ * @param name - The name of this object. The name is used in determining if
+ * there can be more than one dialog at a time. Use names such as:
+ * "Font Settings" or "Color Settings" and not just "Settings" in
+ * applications where there is more than one dialog.
+ *
+ * @param dialogType - Type used in creating the dialog. See KDialogBase
+ *
+ * @param config - Config object containing settings.
+ *
+ * @param dialogButtons - Buttons that should show up on the dialog.
+ *
+ * @param defaultButton default button that is choosen by hitting the enter key.
+ *
+ * @param modal - Whether the dialog should be modal. To prevent more than one
+ * non-modal settings dialog from showing the static function showDialog() can be
+ * used in determining if the settings dialog already exists before creating
+ * a new KConfigDialog object.
+ */
+ // KDE4: Add the "separator" parameter as in KDialogBase
+ // Make "dialogType" an int
+ KConfigDialog( QWidget *parent, const char *name,
+ KConfigSkeleton *config,
+ DialogType dialogType = IconList,
+ int dialogButtons = Default|Ok|Apply|Cancel|Help,
+ ButtonCode defaultButton = Ok,
+ bool modal=false );
+
+ /**
+ * Deconstructor, removes name from the list of open dialogs.
+ * Deletes private class.
+ * @see exists()
+ */
+ ~KConfigDialog();
+
+ /**
+ * Adds page to the dialog and to KConfigDialogManager. When an
+ * application is done adding pages show() should be called to
+ * display the dialog.
+ * Note that after you call show() you can not add any more pages
+ * to the dialog.
+ * @param page - Pointer to the page that is to be added to the dialog.
+ * This object is reparented.
+ * @param itemName - Name of the page.
+ * @param pixmapName - Name of the pixmap that should be used if needed.
+ * @param header - Header text use in the list modes. Ignored in Tabbed
+ * mode. If empty, the itemName text is used when needed.
+ * @param manage - Whether KConfigDialogManager should manage the page or not.
+ */
+ // KDE4: Add a default value for itemName & pixmapName
+ void addPage( QWidget *page, const QString &itemName,
+ const QString &pixmapName,
+ const QString &header=QString::null,
+ bool manage=true );
+
+ /**
+ * Adds page to the dialog that is managed by a custom KConfigDialogManager.
+ * This is useful for dialogs that contain settings spread over more than
+ * one configuration file and thus have/need more than one KConfigSkeleton.
+ * When an application is done adding pages show() should be called to
+ * display the dialog.
+ * Note that after you call show() you can not add any more pages
+ * to the dialog.
+ * @param page - Pointer to the page that is to be added to the dialog.
+ * This object is reparented.
+ * @param config - Config object containing corresponding settings.
+ * @param itemName - Name of the page.
+ * @param pixmapName - Name of the pixmap that should be used if needed.
+ * @param header - Header text use in the list modes. Ignored in Tabbed
+ * mode. If empty, the itemName text is used when needed.
+ */
+ // KDE4: Add a default value for itemName & pixmapName
+ void addPage( QWidget *page, KConfigSkeleton *config,
+ const QString &itemName,
+ const QString &pixmapName,
+ const QString &header=QString::null );
+
+ /**
+ * See if a dialog with the name 'name' already exists.
+ * @see showDialog()
+ * @param name - Dialog name to look for.
+ * @return Pointer to widget or NULL if it does not exist.
+ */
+ static KConfigDialog* exists( const char* name );
+
+ /**
+ * Attempts to show the dialog with the name 'name'.
+ * @see exists()
+ * @param name - The name of the dialog to show.
+ * @return True if the dialog 'name' exists and was shown.
+ */
+ static bool showDialog( const char* name );
+
+ /**
+ * Show the dialog.
+ */
+ virtual void show();
+
+protected slots:
+ /**
+ * Update the settings from the dialog.
+ * Virtual function for custom additions.
+ *
+ * Example use: User clicks Ok or Apply button in a configure dialog.
+ */
+ virtual void updateSettings();
+
+ /**
+ * Update the dialog based on the settings.
+ * Virtual function for custom additions.
+ *
+ * Example use: Initialisation of dialog.
+ * Example use: User clicks Reset button in a configure dialog.
+ */
+ virtual void updateWidgets();
+
+ /**
+ * Update the dialog based on the default settings.
+ * Virtual function for custom additions.
+ *
+ * Example use: User clicks Defaults button in a configure dialog.
+ */
+ virtual void updateWidgetsDefault();
+
+protected:
+
+ /**
+ * Returns whether the current state of the dialog is
+ * different from the current configutation.
+ * Virtual function for custom additions.
+ */
+ virtual bool hasChanged() { return false; }
+
+ /**
+ * Returns whether the current state of the dialog is
+ * the same as the default configuration.
+ */
+ virtual bool isDefault() { return true; }
+
+protected slots:
+ /**
+ * Updates the Apply and Default buttons.
+ */
+ void updateButtons();
+
+ /**
+ * Some setting was changed. Emit the signal with the dialogs name
+ */
+ void settingsChangedSlot();
+
+private:
+ /**
+ * Internal function with common addPage code.
+ */
+ void addPageInternal(QWidget *page, const QString &itemName,
+ const QString &pixmapName, const QString &header);
+
+ /**
+ * Sets the connections from a manager to the dialog (and the other
+ * way round) up.
+ */
+ void setupManagerConnections(KConfigDialogManager *manager);
+
+private:
+ /**
+ * The list of existing dialogs.
+ */
+ static QAsciiDict<KConfigDialog> openDialogs;
+
+ class KConfigDialogPrivate;
+ /**
+ * Private class.
+ */
+ KConfigDialogPrivate *d;
+};
+
+#endif //KCONFIGDIALOG_H
+
diff --git a/kdeui/kcursor.cpp b/kdeui/kcursor.cpp
new file mode 100644
index 000000000..74e37327d
--- /dev/null
+++ b/kdeui/kcursor.cpp
@@ -0,0 +1,434 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1998 Kurt Granroth (granroth@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifdef KDE_USE_FINAL
+#ifdef KeyRelease
+#undef KeyRelease
+#endif
+#endif
+
+#include <kcursor.h>
+
+#include <qbitmap.h>
+#include <qcursor.h>
+#include <qevent.h>
+#include <qtimer.h>
+#include <qwidget.h>
+
+#include <kglobal.h>
+#include <kconfig.h>
+#include <qscrollview.h>
+
+#include "kcursor_private.h"
+
+KCursor::KCursor()
+{
+}
+
+QCursor KCursor::handCursor()
+{
+ static QCursor *hand_cursor = 0;
+
+ if (!hand_cursor)
+ {
+ KConfig *config = KGlobal::config();
+ KConfigGroupSaver saver( config, "General" );
+
+#ifndef Q_WS_WIN // this mask doesn't work too well on win32
+ if ( config->readEntry("handCursorStyle", "Windows") == "Windows" )
+ {
+ static const unsigned char HAND_BITS[] = {
+ 0x80, 0x01, 0x00, 0x40, 0x02, 0x00, 0x40, 0x02, 0x00, 0x40, 0x02,
+ 0x00, 0x40, 0x02, 0x00, 0x40, 0x02, 0x00, 0x40, 0x1e, 0x00, 0x40,
+ 0xf2, 0x00, 0x40, 0x92, 0x01, 0x70, 0x92, 0x02, 0x50, 0x92, 0x04,
+ 0x48, 0x80, 0x04, 0x48, 0x00, 0x04, 0x48, 0x00, 0x04, 0x08, 0x00,
+ 0x04, 0x08, 0x00, 0x04, 0x10, 0x00, 0x04, 0x10, 0x00, 0x04, 0x20,
+ 0x00, 0x02, 0x40, 0x00, 0x02, 0x40, 0x00, 0x01, 0xc0, 0xff, 0x01};
+ static const unsigned char HAND_MASK_BITS[] = {
+ 0x80, 0x01, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03,
+ 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x1f, 0x00, 0xc0,
+ 0xff, 0x00, 0xc0, 0xff, 0x01, 0xf0, 0xff, 0x03, 0xf0, 0xff, 0x07,
+ 0xf8, 0xff, 0x07, 0xf8, 0xff, 0x07, 0xf8, 0xff, 0x07, 0xf8, 0xff,
+ 0x07, 0xf8, 0xff, 0x07, 0xf0, 0xff, 0x07, 0xf0, 0xff, 0x07, 0xe0,
+ 0xff, 0x03, 0xc0, 0xff, 0x03, 0xc0, 0xff, 0x01, 0xc0, 0xff, 0x01};
+ QBitmap hand_bitmap(22, 22, HAND_BITS, true);
+ QBitmap hand_mask(22, 22, HAND_MASK_BITS, true);
+ hand_cursor = new QCursor(hand_bitmap, hand_mask, 7, 0);
+ // Hack to force QCursor to call XCreatePixmapCursor() immediately
+ // so the bitmaps don't get pushed out of the Xcursor LRU cache.
+ hand_cursor->handle();
+ }
+ else
+#endif //! Q_WS_WIN
+ hand_cursor = new QCursor(PointingHandCursor);
+ }
+
+ Q_CHECK_PTR(hand_cursor);
+ return *hand_cursor;
+}
+
+/* XPM */
+static const char * const working_cursor_xpm[]={
+"32 32 3 1",
+"# c None",
+"a c #000000",
+". c #ffffff",
+"..##############################",
+".a.##########.aaaa.#############",
+".aa.#########.aaaa.#############",
+".aaa.#######.aaaaaa.############",
+".aaaa.#####.a...a..a..##########",
+".aaaaa.####a....a...aa##########",
+".aaaaaa.###a...aa...aa##########",
+".aaaaaaa.##a..a.....aa##########",
+".aaaaaaaa.#.aa.....a..##########",
+".aaaaa....##.aaaaaa.############",
+".aa.aa.######.aaaa.#############",
+".a.#.aa.#####.aaaa.#############",
+"..##.aa.########################",
+"#####.aa.#######################",
+"#####.aa.#######################",
+"######..########################",
+"################################",
+"################################",
+"################################",
+"################################",
+"################################",
+"################################",
+"################################",
+"################################",
+"################################",
+"################################",
+"################################",
+"################################",
+"################################",
+"################################",
+"################################",
+"################################"};
+
+
+QCursor KCursor::workingCursor()
+{
+ static QCursor *working_cursor = 0;
+
+ if (!working_cursor)
+ {
+ QPixmap pm( const_cast< const char** >( working_cursor_xpm ));
+ working_cursor = new QCursor( pm, 1, 1 );
+ // Hack to force QCursor to call XCreatePixmapCursor() immediately
+ // so the bitmaps don't get pushed out of the Xcursor LRU cache.
+ working_cursor->handle();
+ }
+
+ Q_CHECK_PTR(working_cursor);
+ return *working_cursor;
+}
+
+/**
+ * All of the follow functions will return the Qt default for now regardless
+ * of the style. This will change at some later date
+ */
+QCursor KCursor::arrowCursor()
+{
+ return Qt::arrowCursor;
+}
+
+
+QCursor KCursor::upArrowCursor()
+{
+ return Qt::upArrowCursor;
+}
+
+
+QCursor KCursor::crossCursor()
+{
+ return Qt::crossCursor;
+}
+
+
+QCursor KCursor::waitCursor()
+{
+ return Qt::waitCursor;
+}
+
+
+QCursor KCursor::ibeamCursor()
+{
+ return Qt::ibeamCursor;
+}
+
+
+QCursor KCursor::sizeVerCursor()
+{
+ return Qt::sizeVerCursor;
+}
+
+
+QCursor KCursor::sizeHorCursor()
+{
+ return Qt::sizeHorCursor;
+}
+
+
+QCursor KCursor::sizeBDiagCursor()
+{
+ return Qt::sizeBDiagCursor;
+}
+
+
+QCursor KCursor::sizeFDiagCursor()
+{
+ return Qt::sizeFDiagCursor;
+}
+
+
+QCursor KCursor::sizeAllCursor()
+{
+ return Qt::sizeAllCursor;
+}
+
+
+QCursor KCursor::blankCursor()
+{
+ return Qt::blankCursor;
+}
+
+QCursor KCursor::whatsThisCursor()
+{
+ return Qt::whatsThisCursor;
+}
+
+// auto-hide cursor stuff
+
+void KCursor::setAutoHideCursor( QWidget *w, bool enable )
+{
+ setAutoHideCursor( w, enable, false );
+}
+
+void KCursor::setAutoHideCursor( QWidget *w, bool enable,
+ bool customEventFilter )
+{
+ KCursorPrivate::self()->setAutoHideCursor( w, enable, customEventFilter );
+}
+
+void KCursor::autoHideEventFilter( QObject *o, QEvent *e )
+{
+ KCursorPrivate::self()->eventFilter( o, e );
+}
+
+void KCursor::setHideCursorDelay( int ms )
+{
+ KCursorPrivate::self()->hideCursorDelay = ms;
+}
+
+int KCursor::hideCursorDelay()
+{
+ return KCursorPrivate::self()->hideCursorDelay;
+}
+
+// **************************************************************************
+
+KCursorPrivateAutoHideEventFilter::KCursorPrivateAutoHideEventFilter( QWidget* widget )
+ : m_widget( widget )
+ , m_wasMouseTracking( m_widget->hasMouseTracking() )
+ , m_isCursorHidden( false )
+ , m_isOwnCursor( false )
+{
+ m_widget->setMouseTracking( true );
+ connect( &m_autoHideTimer, SIGNAL( timeout() ),
+ this, SLOT( hideCursor() ) );
+}
+
+KCursorPrivateAutoHideEventFilter::~KCursorPrivateAutoHideEventFilter()
+{
+ if( m_widget != NULL )
+ m_widget->setMouseTracking( m_wasMouseTracking );
+}
+
+void KCursorPrivateAutoHideEventFilter::resetWidget()
+{
+ m_widget = NULL;
+}
+
+void KCursorPrivateAutoHideEventFilter::hideCursor()
+{
+ m_autoHideTimer.stop();
+
+ if ( m_isCursorHidden )
+ return;
+
+ m_isCursorHidden = true;
+
+ QWidget* w = actualWidget();
+
+ m_isOwnCursor = w->ownCursor();
+ if ( m_isOwnCursor )
+ m_oldCursor = w->cursor();
+
+ w->setCursor( KCursor::blankCursor() );
+}
+
+void KCursorPrivateAutoHideEventFilter::unhideCursor()
+{
+ m_autoHideTimer.stop();
+
+ if ( !m_isCursorHidden )
+ return;
+
+ m_isCursorHidden = false;
+
+ QWidget* w = actualWidget();
+
+ if ( w->cursor().shape() != Qt::BlankCursor ) // someone messed with the cursor already
+ return;
+
+ if ( m_isOwnCursor )
+ w->setCursor( m_oldCursor );
+ else
+ w->unsetCursor();
+}
+
+QWidget* KCursorPrivateAutoHideEventFilter::actualWidget() const
+{
+ QWidget* w = m_widget;
+
+ // Is w a scrollview ? Call setCursor on the viewport in that case.
+ QScrollView * sv = dynamic_cast<QScrollView *>( w );
+ if ( sv )
+ w = sv->viewport();
+
+ return w;
+}
+
+bool KCursorPrivateAutoHideEventFilter::eventFilter( QObject *o, QEvent *e )
+{
+ Q_ASSERT( o == m_widget );
+
+ switch ( e->type() )
+ {
+ case QEvent::Create:
+ // Qt steals mouseTracking on create()
+ m_widget->setMouseTracking( true );
+ break;
+ case QEvent::Leave:
+ case QEvent::FocusOut:
+ case QEvent::WindowDeactivate:
+ unhideCursor();
+ break;
+ case QEvent::KeyPress:
+ case QEvent::AccelOverride:
+ hideCursor();
+ break;
+ case QEvent::Enter:
+ case QEvent::FocusIn:
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseMove:
+ case QEvent::Show:
+ case QEvent::Hide:
+ case QEvent::Wheel:
+ unhideCursor();
+ if ( m_widget->hasFocus() )
+ m_autoHideTimer.start( KCursorPrivate::self()->hideCursorDelay, true );
+ break;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+KCursorPrivate * KCursorPrivate::s_self = 0L;
+
+KCursorPrivate * KCursorPrivate::self()
+{
+ if ( !s_self )
+ s_self = new KCursorPrivate;
+ // WABA: We never delete KCursorPrivate. Don't change.
+
+ return s_self;
+}
+
+KCursorPrivate::KCursorPrivate()
+{
+ hideCursorDelay = 5000; // 5s default value
+
+ KConfig *kc = KGlobal::config();
+ KConfigGroupSaver ks( kc, QString::fromLatin1("KDE") );
+ enabled = kc->readBoolEntry(
+ QString::fromLatin1("Autohiding cursor enabled"), true );
+}
+
+KCursorPrivate::~KCursorPrivate()
+{
+}
+
+void KCursorPrivate::setAutoHideCursor( QWidget *w, bool enable, bool customEventFilter )
+{
+ if ( !w || !enabled )
+ return;
+
+ if ( enable )
+ {
+ if ( m_eventFilters.find( w ) != NULL )
+ return;
+ KCursorPrivateAutoHideEventFilter* filter = new KCursorPrivateAutoHideEventFilter( w );
+ m_eventFilters.insert( w, filter );
+ if ( !customEventFilter )
+ w->installEventFilter( filter );
+ connect( w, SIGNAL( destroyed(QObject*) ),
+ this, SLOT( slotWidgetDestroyed(QObject*) ) );
+ }
+ else
+ {
+ KCursorPrivateAutoHideEventFilter* filter = m_eventFilters.take( w );
+ if ( filter == NULL )
+ return;
+ w->removeEventFilter( filter );
+ delete filter;
+ disconnect( w, SIGNAL( destroyed(QObject*) ),
+ this, SLOT( slotWidgetDestroyed(QObject*) ) );
+ }
+}
+
+bool KCursorPrivate::eventFilter( QObject *o, QEvent *e )
+{
+ if ( !enabled )
+ return false;
+
+ KCursorPrivateAutoHideEventFilter* filter = m_eventFilters.find( o );
+
+ Q_ASSERT( filter != NULL );
+ if ( filter == NULL )
+ return false;
+
+ return filter->eventFilter( o, e );
+}
+
+void KCursorPrivate::slotWidgetDestroyed( QObject* o )
+{
+ KCursorPrivateAutoHideEventFilter* filter = m_eventFilters.take( o );
+
+ Q_ASSERT( filter != NULL );
+
+ filter->resetWidget(); // so that dtor doesn't access it
+ delete filter;
+}
+
+#include "kcursor_private.moc"
diff --git a/kdeui/kcursor.h b/kdeui/kcursor.h
new file mode 100644
index 000000000..1c96c49b6
--- /dev/null
+++ b/kdeui/kcursor.h
@@ -0,0 +1,224 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1998 Kurt Granroth (granroth@kde.org)
+ 2000 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+/*
+ * $Id$
+ *
+ */
+#ifndef _KCURSOR_H
+#define _KCURSOR_H
+
+#include <qcursor.h>
+#include <kdelibs_export.h>
+
+class QWidget;
+
+/**
+ * @short A QCursor wrapper allowing "themed" cursors and auto-hiding cursors.
+ *
+ * A wrapper around QCursor that allows for "themed" cursors.
+ *
+ * Currently, the only themed cursor is a hand shaped cursor.
+ *
+ * A typical usage would be
+ * \code
+ * setCursor(KCursor::handCursor());
+ * \endcode
+ *
+ * @author Kurt Granroth <granroth@kde.org>
+ */
+class KDEUI_EXPORT KCursor : public Qt
+{
+public:
+ /**
+ * Constructor.
+ *
+ * Does not do anything so far.
+ **/
+ KCursor();
+
+ /**
+ * Returns the proper hand cursor according to
+ * the current GUI style (static function).
+ */
+ static QCursor handCursor();
+
+ /**
+ * Returns the proper arrow+hourglass cursor according to
+ * the current GUI style (static function).
+ */
+ static QCursor workingCursor();
+
+ /**
+ * Returns the proper arrow cursor according to
+ * the current GUI style (static function).
+ */
+ static QCursor arrowCursor();
+
+ /**
+ * Returns the proper up arrow cursor according to
+ * the current GUI style (static function).
+ */
+ static QCursor upArrowCursor();
+
+ /**
+ * Returns the proper cross-hair cursor according to
+ * the current GUI style (static function).
+ */
+ static QCursor crossCursor();
+
+ /**
+ * Returns the proper hourglass cursor according to
+ * the current GUI style (static function).
+ */
+ static QCursor waitCursor();
+
+ /**
+ * Returns the proper text cursor according to
+ * the current GUI style (static function).
+ */
+ static QCursor ibeamCursor();
+
+ /**
+ * Returns the proper vertical resize cursor
+ * according to the current GUI style (static function).
+ */
+ static QCursor sizeVerCursor();
+
+ /**
+ * Returns the proper horizontal resize cursor
+ * according to the current GUI style (static function).
+ */
+ static QCursor sizeHorCursor();
+
+ /**
+ * Returns the proper diagonal resize (/) cursor
+ * according to the current GUI style (static function).
+ */
+ static QCursor sizeBDiagCursor();
+
+ /**
+ * Returns the proper diagonal resize (\) cursor
+ * according to the current GUI style (static function).
+ */
+ static QCursor sizeFDiagCursor();
+
+ /**
+ * Returns the proper all-directions resize cursor
+ * according to the current GUI style (static function).
+ */
+ static QCursor sizeAllCursor();
+
+ /**
+ * Returns a blank or invisible cursor (static function).
+ */
+ static QCursor blankCursor();
+
+ /**
+ * Returns a WhatsThis cursor (static function).
+ */
+ static QCursor whatsThisCursor();
+
+ /**
+ * Sets auto-hiding the cursor for widget @p w. Enabling it will result in
+ * the cursor being hidden when
+ * @li a key-event happens
+ * @li there are no key-events for a configured time-frame (see
+ * setHideCursorDelay())
+ *
+ * The cursor will be shown again when the focus is lost or a mouse-event
+ * happens.
+ *
+ * Side effect: when enabling auto-hide, mouseTracking is enabled for the
+ * specified widget, because it's needed to get mouse-move-events. So
+ * don't disable mouseTracking for a widget while using auto-hide for it.
+ *
+ * When disabling auto-hide, mouseTracking will be disabled, so if you need
+ * mouseTracking after disabling auto-hide, you have to reenable
+ * mouseTracking.
+ *
+ * If you want to use auto-hiding for widgets that don't take focus, e.g.
+ * a QCanvasView, then you have to pass all key-events that should trigger
+ * auto-hiding to autoHideEventFilter().
+ */
+ static void setAutoHideCursor( QWidget *w, bool enable );
+
+ /**
+ * Overloaded method for the case where you have an event-filter installed
+ * on the widget you want to enable auto-cursor-hiding.
+ *
+ * In this case set @p customEventFilter to true and call
+ * autoHideEventFilter() from the beginning of your eventFilter().
+ *
+ * @see autoHideEventFilter
+ */
+ static void setAutoHideCursor( QWidget *w, bool enable,
+ bool customEventFilter );
+
+ /**
+ * Sets the delay time in milliseconds for auto-hiding. When no keyboard
+ * events arrive for that time-frame, the cursor will be hidden.
+ *
+ * Default is 5000, i.e. 5 seconds.
+ */
+ static void setHideCursorDelay( int ms );
+
+ /**
+ * @returns the current auto-hide delay time.
+ *
+ * Default is 5000, i.e. 5 seconds.
+ */
+ static int hideCursorDelay();
+
+ /**
+ * KCursor has to install an eventFilter over the widget you want to
+ * auto-hide. If you have an own eventFilter() on that widget and stop
+ * some events by returning true, you might break auto-hiding, because
+ * KCursor doesn't get those events.
+ *
+ * In this case, you need to call setAutoHideCursor( widget, true, true );
+ * to tell KCursor not to install an eventFilter. Then you call this method
+ * from the beginning of your eventFilter, for example:
+ * \code
+ * edit = new KEdit( this, "some edit widget" );
+ * edit->installEventFilter( this );
+ * KCursor::setAutoHideCursor( edit, true, true );
+ *
+ * [...]
+ *
+ * bool YourClass::eventFilter( QObject *o, QEvent *e )
+ * {
+ * if ( o == edit ) // only that widget where you enabled auto-hide!
+ * KCursor::autoHideEventFilter( o, e );
+ *
+ * // now you can do your own event-processing
+ * [...]
+ * }
+ * \endcode
+ *
+ * Note that you must not call KCursor::autoHideEventFilter() when you
+ * didn't enable or after disabling auto-hiding.
+ */
+ static void autoHideEventFilter( QObject *, QEvent * );
+
+private:
+ static QCursor *s_handCursor;
+};
+
+
+#endif // _KCURSOR_H
diff --git a/kdeui/kcursor_private.h b/kdeui/kcursor_private.h
new file mode 100644
index 000000000..0a85d0ec5
--- /dev/null
+++ b/kdeui/kcursor_private.h
@@ -0,0 +1,99 @@
+/* This file is part of the KDE libraries
+
+ Copyright (c) 2000 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License (LGPL) as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KCURSOR_PRIVATE_H
+#define KCURSOR_PRIVATE_H
+
+#include <qcursor.h>
+#include <qobject.h>
+#include <qptrdict.h>
+
+class QPoint;
+class QTimer;
+class QWidget;
+
+/**
+ * I don't want the eventFilter to be in KCursor, so we have another class
+ * for that stuff
+ * @internal
+ * @author John Firebaugh <jfirebaugh@kde.org>
+ * @author Carsten Pfeiffer <pfeiffer@kde.org>
+*/
+class KCursorPrivateAutoHideEventFilter : public QObject
+{
+ Q_OBJECT
+
+public:
+ KCursorPrivateAutoHideEventFilter( QWidget* widget );
+ ~KCursorPrivateAutoHideEventFilter();
+
+ virtual bool eventFilter( QObject *o, QEvent *e );
+
+ void resetWidget();
+
+private slots:
+ void hideCursor();
+ void unhideCursor();
+
+private:
+ QWidget* actualWidget() const;
+
+ QTimer m_autoHideTimer;
+ QWidget* m_widget;
+ bool m_wasMouseTracking;
+ bool m_isCursorHidden;
+ bool m_isOwnCursor;
+ QCursor m_oldCursor;
+};
+
+/**
+ * @internal
+ * @author Carsten Pfeiffer <pfeiffer@kde.org>
+ * @author John Firebaugh <jfirebaugh@kde.org>
+*/
+class KCursorPrivate : public QObject
+{
+ friend class KCursor; // to shut up the compiler
+ Q_OBJECT
+
+public:
+ static KCursorPrivate *self();
+
+ void setAutoHideCursor( QWidget *w, bool enable, bool customEventFilter );
+ virtual bool eventFilter( QObject *o, QEvent *e );
+
+ int hideCursorDelay;
+
+private slots:
+ void slotWidgetDestroyed( QObject* );
+
+private:
+ KCursorPrivate();
+ ~KCursorPrivate();
+
+ bool enabled;
+ static KCursorPrivate *s_self;
+
+ QPtrDict<KCursorPrivateAutoHideEventFilter> m_eventFilters;
+};
+
+
+
+#endif // KCURSOR_PRIVATE_H
diff --git a/kdeui/kdatepicker.cpp b/kdeui/kdatepicker.cpp
new file mode 100644
index 000000000..ae9f97cb7
--- /dev/null
+++ b/kdeui/kdatepicker.cpp
@@ -0,0 +1,549 @@
+/* -*- C++ -*-
+ This file is part of the KDE libraries
+ Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org)
+ (C) 1998-2001 Mirko Boehm (mirko@kde.org)
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qlayout.h>
+#include <qframe.h>
+#include <qpainter.h>
+#include <qdialog.h>
+#include <qstyle.h>
+#include <qtoolbutton.h>
+#include <qcombobox.h>
+#include <qtooltip.h>
+#include <qfont.h>
+#include <qvalidator.h>
+#include <qpopupmenu.h>
+#include <qtimer.h>
+
+#include "kdatepicker.h"
+#include <kglobal.h>
+#include <kapplication.h>
+#include <kdialog.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <ktoolbar.h>
+#include <klineedit.h>
+#include <kdebug.h>
+#include <knotifyclient.h>
+#include <kcalendarsystem.h>
+
+#include "kdatetbl.h"
+#include "kdatepicker.moc"
+
+// Week numbers are defined by ISO 8601
+// See http://www.merlyn.demon.co.uk/weekinfo.htm for details
+
+class KDatePicker::KDatePickerPrivate
+{
+public:
+ KDatePickerPrivate() : closeButton(0L), selectWeek(0L), todayButton(0), navigationLayout(0) {}
+
+ void fillWeeksCombo(const QDate &date);
+
+ QToolButton *closeButton;
+ QComboBox *selectWeek;
+ QToolButton *todayButton;
+ QBoxLayout *navigationLayout;
+};
+
+void KDatePicker::fillWeeksCombo(const QDate &date)
+{
+ // every year can have a different number of weeks
+ const KCalendarSystem * calendar = KGlobal::locale()->calendar();
+
+ // it could be that we had 53,1..52 and now 1..53 which is the same number but different
+ // so always fill with new values
+
+ d->selectWeek->clear();
+
+ // We show all week numbers for all weeks between first day of year to last day of year
+ // This of course can be a list like 53,1,2..52
+
+ QDate day;
+ int year = calendar->year(date);
+ calendar->setYMD(day, year, 1, 1);
+ int lastMonth = calendar->monthsInYear(day);
+ QDate lastDay, firstDayOfLastMonth;
+ calendar->setYMD(firstDayOfLastMonth, year, lastMonth, 1);
+ calendar->setYMD(lastDay, year, lastMonth, calendar->daysInMonth(firstDayOfLastMonth));
+
+ for (; day <= lastDay ; day = calendar->addDays(day, 7 /*calendar->daysOfWeek()*/) )
+ {
+ QString week = i18n("Week %1").arg(calendar->weekNumber(day, &year));
+ if ( year != calendar->year(day) ) week += "*"; // show that this is a week from a different year
+ d->selectWeek->insertItem(week);
+
+ // make sure that the week of the lastDay is always inserted: in Chinese calendar
+ // system, this is not always the case
+ if(day < lastDay && day.daysTo(lastDay) < 7 && calendar->weekNumber(day) != calendar->weekNumber(lastDay))
+ day = lastDay.addDays(-7);
+ }
+}
+
+KDatePicker::KDatePicker(QWidget *parent, QDate dt, const char *name)
+ : QFrame(parent,name)
+{
+ init( dt );
+}
+
+KDatePicker::KDatePicker(QWidget *parent, QDate dt, const char *name, WFlags f)
+ : QFrame(parent,name, f)
+{
+ init( dt );
+}
+
+KDatePicker::KDatePicker( QWidget *parent, const char *name )
+ : QFrame(parent,name)
+{
+ init( QDate::currentDate() );
+}
+
+void KDatePicker::init( const QDate &dt )
+{
+ d = new KDatePickerPrivate();
+
+ QBoxLayout * topLayout = new QVBoxLayout(this);
+
+ d->navigationLayout = new QHBoxLayout(topLayout);
+ d->navigationLayout->addStretch();
+ yearBackward = new QToolButton(this);
+ yearBackward->setAutoRaise(true);
+ d->navigationLayout->addWidget(yearBackward);
+ monthBackward = new QToolButton(this);
+ monthBackward ->setAutoRaise(true);
+ d->navigationLayout->addWidget(monthBackward);
+ d->navigationLayout->addSpacing(KDialog::spacingHint());
+
+ selectMonth = new QToolButton(this);
+ selectMonth ->setAutoRaise(true);
+ d->navigationLayout->addWidget(selectMonth);
+ selectYear = new QToolButton(this);
+ selectYear->setToggleButton(true);
+ selectYear->setAutoRaise(true);
+ d->navigationLayout->addWidget(selectYear);
+ d->navigationLayout->addSpacing(KDialog::spacingHint());
+
+ monthForward = new QToolButton(this);
+ monthForward ->setAutoRaise(true);
+ d->navigationLayout->addWidget(monthForward);
+ yearForward = new QToolButton(this);
+ yearForward ->setAutoRaise(true);
+ d->navigationLayout->addWidget(yearForward);
+ d->navigationLayout->addStretch();
+
+ line = new KLineEdit(this);
+ val = new KDateValidator(this);
+ table = new KDateTable(this);
+ fontsize = KGlobalSettings::generalFont().pointSize();
+ if (fontsize == -1)
+ fontsize = QFontInfo(KGlobalSettings::generalFont()).pointSize();
+
+ fontsize++; // Make a little bigger
+
+ d->selectWeek = new QComboBox(false, this); // read only week selection
+ d->todayButton = new QToolButton(this);
+ d->todayButton->setIconSet(SmallIconSet("today"));
+
+ QToolTip::add(yearForward, i18n("Next year"));
+ QToolTip::add(yearBackward, i18n("Previous year"));
+ QToolTip::add(monthForward, i18n("Next month"));
+ QToolTip::add(monthBackward, i18n("Previous month"));
+ QToolTip::add(d->selectWeek, i18n("Select a week"));
+ QToolTip::add(selectMonth, i18n("Select a month"));
+ QToolTip::add(selectYear, i18n("Select a year"));
+ QToolTip::add(d->todayButton, i18n("Select the current day"));
+
+ // -----
+ setFontSize(fontsize);
+ line->setValidator(val);
+ line->installEventFilter( this );
+ if ( QApplication::reverseLayout() )
+ {
+ yearForward->setIconSet(BarIconSet(QString::fromLatin1("2leftarrow")));
+ yearBackward->setIconSet(BarIconSet(QString::fromLatin1("2rightarrow")));
+ monthForward->setIconSet(BarIconSet(QString::fromLatin1("1leftarrow")));
+ monthBackward->setIconSet(BarIconSet(QString::fromLatin1("1rightarrow")));
+ }
+ else
+ {
+ yearForward->setIconSet(BarIconSet(QString::fromLatin1("2rightarrow")));
+ yearBackward->setIconSet(BarIconSet(QString::fromLatin1("2leftarrow")));
+ monthForward->setIconSet(BarIconSet(QString::fromLatin1("1rightarrow")));
+ monthBackward->setIconSet(BarIconSet(QString::fromLatin1("1leftarrow")));
+ }
+ connect(table, SIGNAL(dateChanged(QDate)), SLOT(dateChangedSlot(QDate)));
+ connect(table, SIGNAL(tableClicked()), SLOT(tableClickedSlot()));
+ connect(monthForward, SIGNAL(clicked()), SLOT(monthForwardClicked()));
+ connect(monthBackward, SIGNAL(clicked()), SLOT(monthBackwardClicked()));
+ connect(yearForward, SIGNAL(clicked()), SLOT(yearForwardClicked()));
+ connect(yearBackward, SIGNAL(clicked()), SLOT(yearBackwardClicked()));
+ connect(d->selectWeek, SIGNAL(activated(int)), SLOT(weekSelected(int)));
+ connect(d->todayButton, SIGNAL(clicked()), SLOT(todayButtonClicked()));
+ connect(selectMonth, SIGNAL(clicked()), SLOT(selectMonthClicked()));
+ connect(selectYear, SIGNAL(toggled(bool)), SLOT(selectYearClicked()));
+ connect(line, SIGNAL(returnPressed()), SLOT(lineEnterPressed()));
+ table->setFocus();
+
+
+ topLayout->addWidget(table);
+
+ QBoxLayout * bottomLayout = new QHBoxLayout(topLayout);
+ bottomLayout->addWidget(d->todayButton);
+ bottomLayout->addWidget(line);
+ bottomLayout->addWidget(d->selectWeek);
+
+ table->setDate(dt);
+ dateChangedSlot(dt); // needed because table emits changed only when newDate != oldDate
+}
+
+KDatePicker::~KDatePicker()
+{
+ delete d;
+}
+
+bool
+KDatePicker::eventFilter(QObject *o, QEvent *e )
+{
+ if ( e->type() == QEvent::KeyPress ) {
+ QKeyEvent *k = (QKeyEvent *)e;
+
+ if ( (k->key() == Qt::Key_Prior) ||
+ (k->key() == Qt::Key_Next) ||
+ (k->key() == Qt::Key_Up) ||
+ (k->key() == Qt::Key_Down) )
+ {
+ QApplication::sendEvent( table, e );
+ table->setFocus();
+ return true; // eat event
+ }
+ }
+ return QFrame::eventFilter( o, e );
+}
+
+void
+KDatePicker::resizeEvent(QResizeEvent* e)
+{
+ QWidget::resizeEvent(e);
+}
+
+void
+KDatePicker::dateChangedSlot(QDate date)
+{
+ kdDebug(298) << "KDatePicker::dateChangedSlot: date changed (" << date.year() << "/" << date.month() << "/" << date.day() << ")." << endl;
+
+ const KCalendarSystem * calendar = KGlobal::locale()->calendar();
+
+ line->setText(KGlobal::locale()->formatDate(date, true));
+ selectMonth->setText(calendar->monthName(date, false));
+ fillWeeksCombo(date);
+
+ // calculate the item num in the week combo box; normalize selected day so as if 1.1. is the first day of the week
+ QDate firstDay;
+ calendar->setYMD(firstDay, calendar->year(date), 1, 1);
+ d->selectWeek->setCurrentItem((calendar->dayOfYear(date) + calendar->dayOfWeek(firstDay) - 2) / 7/*calendar->daysInWeek()*/);
+ selectYear->setText(calendar->yearString(date, false));
+
+ emit(dateChanged(date));
+}
+
+void
+KDatePicker::tableClickedSlot()
+{
+ kdDebug(298) << "KDatePicker::tableClickedSlot: table clicked." << endl;
+ emit(dateSelected(table->getDate()));
+ emit(tableClicked());
+}
+
+const QDate&
+KDatePicker::getDate() const
+{
+ return table->getDate();
+}
+
+const QDate &
+KDatePicker::date() const
+{
+ return table->getDate();
+}
+
+bool
+KDatePicker::setDate(const QDate& date)
+{
+ if(date.isValid())
+ {
+ table->setDate(date); // this also emits dateChanged() which then calls our dateChangedSlot()
+ return true;
+ }
+ else
+ {
+ kdDebug(298) << "KDatePicker::setDate: refusing to set invalid date." << endl;
+ return false;
+ }
+}
+
+void
+KDatePicker::monthForwardClicked()
+{
+ QDate temp;
+ temp = KGlobal::locale()->calendar()->addMonths( table->getDate(), 1 );
+
+ setDate( temp );
+}
+
+void
+KDatePicker::monthBackwardClicked()
+{
+ QDate temp;
+ temp = KGlobal::locale()->calendar()->addMonths( table->getDate(), -1 );
+
+ setDate( temp );
+}
+
+void
+KDatePicker::yearForwardClicked()
+{
+ QDate temp;
+ temp = KGlobal::locale()->calendar()->addYears( table->getDate(), 1 );
+
+ setDate( temp );
+}
+
+void
+KDatePicker::yearBackwardClicked()
+{
+ QDate temp;
+ temp = KGlobal::locale()->calendar()->addYears( table->getDate(), -1 );
+
+ setDate( temp );
+}
+
+void KDatePicker::selectWeekClicked() {} // ### in 3.2 obsolete; kept for binary compatibility
+
+void
+KDatePicker::weekSelected(int week)
+{
+ const KCalendarSystem * calendar = KGlobal::locale()->calendar();
+
+ QDate date = table->getDate();
+ int year = calendar->year(date);
+
+ calendar->setYMD(date, year, 1, 1); // first day of selected year
+
+ // calculate the first day in the selected week (day 1 is first day of week)
+ date = calendar->addDays(date, week * 7/*calendar->daysOfWeek()*/ -calendar->dayOfWeek(date) + 1);
+
+ setDate(date);
+}
+
+void
+KDatePicker::selectMonthClicked()
+{
+ // every year can have different month names (in some calendar systems)
+ const KCalendarSystem * calendar = KGlobal::locale()->calendar();
+ QDate date = table->getDate();
+ int i, month, months = calendar->monthsInYear(date);
+
+ QPopupMenu popup(selectMonth);
+
+ for (i = 1; i <= months; i++)
+ popup.insertItem(calendar->monthName(i, calendar->year(date)), i);
+
+ popup.setActiveItem(calendar->month(date) - 1);
+
+ if ( (month = popup.exec(selectMonth->mapToGlobal(QPoint(0, 0)), calendar->month(date) - 1)) == -1 ) return; // canceled
+
+ int day = calendar->day(date);
+ // ----- construct a valid date in this month:
+ calendar->setYMD(date, calendar->year(date), month, 1);
+ date = date.addDays(QMIN(day, calendar->daysInMonth(date)) - 1);
+ // ----- set this month
+ setDate(date);
+}
+
+void
+KDatePicker::selectYearClicked()
+{
+ const KCalendarSystem * calendar = KGlobal::locale()->calendar();
+
+ if (selectYear->state() == QButton::Off)
+ {
+ return;
+ }
+
+ int year;
+ KPopupFrame* popup = new KPopupFrame(this);
+ KDateInternalYearSelector* picker = new KDateInternalYearSelector(popup);
+ // -----
+ picker->resize(picker->sizeHint());
+ picker->setYear( table->getDate().year() );
+ picker->selectAll();
+ popup->setMainWidget(picker);
+ connect(picker, SIGNAL(closeMe(int)), popup, SLOT(close(int)));
+ picker->setFocus();
+ if(popup->exec(selectYear->mapToGlobal(QPoint(0, selectMonth->height()))))
+ {
+ QDate date;
+ int day;
+ // -----
+ year=picker->getYear();
+ date=table->getDate();
+ day=calendar->day(date);
+ // ----- construct a valid date in this month:
+ //date.setYMD(year, date.month(), 1);
+ //date.setYMD(year, date.month(), QMIN(day, date.daysInMonth()));
+ calendar->setYMD(date, year, calendar->month(date),
+ QMIN(day, calendar->daysInMonth(date)));
+ // ----- set this month
+ setDate(date);
+ } else {
+ KNotifyClient::beep();
+ }
+
+ delete popup;
+ QTimer::singleShot(0, this, SLOT(ensureSelectYearIsUp()));
+}
+
+void
+KDatePicker::ensureSelectYearIsUp()
+{
+ if (!selectYear->isDown())
+ {
+ selectYear->setOn( false );
+ }
+}
+
+void
+KDatePicker::setEnabled(bool enable)
+{
+ QWidget *widgets[]= {
+ yearForward, yearBackward, monthForward, monthBackward,
+ selectMonth, selectYear,
+ line, table, d->selectWeek, d->todayButton };
+ const int Size=sizeof(widgets)/sizeof(widgets[0]);
+ int count;
+ // -----
+ for(count=0; count<Size; ++count)
+ {
+ widgets[count]->setEnabled(enable);
+ }
+}
+
+void
+KDatePicker::lineEnterPressed()
+{
+ QDate temp;
+ // -----
+ if(val->date(line->text(), temp)==QValidator::Acceptable)
+ {
+ kdDebug(298) << "KDatePicker::lineEnterPressed: valid date entered." << endl;
+ emit(dateEntered(temp));
+ setDate(temp);
+ } else {
+ KNotifyClient::beep();
+ kdDebug(298) << "KDatePicker::lineEnterPressed: invalid date entered." << endl;
+ }
+}
+
+void
+KDatePicker::todayButtonClicked()
+{
+ setDate(QDate::currentDate());
+}
+
+QSize
+KDatePicker::sizeHint() const
+{
+ return QWidget::sizeHint();
+}
+
+void
+KDatePicker::setFontSize(int s)
+{
+ QWidget *buttons[]= {
+ // yearBackward,
+ // monthBackward,
+ selectMonth,
+ selectYear,
+ // monthForward,
+ // yearForward
+ };
+ const int NoOfButtons=sizeof(buttons)/sizeof(buttons[0]);
+ int count;
+ QFont font;
+ QRect r;
+ // -----
+ fontsize=s;
+ for(count=0; count<NoOfButtons; ++count)
+ {
+ font=buttons[count]->font();
+ font.setPointSize(s);
+ buttons[count]->setFont(font);
+ }
+ QFontMetrics metrics(selectMonth->fontMetrics());
+
+ for (int i = 1; ; ++i)
+ {
+ QString str = KGlobal::locale()->calendar()->monthName(i,
+ KGlobal::locale()->calendar()->year(table->getDate()), false);
+ if (str.isNull()) break;
+ r=metrics.boundingRect(str);
+ maxMonthRect.setWidth(QMAX(r.width(), maxMonthRect.width()));
+ maxMonthRect.setHeight(QMAX(r.height(), maxMonthRect.height()));
+ }
+
+ QSize metricBound = style().sizeFromContents(QStyle::CT_ToolButton,
+ selectMonth,
+ maxMonthRect);
+ selectMonth->setMinimumSize(metricBound);
+
+ table->setFontSize(s);
+}
+
+void
+KDatePicker::setCloseButton( bool enable )
+{
+ if ( enable == (d->closeButton != 0L) )
+ return;
+
+ if ( enable ) {
+ d->closeButton = new QToolButton( this );
+ d->closeButton->setAutoRaise(true);
+ d->navigationLayout->addSpacing(KDialog::spacingHint());
+ d->navigationLayout->addWidget(d->closeButton);
+ QToolTip::add(d->closeButton, i18n("Close"));
+ d->closeButton->setPixmap( SmallIcon("remove") );
+ connect( d->closeButton, SIGNAL( clicked() ),
+ topLevelWidget(), SLOT( close() ) );
+ }
+ else {
+ delete d->closeButton;
+ d->closeButton = 0L;
+ }
+
+ updateGeometry();
+}
+
+bool KDatePicker::hasCloseButton() const
+{
+ return (d->closeButton);
+}
+
+void KDatePicker::virtual_hook( int /*id*/, void* /*data*/ )
+{ /*BASE::virtual_hook( id, data );*/ }
+
diff --git a/kdeui/kdatepicker.h b/kdeui/kdatepicker.h
new file mode 100644
index 000000000..414fb0ab9
--- /dev/null
+++ b/kdeui/kdatepicker.h
@@ -0,0 +1,257 @@
+/* -*- C++ -*-
+ This file is part of the KDE libraries
+ Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org)
+ (C) 1998-2001 Mirko Boehm (mirko@kde.org)
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef KDATEPICKER_H
+#define KDATEPICKER_H
+#include <qdatetime.h>
+#include <qframe.h>
+#include <kdelibs_export.h>
+
+class QLineEdit;
+class QToolButton;
+class KDateValidator;
+class KDateTable;
+
+/**
+ * @short A date selection widget.
+ *
+ * Provides a widget for calendar date input.
+ *
+ * Different from the
+ * previous versions, it now emits two types of signals, either
+ * dateSelected() or dateEntered() (see documentation for both
+ * signals).
+ *
+ * A line edit has been added in the newer versions to allow the user
+ * to select a date directly by entering numbers like 19990101
+ * or 990101.
+ *
+ * \image html kdatepicker.png "KDE Date Widget"
+ *
+ * @version $Id$
+ * @author Tim Gilman, Mirko Boehm
+ *
+ **/
+class KDEUI_EXPORT KDatePicker: public QFrame
+{
+ Q_OBJECT
+ Q_PROPERTY( QDate date READ date WRITE setDate)
+ Q_PROPERTY( bool closeButton READ hasCloseButton WRITE setCloseButton )
+ Q_PROPERTY( int fontSize READ fontSize WRITE setFontSize )
+
+public:
+ /** The usual constructor. The given date will be displayed
+ * initially.
+ **/
+ KDatePicker(QWidget *parent=0,
+ QDate=QDate::currentDate(),
+ const char *name=0);
+
+ /** The usual constructor. The given date will be displayed
+ * initially.
+ * @since 3.1
+ **/
+ KDatePicker(QWidget *parent,
+ QDate,
+ const char *name,
+ WFlags f); // ### KDE 4.0: Merge
+
+ /**
+ * Standard qt widget constructor. The initial date will be the
+ * current date.
+ * @since 3.1
+ */
+ KDatePicker( QWidget *parent, const char *name );
+
+ /**
+ * The destructor.
+ **/
+ virtual ~KDatePicker();
+
+ /** The size hint for date pickers. The size hint recommends the
+ * minimum size of the widget so that all elements may be placed
+ * without clipping. This sometimes looks ugly, so when using the
+ * size hint, try adding 28 to each of the reported numbers of
+ * pixels.
+ **/
+ QSize sizeHint() const;
+
+ /**
+ * Sets the date.
+ *
+ * @returns @p false and does not change anything
+ * if the date given is invalid.
+ **/
+ bool setDate(const QDate&);
+
+ /**
+ * Returns the selected date.
+ * @deprecated
+ **/
+ const QDate& getDate() const KDE_DEPRECATED;
+
+ /**
+ * @returns the selected date.
+ */
+ const QDate &date() const;
+
+ /**
+ * Enables or disables the widget.
+ **/
+ void setEnabled(bool);
+
+ /**
+ * @returns the KDateTable widget child of this KDatePicker
+ * widget.
+ * @since 3.2
+ */
+ KDateTable *dateTable() const { return table; }
+
+ /**
+ * Sets the font size of the widgets elements.
+ **/
+ void setFontSize(int);
+ /**
+ * Returns the font size of the widget elements.
+ */
+ int fontSize() const
+ { return fontsize; }
+
+ /**
+ * By calling this method with @p enable = true, KDatePicker will show
+ * a little close-button in the upper button-row. Clicking the
+ * close-button will cause the KDatePicker's topLevelWidget()'s close()
+ * method being called. This is mostly useful for toplevel datepickers
+ * without a window manager decoration.
+ * @see hasCloseButton
+ * @since 3.1
+ */
+ void setCloseButton( bool enable );
+
+ /**
+ * @returns true if a KDatePicker shows a close-button.
+ * @see setCloseButton
+ * @since 3.1
+ */
+ bool hasCloseButton() const;
+
+protected:
+ /// to catch move keyEvents when QLineEdit has keyFocus
+ virtual bool eventFilter(QObject *o, QEvent *e );
+ /// the resize event
+ virtual void resizeEvent(QResizeEvent*);
+ /// the year forward button
+ QToolButton *yearForward;
+ /// the year backward button
+ QToolButton *yearBackward;
+ /// the month forward button
+ QToolButton *monthForward;
+ /// the month backward button
+ QToolButton *monthBackward;
+ /// the button for selecting the month directly
+ QToolButton *selectMonth;
+ /// the button for selecting the year directly
+ QToolButton *selectYear;
+ /// the line edit to enter the date directly
+ QLineEdit *line;
+ /// the validator for the line edit:
+ KDateValidator *val;
+ /// the date table
+ KDateTable *table;
+ /// the size calculated during resize events
+ // QSize sizehint;
+ /// the widest month string in pixels:
+ QSize maxMonthRect;
+protected slots:
+ void dateChangedSlot(QDate);
+ void tableClickedSlot();
+ void monthForwardClicked();
+ void monthBackwardClicked();
+ void yearForwardClicked();
+ void yearBackwardClicked();
+ /**
+ * @since 3.1
+ * @deprecated in 3.2
+ */
+ void selectWeekClicked();
+ /**
+ * @since 3.1
+ */
+ void selectMonthClicked();
+ /**
+ * @since 3.1
+ */
+ void selectYearClicked();
+ /**
+ * @since 3.1
+ */
+ void lineEnterPressed();
+ /**
+ * @since 3.2
+ */
+ void todayButtonClicked();
+ /**
+ * @since 3.2
+ */
+ void weekSelected(int);
+
+signals:
+ // ### KDE 4.0 Make all QDate parameters const references
+
+ /** This signal is emitted each time the selected date is changed.
+ * Usually, this does not mean that the date has been entered,
+ * since the date also changes, for example, when another month is
+ * selected.
+ * @see dateSelected
+ */
+ void dateChanged(QDate);
+ /** This signal is emitted each time a day has been selected by
+ * clicking on the table (hitting a day in the current month). It
+ * has the same meaning as dateSelected() in older versions of
+ * KDatePicker.
+ */
+ void dateSelected(QDate);
+ /** This signal is emitted when enter is pressed and a VALID date
+ * has been entered before into the line edit. Connect to both
+ * dateEntered() and dateSelected() to receive all events where the
+ * user really enters a date.
+ */
+ void dateEntered(QDate);
+ /** This signal is emitted when the day has been selected by
+ * clicking on it in the table.
+ */
+ void tableClicked();
+
+private slots:
+ void ensureSelectYearIsUp();
+
+private:
+ /// the font size for the widget
+ int fontsize;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ void init( const QDate &dt );
+ void fillWeeksCombo(const QDate &date);
+ class KDatePickerPrivate;
+ KDatePickerPrivate *d;
+};
+
+#endif // KDATEPICKER_H
diff --git a/kdeui/kdatepik.h b/kdeui/kdatepik.h
new file mode 100644
index 000000000..03debbca0
--- /dev/null
+++ b/kdeui/kdatepik.h
@@ -0,0 +1,6 @@
+#ifndef KDE_NO_COMPAT
+#ifndef __KDATEPIK_H_
+#define __KDATEPIK_H_
+#include <kdatepicker.h>
+#endif
+#endif
diff --git a/kdeui/kdatetbl.cpp b/kdeui/kdatetbl.cpp
new file mode 100644
index 000000000..89d73ed7a
--- /dev/null
+++ b/kdeui/kdatetbl.cpp
@@ -0,0 +1,1031 @@
+/* -*- C++ -*-
+ This file is part of the KDE libraries
+ Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org)
+ (C) 1998-2001 Mirko Boehm (mirko@kde.org)
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+/////////////////// KDateTable widget class //////////////////////
+//
+// Copyright (C) 1997 Tim D. Gilman
+// (C) 1998-2001 Mirko Boehm
+// Written using Qt (http://www.troll.no) for the
+// KDE project (http://www.kde.org)
+//
+// This is a support class for the KDatePicker class. It just
+// draws the calender table without titles, but could theoretically
+// be used as a standalone.
+//
+// When a date is selected by the user, it emits a signal:
+// dateSelected(QDate)
+
+#include <kconfig.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+#include <kapplication.h>
+#include <kaccel.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <knotifyclient.h>
+#include <kcalendarsystem.h>
+#include <kshortcut.h>
+#include <kstdaccel.h>
+#include "kdatepicker.h"
+#include "kdatetbl.h"
+#include "kpopupmenu.h"
+#include <qdatetime.h>
+#include <qguardedptr.h>
+#include <qstring.h>
+#include <qpen.h>
+#include <qpainter.h>
+#include <qdialog.h>
+#include <qdict.h>
+#include <assert.h>
+
+
+class KDateTable::KDateTablePrivate
+{
+public:
+ KDateTablePrivate()
+ {
+ popupMenuEnabled=false;
+ useCustomColors=false;
+ }
+
+ ~KDateTablePrivate()
+ {
+ }
+
+ bool popupMenuEnabled;
+ bool useCustomColors;
+
+ struct DatePaintingMode
+ {
+ QColor fgColor;
+ QColor bgColor;
+ BackgroundMode bgMode;
+ };
+ QDict <DatePaintingMode> customPaintingModes;
+
+};
+
+
+KDateValidator::KDateValidator(QWidget* parent, const char* name)
+ : QValidator(parent, name)
+{
+}
+
+QValidator::State
+KDateValidator::validate(QString& text, int&) const
+{
+ QDate temp;
+ // ----- everything is tested in date():
+ return date(text, temp);
+}
+
+QValidator::State
+KDateValidator::date(const QString& text, QDate& d) const
+{
+ QDate tmp = KGlobal::locale()->readDate(text);
+ if (!tmp.isNull())
+ {
+ d = tmp;
+ return Acceptable;
+ } else
+ return Valid;
+}
+
+void
+KDateValidator::fixup( QString& ) const
+{
+
+}
+
+KDateTable::KDateTable(QWidget *parent, QDate date_, const char* name, WFlags f)
+ : QGridView(parent, name, (f | WNoAutoErase))
+{
+ d = new KDateTablePrivate;
+ setFontSize(10);
+ if(!date_.isValid())
+ {
+ kdDebug() << "KDateTable ctor: WARNING: Given date is invalid, using current date." << endl;
+ date_=QDate::currentDate();
+ }
+ setFocusPolicy( QWidget::StrongFocus );
+ setNumRows(7); // 6 weeks max + headline
+ setNumCols(7); // 7 days a week
+ setHScrollBarMode(AlwaysOff);
+ setVScrollBarMode(AlwaysOff);
+ viewport()->setEraseColor(KGlobalSettings::baseColor());
+ setDate(date_); // this initializes firstday, numdays, numDaysPrevMonth
+
+ initAccels();
+}
+
+KDateTable::KDateTable(QWidget *parent, const char* name, WFlags f)
+ : QGridView(parent, name, (f | WNoAutoErase))
+{
+ d = new KDateTablePrivate;
+ setFontSize(10);
+ setFocusPolicy( QWidget::StrongFocus );
+ setNumRows(7); // 6 weeks max + headline
+ setNumCols(7); // 7 days a week
+ setHScrollBarMode(AlwaysOff);
+ setVScrollBarMode(AlwaysOff);
+ viewport()->setEraseColor(KGlobalSettings::baseColor());
+ setDate(QDate::currentDate()); // this initializes firstday, numdays, numDaysPrevMonth
+ initAccels();
+}
+
+KDateTable::~KDateTable()
+{
+ delete d;
+}
+
+void KDateTable::initAccels()
+{
+ KAccel* accel = new KAccel(this, "date table accel");
+ accel->insert(KStdAccel::Next, this, SLOT(nextMonth()));
+ accel->insert(KStdAccel::Prior, this, SLOT(previousMonth()));
+ accel->insert(KStdAccel::Home, this, SLOT(beginningOfMonth()));
+ accel->insert(KStdAccel::End, this, SLOT(endOfMonth()));
+ accel->insert(KStdAccel::BeginningOfLine, this, SLOT(beginningOfWeek()));
+ accel->insert(KStdAccel::EndOfLine, this, SLOT(endOfWeek()));
+ accel->readSettings();
+}
+
+int KDateTable::posFromDate( const QDate &dt )
+{
+ const KCalendarSystem * calendar = KGlobal::locale()->calendar();
+ const int firstWeekDay = KGlobal::locale()->weekStartDay();
+ int pos = calendar->day( dt );
+ int offset = (firstday - firstWeekDay + 7) % 7;
+ // make sure at least one day of the previous month is visible.
+ // adjust this <1 if more days should be forced visible:
+ if ( offset < 1 ) offset += 7;
+ return pos + offset;
+}
+
+QDate KDateTable::dateFromPos( int pos )
+{
+ QDate pCellDate;
+ const KCalendarSystem * calendar = KGlobal::locale()->calendar();
+ calendar->setYMD(pCellDate, calendar->year(date), calendar->month(date), 1);
+
+ int firstWeekDay = KGlobal::locale()->weekStartDay();
+ int offset = (firstday - firstWeekDay + 7) % 7;
+ // make sure at least one day of the previous month is visible.
+ // adjust this <1 if more days should be forced visible:
+ if ( offset < 1 ) offset += 7;
+ pCellDate = calendar->addDays( pCellDate, pos - offset );
+ return pCellDate;
+}
+
+void
+KDateTable::paintEmptyArea(QPainter *paint, int, int, int, int)
+{
+ // Erase the unused areas on the right and bottom.
+ QRect unusedRight = frameRect();
+ unusedRight.setLeft(gridSize().width());
+
+ QRect unusedBottom = frameRect();
+ unusedBottom.setTop(gridSize().height());
+
+ paint->eraseRect(unusedRight);
+ paint->eraseRect(unusedBottom);
+}
+
+void
+KDateTable::paintCell(QPainter *painter, int row, int col)
+{
+ const KCalendarSystem * calendar = KGlobal::locale()->calendar();
+
+ QRect rect;
+ QString text;
+ QPen pen;
+ int w=cellWidth();
+ int h=cellHeight();
+ QFont font=KGlobalSettings::generalFont();
+ // -----
+
+ if(row == 0)
+ { // we are drawing the headline
+ font.setBold(true);
+ painter->setFont(font);
+ bool normalday = true;
+ int firstWeekDay = KGlobal::locale()->weekStartDay();
+ int daynum = ( col+firstWeekDay < 8 ) ? col+firstWeekDay :
+ col+firstWeekDay-7;
+ if ( daynum == calendar->weekDayOfPray() ||
+ ( daynum == 6 && calendar->calendarName() == "gregorian" ) )
+ normalday=false;
+
+ QBrush brushInvertTitle(colorGroup().base());
+ QColor titleColor(isEnabled()?( KGlobalSettings::activeTitleColor() ):( KGlobalSettings::inactiveTitleColor() ) );
+ QColor textColor(isEnabled()?( KGlobalSettings::activeTextColor() ):( KGlobalSettings::inactiveTextColor() ) );
+ if (!normalday)
+ {
+ painter->setPen(textColor);
+ painter->setBrush(textColor);
+ painter->drawRect(0, 0, w, h);
+ painter->setPen(titleColor);
+ } else {
+ painter->setPen(titleColor);
+ painter->setBrush(titleColor);
+ painter->drawRect(0, 0, w, h);
+ painter->setPen(textColor);
+ }
+ painter->drawText(0, 0, w, h-1, AlignCenter,
+ calendar->weekDayName(daynum, true), -1, &rect);
+ painter->setPen(colorGroup().text());
+ painter->moveTo(0, h-1);
+ painter->lineTo(w-1, h-1);
+ // ----- draw the weekday:
+ } else {
+ bool paintRect=true;
+ painter->setFont(font);
+ int pos=7*(row-1)+col;
+
+ QDate pCellDate = dateFromPos( pos );
+ // First day of month
+ text = calendar->dayString(pCellDate, true);
+ if( calendar->month(pCellDate) != calendar->month(date) )
+ { // we are either
+ // ° painting a day of the previous month or
+ // ° painting a day of the following month
+ // TODO: don't hardcode gray here! Use a color with less contrast to the background than normal text.
+ painter->setPen( colorGroup().mid() );
+// painter->setPen(gray);
+ } else { // paint a day of the current month
+ if ( d->useCustomColors )
+ {
+ KDateTablePrivate::DatePaintingMode *mode=d->customPaintingModes[pCellDate.toString()];
+ if (mode)
+ {
+ if (mode->bgMode != NoBgMode)
+ {
+ QBrush oldbrush=painter->brush();
+ painter->setBrush( mode->bgColor );
+ switch(mode->bgMode)
+ {
+ case(CircleMode) : painter->drawEllipse(0,0,w,h);break;
+ case(RectangleMode) : painter->drawRect(0,0,w,h);break;
+ case(NoBgMode) : // Should never be here, but just to get one
+ // less warning when compiling
+ default: break;
+ }
+ painter->setBrush( oldbrush );
+ paintRect=false;
+ }
+ painter->setPen( mode->fgColor );
+ } else
+ painter->setPen(colorGroup().text());
+ } else //if ( firstWeekDay < 4 ) // <- this doesn' make sense at all!
+ painter->setPen(colorGroup().text());
+ }
+
+ pen=painter->pen();
+ int firstWeekDay=KGlobal::locale()->weekStartDay();
+ int offset=firstday-firstWeekDay;
+ if(offset<1)
+ offset+=7;
+ int d = calendar->day(date);
+ if( (offset+d) == (pos+1))
+ {
+ // draw the currently selected date
+ if (isEnabled())
+ {
+ painter->setPen(colorGroup().highlight());
+ painter->setBrush(colorGroup().highlight());
+ }
+ else
+ {
+ painter->setPen(colorGroup().text());
+ painter->setBrush(colorGroup().text());
+ }
+ pen=colorGroup().highlightedText();
+ } else {
+ painter->setBrush(paletteBackgroundColor());
+ painter->setPen(paletteBackgroundColor());
+// painter->setBrush(colorGroup().base());
+// painter->setPen(colorGroup().base());
+ }
+
+ if ( pCellDate == QDate::currentDate() )
+ {
+ painter->setPen(colorGroup().text());
+ }
+
+ if ( paintRect ) painter->drawRect(0, 0, w, h);
+ painter->setPen(pen);
+ painter->drawText(0, 0, w, h, AlignCenter, text, -1, &rect);
+ }
+ if(rect.width()>maxCell.width()) maxCell.setWidth(rect.width());
+ if(rect.height()>maxCell.height()) maxCell.setHeight(rect.height());
+}
+
+void KDateTable::nextMonth()
+{
+ const KCalendarSystem * calendar = KGlobal::locale()->calendar();
+ setDate(calendar->addMonths( date, 1 ));
+}
+
+void KDateTable::previousMonth()
+{
+ const KCalendarSystem * calendar = KGlobal::locale()->calendar();
+ setDate(calendar->addMonths( date, -1 ));
+}
+
+void KDateTable::beginningOfMonth()
+{
+ setDate(date.addDays(1 - date.day()));
+}
+
+void KDateTable::endOfMonth()
+{
+ setDate(date.addDays(date.daysInMonth() - date.day()));
+}
+
+void KDateTable::beginningOfWeek()
+{
+ setDate(date.addDays(1 - date.dayOfWeek()));
+}
+
+void KDateTable::endOfWeek()
+{
+ setDate(date.addDays(7 - date.dayOfWeek()));
+}
+
+void
+KDateTable::keyPressEvent( QKeyEvent *e )
+{
+ switch( e->key() ) {
+ case Key_Up:
+ setDate(date.addDays(-7));
+ break;
+ case Key_Down:
+ setDate(date.addDays(7));
+ break;
+ case Key_Left:
+ setDate(date.addDays(-1));
+ break;
+ case Key_Right:
+ setDate(date.addDays(1));
+ break;
+ case Key_Minus:
+ setDate(date.addDays(-1));
+ break;
+ case Key_Plus:
+ setDate(date.addDays(1));
+ break;
+ case Key_N:
+ setDate(QDate::currentDate());
+ break;
+ case Key_Return:
+ case Key_Enter:
+ emit tableClicked();
+ break;
+ case Key_Control:
+ case Key_Alt:
+ case Key_Meta:
+ case Key_Shift:
+ // Don't beep for modifiers
+ break;
+ default:
+ if (!e->state()) { // hm
+ KNotifyClient::beep();
+}
+ }
+}
+
+void
+KDateTable::viewportResizeEvent(QResizeEvent * e)
+{
+ QGridView::viewportResizeEvent(e);
+
+ setCellWidth(viewport()->width()/7);
+ setCellHeight(viewport()->height()/7);
+}
+
+void
+KDateTable::setFontSize(int size)
+{
+ int count;
+ QFontMetrics metrics(fontMetrics());
+ QRect rect;
+ // ----- store rectangles:
+ fontsize=size;
+ // ----- find largest day name:
+ maxCell.setWidth(0);
+ maxCell.setHeight(0);
+ for(count=0; count<7; ++count)
+ {
+ rect=metrics.boundingRect(KGlobal::locale()->calendar()
+ ->weekDayName(count+1, true));
+ maxCell.setWidth(QMAX(maxCell.width(), rect.width()));
+ maxCell.setHeight(QMAX(maxCell.height(), rect.height()));
+ }
+ // ----- compare with a real wide number and add some space:
+ rect=metrics.boundingRect(QString::fromLatin1("88"));
+ maxCell.setWidth(QMAX(maxCell.width()+2, rect.width()));
+ maxCell.setHeight(QMAX(maxCell.height()+4, rect.height()));
+}
+
+void
+KDateTable::wheelEvent ( QWheelEvent * e )
+{
+ setDate(date.addMonths( -(int)(e->delta()/120)) );
+ e->accept();
+}
+
+void
+KDateTable::contentsMousePressEvent(QMouseEvent *e)
+{
+
+ if(e->type()!=QEvent::MouseButtonPress)
+ { // the KDatePicker only reacts on mouse press events:
+ return;
+ }
+ if(!isEnabled())
+ {
+ KNotifyClient::beep();
+ return;
+ }
+
+ // -----
+ int row, col, pos, temp;
+ QPoint mouseCoord;
+ // -----
+ mouseCoord = e->pos();
+ row=rowAt(mouseCoord.y());
+ col=columnAt(mouseCoord.x());
+ if(row<1 || col<0)
+ { // the user clicked on the frame of the table
+ return;
+ }
+
+ // Rows and columns are zero indexed. The (row - 1) below is to avoid counting
+ // the row with the days of the week in the calculation.
+
+ // old selected date:
+ temp = posFromDate( date );
+ // new position and date
+ pos = (7 * (row - 1)) + col;
+ QDate clickedDate = dateFromPos( pos );
+
+ // set the new date. If it is in the previous or next month, the month will
+ // automatically be changed, no need to do that manually...
+ setDate( clickedDate );
+
+ // call updateCell on the old and new selection. If setDate switched to a different
+ // month, these cells will be painted twice, but that's no problem.
+ updateCell( temp/7+1, temp%7 );
+ updateCell( row, col );
+
+ emit tableClicked();
+
+ if ( e->button() == Qt::RightButton && d->popupMenuEnabled )
+ {
+ KPopupMenu *menu = new KPopupMenu();
+ menu->insertTitle( KGlobal::locale()->formatDate(clickedDate) );
+ emit aboutToShowContextMenu( menu, clickedDate );
+ menu->popup(e->globalPos());
+ }
+}
+
+bool
+KDateTable::setDate(const QDate& date_)
+{
+ bool changed=false;
+ QDate temp;
+ // -----
+ if(!date_.isValid())
+ {
+ kdDebug() << "KDateTable::setDate: refusing to set invalid date." << endl;
+ return false;
+ }
+ if(date!=date_)
+ {
+ emit(dateChanged(date, date_));
+ date=date_;
+ emit(dateChanged(date));
+ changed=true;
+ }
+ const KCalendarSystem * calendar = KGlobal::locale()->calendar();
+
+ calendar->setYMD(temp, calendar->year(date), calendar->month(date), 1);
+ //temp.setYMD(date.year(), date.month(), 1);
+ //kdDebug() << "firstDayInWeek: " << temp.toString() << endl;
+ firstday=temp.dayOfWeek();
+ numdays=calendar->daysInMonth(date);
+
+ temp = calendar->addMonths(temp, -1);
+ numDaysPrevMonth=calendar->daysInMonth(temp);
+ if(changed)
+ {
+ repaintContents(false);
+ }
+ return true;
+}
+
+const QDate&
+KDateTable::getDate() const
+{
+ return date;
+}
+
+// what are those repaintContents() good for? (pfeiffer)
+void KDateTable::focusInEvent( QFocusEvent *e )
+{
+// repaintContents(false);
+ QGridView::focusInEvent( e );
+}
+
+void KDateTable::focusOutEvent( QFocusEvent *e )
+{
+// repaintContents(false);
+ QGridView::focusOutEvent( e );
+}
+
+QSize
+KDateTable::sizeHint() const
+{
+ if(maxCell.height()>0 && maxCell.width()>0)
+ {
+ return QSize(maxCell.width()*numCols()+2*frameWidth(),
+ (maxCell.height()+2)*numRows()+2*frameWidth());
+ } else {
+ kdDebug() << "KDateTable::sizeHint: obscure failure - " << endl;
+ return QSize(-1, -1);
+ }
+}
+
+void KDateTable::setPopupMenuEnabled( bool enable )
+{
+ d->popupMenuEnabled=enable;
+}
+
+bool KDateTable::popupMenuEnabled() const
+{
+ return d->popupMenuEnabled;
+}
+
+void KDateTable::setCustomDatePainting(const QDate &date, const QColor &fgColor, BackgroundMode bgMode, const QColor &bgColor)
+{
+ if (!fgColor.isValid())
+ {
+ unsetCustomDatePainting( date );
+ return;
+ }
+
+ KDateTablePrivate::DatePaintingMode *mode=new KDateTablePrivate::DatePaintingMode;
+ mode->bgMode=bgMode;
+ mode->fgColor=fgColor;
+ mode->bgColor=bgColor;
+
+ d->customPaintingModes.replace( date.toString(), mode );
+ d->useCustomColors=true;
+ update();
+}
+
+void KDateTable::unsetCustomDatePainting( const QDate &date )
+{
+ d->customPaintingModes.remove( date.toString() );
+}
+
+KDateInternalWeekSelector::KDateInternalWeekSelector
+(QWidget* parent, const char* name)
+ : QLineEdit(parent, name),
+ val(new QIntValidator(this)),
+ result(0)
+{
+ QFont font;
+ // -----
+ font=KGlobalSettings::generalFont();
+ setFont(font);
+ setFrameStyle(QFrame::NoFrame);
+ setValidator(val);
+ connect(this, SIGNAL(returnPressed()), SLOT(weekEnteredSlot()));
+}
+
+void
+KDateInternalWeekSelector::weekEnteredSlot()
+{
+ bool ok;
+ int week;
+ // ----- check if this is a valid week:
+ week=text().toInt(&ok);
+ if(!ok)
+ {
+ KNotifyClient::beep();
+ emit(closeMe(0));
+ return;
+ }
+ result=week;
+ emit(closeMe(1));
+}
+
+int
+KDateInternalWeekSelector::getWeek()
+{
+ return result;
+}
+
+void
+KDateInternalWeekSelector::setWeek(int week)
+{
+ QString temp;
+ // -----
+ temp.setNum(week);
+ setText(temp);
+}
+
+void
+KDateInternalWeekSelector::setMaxWeek(int max)
+{
+ val->setRange(1, max);
+}
+
+// ### CFM To avoid binary incompatibility.
+// In future releases, remove this and replace by a QDate
+// private member, needed in KDateInternalMonthPicker::paintCell
+class KDateInternalMonthPicker::KDateInternalMonthPrivate {
+public:
+ KDateInternalMonthPrivate (int y, int m, int d)
+ : year(y), month(m), day(d)
+ {}
+ int year;
+ int month;
+ int day;
+};
+
+KDateInternalMonthPicker::~KDateInternalMonthPicker() {
+ delete d;
+}
+
+KDateInternalMonthPicker::KDateInternalMonthPicker
+(const QDate & date, QWidget* parent, const char* name)
+ : QGridView(parent, name),
+ result(0) // invalid
+{
+ QRect rect;
+ QFont font;
+ // -----
+ activeCol = -1;
+ activeRow = -1;
+ font=KGlobalSettings::generalFont();
+ setFont(font);
+ setHScrollBarMode(AlwaysOff);
+ setVScrollBarMode(AlwaysOff);
+ setFrameStyle(QFrame::NoFrame);
+ setNumCols(3);
+ d = new KDateInternalMonthPrivate(date.year(), date.month(), date.day());
+ // For monthsInYear != 12
+ setNumRows( (KGlobal::locale()->calendar()->monthsInYear(date) + 2) / 3);
+ // enable to find drawing failures:
+ // setTableFlags(Tbl_clipCellPainting);
+ viewport()->setEraseColor(KGlobalSettings::baseColor()); // for consistency with the datepicker
+ // ----- find the preferred size
+ // (this is slow, possibly, but unfortunately it is needed here):
+ QFontMetrics metrics(font);
+ for(int i = 1; ; ++i)
+ {
+ QString str = KGlobal::locale()->calendar()->monthName(i,
+ KGlobal::locale()->calendar()->year(date), false);
+ if (str.isNull()) break;
+ rect=metrics.boundingRect(str);
+ if(max.width()<rect.width()) max.setWidth(rect.width());
+ if(max.height()<rect.height()) max.setHeight(rect.height());
+ }
+}
+
+QSize
+KDateInternalMonthPicker::sizeHint() const
+{
+ return QSize((max.width()+6)*numCols()+2*frameWidth(),
+ (max.height()+6)*numRows()+2*frameWidth());
+}
+
+int
+KDateInternalMonthPicker::getResult() const
+{
+ return result;
+}
+
+void
+KDateInternalMonthPicker::setupPainter(QPainter *p)
+{
+ p->setPen(KGlobalSettings::textColor());
+}
+
+void
+KDateInternalMonthPicker::viewportResizeEvent(QResizeEvent*)
+{
+ setCellWidth(width() / numCols());
+ setCellHeight(height() / numRows());
+}
+
+void
+KDateInternalMonthPicker::paintCell(QPainter* painter, int row, int col)
+{
+ int index;
+ QString text;
+ // ----- find the number of the cell:
+ index=3*row+col+1;
+ text=KGlobal::locale()->calendar()->monthName(index,
+ KGlobal::locale()->calendar()->year(QDate(d->year, d->month,
+ d->day)), false);
+ painter->drawText(0, 0, cellWidth(), cellHeight(), AlignCenter, text);
+ if ( activeCol == col && activeRow == row )
+ painter->drawRect( 0, 0, cellWidth(), cellHeight() );
+}
+
+void
+KDateInternalMonthPicker::contentsMousePressEvent(QMouseEvent *e)
+{
+ if(!isEnabled() || e->button() != LeftButton)
+ {
+ KNotifyClient::beep();
+ return;
+ }
+ // -----
+ int row, col;
+ QPoint mouseCoord;
+ // -----
+ mouseCoord = e->pos();
+ row=rowAt(mouseCoord.y());
+ col=columnAt(mouseCoord.x());
+
+ if(row<0 || col<0)
+ { // the user clicked on the frame of the table
+ activeCol = -1;
+ activeRow = -1;
+ } else {
+ activeCol = col;
+ activeRow = row;
+ updateCell( row, col /*, false */ );
+ }
+}
+
+void
+KDateInternalMonthPicker::contentsMouseMoveEvent(QMouseEvent *e)
+{
+ if (e->state() & LeftButton)
+ {
+ int row, col;
+ QPoint mouseCoord;
+ // -----
+ mouseCoord = e->pos();
+ row=rowAt(mouseCoord.y());
+ col=columnAt(mouseCoord.x());
+ int tmpRow = -1, tmpCol = -1;
+ if(row<0 || col<0)
+ { // the user clicked on the frame of the table
+ if ( activeCol > -1 )
+ {
+ tmpRow = activeRow;
+ tmpCol = activeCol;
+ }
+ activeCol = -1;
+ activeRow = -1;
+ } else {
+ bool differentCell = (activeRow != row || activeCol != col);
+ if ( activeCol > -1 && differentCell)
+ {
+ tmpRow = activeRow;
+ tmpCol = activeCol;
+ }
+ if ( differentCell)
+ {
+ activeRow = row;
+ activeCol = col;
+ updateCell( row, col /*, false */ ); // mark the new active cell
+ }
+ }
+ if ( tmpRow > -1 ) // repaint the former active cell
+ updateCell( tmpRow, tmpCol /*, true */ );
+ }
+}
+
+void
+KDateInternalMonthPicker::contentsMouseReleaseEvent(QMouseEvent *e)
+{
+ if(!isEnabled())
+ {
+ return;
+ }
+ // -----
+ int row, col, pos;
+ QPoint mouseCoord;
+ // -----
+ mouseCoord = e->pos();
+ row=rowAt(mouseCoord.y());
+ col=columnAt(mouseCoord.x());
+ if(row<0 || col<0)
+ { // the user clicked on the frame of the table
+ emit(closeMe(0));
+ return;
+ }
+
+ pos=3*row+col+1;
+ result=pos;
+ emit(closeMe(1));
+}
+
+
+
+KDateInternalYearSelector::KDateInternalYearSelector
+(QWidget* parent, const char* name)
+ : QLineEdit(parent, name),
+ val(new QIntValidator(this)),
+ result(0)
+{
+ QFont font;
+ // -----
+ font=KGlobalSettings::generalFont();
+ setFont(font);
+ setFrameStyle(QFrame::NoFrame);
+ // we have to respect the limits of QDate here, I fear:
+ val->setRange(0, 8000);
+ setValidator(val);
+ connect(this, SIGNAL(returnPressed()), SLOT(yearEnteredSlot()));
+}
+
+void
+KDateInternalYearSelector::yearEnteredSlot()
+{
+ bool ok;
+ int year;
+ QDate date;
+ // ----- check if this is a valid year:
+ year=text().toInt(&ok);
+ if(!ok)
+ {
+ KNotifyClient::beep();
+ emit(closeMe(0));
+ return;
+ }
+ //date.setYMD(year, 1, 1);
+ KGlobal::locale()->calendar()->setYMD(date, year, 1, 1);
+ if(!date.isValid())
+ {
+ KNotifyClient::beep();
+ emit(closeMe(0));
+ return;
+ }
+ result=year;
+ emit(closeMe(1));
+}
+
+int
+KDateInternalYearSelector::getYear()
+{
+ return result;
+}
+
+void
+KDateInternalYearSelector::setYear(int year)
+{
+ QString temp;
+ // -----
+ temp.setNum(year);
+ setText(temp);
+}
+
+class KPopupFrame::KPopupFramePrivate
+{
+ public:
+ KPopupFramePrivate() : exec(false) {}
+
+ bool exec;
+};
+
+KPopupFrame::KPopupFrame(QWidget* parent, const char* name)
+ : QFrame(parent, name, WType_Popup),
+ result(0), // rejected
+ main(0),
+ d(new KPopupFramePrivate)
+{
+ setFrameStyle(QFrame::Box|QFrame::Raised);
+ setMidLineWidth(2);
+}
+
+KPopupFrame::~KPopupFrame()
+{
+ delete d;
+}
+
+void
+KPopupFrame::keyPressEvent(QKeyEvent* e)
+{
+ if(e->key()==Key_Escape)
+ {
+ result=0; // rejected
+ d->exec = false;
+ qApp->exit_loop();
+ }
+}
+
+void
+KPopupFrame::close(int r)
+{
+ result=r;
+ d->exec = false;
+ qApp->exit_loop();
+}
+
+void
+KPopupFrame::hide()
+{
+ QFrame::hide();
+ if (d->exec)
+ {
+ d->exec = false;
+ qApp->exit_loop();
+ }
+}
+
+void
+KPopupFrame::setMainWidget(QWidget* m)
+{
+ main=m;
+ if(main)
+ {
+ resize(main->width()+2*frameWidth(), main->height()+2*frameWidth());
+ }
+}
+
+void
+KPopupFrame::resizeEvent(QResizeEvent*)
+{
+ if(main)
+ {
+ main->setGeometry(frameWidth(), frameWidth(),
+ width()-2*frameWidth(), height()-2*frameWidth());
+ }
+}
+
+void
+KPopupFrame::popup(const QPoint &pos)
+{
+ // Make sure the whole popup is visible.
+ QRect d = KGlobalSettings::desktopGeometry(pos);
+
+ int x = pos.x();
+ int y = pos.y();
+ int w = width();
+ int h = height();
+ if (x+w > d.x()+d.width())
+ x = d.width() - w;
+ if (y+h > d.y()+d.height())
+ y = d.height() - h;
+ if (x < d.x())
+ x = 0;
+ if (y < d.y())
+ y = 0;
+
+ // Pop the thingy up.
+ move(x, y);
+ show();
+}
+
+int
+KPopupFrame::exec(QPoint pos)
+{
+ popup(pos);
+ repaint();
+ d->exec = true;
+ const QGuardedPtr<QObject> that = this;
+ qApp->enter_loop();
+ if ( !that )
+ return QDialog::Rejected;
+ hide();
+ return result;
+}
+
+int
+KPopupFrame::exec(int x, int y)
+{
+ return exec(QPoint(x, y));
+}
+
+void KPopupFrame::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void KDateTable::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "kdatetbl.moc"
diff --git a/kdeui/kdatetbl.h b/kdeui/kdatetbl.h
new file mode 100644
index 000000000..c29c9d3e1
--- /dev/null
+++ b/kdeui/kdatetbl.h
@@ -0,0 +1,447 @@
+/* -*- C++ -*-
+ This file is part of the KDE libraries
+ Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org)
+ (C) 1998-2001 Mirko Boehm (mirko@kde.org)
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef KDATETBL_H
+#define KDATETBL_H
+
+// KDE4: rename this file to kdatetable.h
+
+#include <qvalidator.h>
+#include <qgridview.h>
+#include <qlineedit.h>
+#include <qdatetime.h>
+#include <qcolor.h>
+
+#include <kdelibs_export.h>
+
+class KPopupMenu;
+
+/** Week selection widget.
+* @internal
+* @version $Id$
+* @author Stephan Binner
+*/
+class KDEUI_EXPORT KDateInternalWeekSelector : public QLineEdit
+{
+ Q_OBJECT
+protected:
+ QIntValidator *val;
+ int result;
+public slots:
+ void weekEnteredSlot();
+ void setMaxWeek(int max);
+signals:
+ void closeMe(int);
+public:
+ KDateInternalWeekSelector( QWidget* parent=0, const char* name=0);
+ int getWeek();
+ void setWeek(int week);
+
+private:
+ class KDateInternalWeekPrivate;
+ KDateInternalWeekPrivate *d;
+};
+
+/**
+* A table containing month names. It is used to pick a month directly.
+* @internal
+* @version $Id$
+* @author Tim Gilman, Mirko Boehm
+*/
+class KDEUI_EXPORT KDateInternalMonthPicker : public QGridView
+{
+ Q_OBJECT
+protected:
+ /**
+ * Store the month that has been clicked [1..12].
+ */
+ int result;
+ /**
+ * the cell under mouse cursor when LBM is pressed
+ */
+ short int activeCol;
+ short int activeRow;
+ /**
+ * Contains the largest rectangle needed by the month names.
+ */
+ QRect max;
+signals:
+ /**
+ * This is send from the mouse click event handler.
+ */
+ void closeMe(int);
+public:
+ /**
+ * The constructor.
+ */
+ KDateInternalMonthPicker(const QDate& date, QWidget* parent, const char* name=0);
+ /**
+ * The destructor.
+ */
+ ~KDateInternalMonthPicker();
+ /**
+ * The size hint.
+ */
+ QSize sizeHint() const;
+ /**
+ * Return the result. 0 means no selection (reject()), 1..12 are the
+ * months.
+ */
+ int getResult() const;
+protected:
+ /**
+ * Set up the painter.
+ */
+ void setupPainter(QPainter *p);
+ /**
+ * The resize event.
+ */
+ virtual void viewportResizeEvent(QResizeEvent*);
+ /**
+ * Paint a cell. This simply draws the month names in it.
+ */
+ virtual void paintCell(QPainter* painter, int row, int col);
+ /**
+ * Catch mouse click and move events to paint a rectangle around the item.
+ */
+ virtual void contentsMousePressEvent(QMouseEvent *e);
+ virtual void contentsMouseMoveEvent(QMouseEvent *e);
+ /**
+ * Emit monthSelected(int) when a cell has been released.
+ */
+ virtual void contentsMouseReleaseEvent(QMouseEvent *e);
+
+private:
+ class KDateInternalMonthPrivate;
+ KDateInternalMonthPrivate *d;
+};
+
+/** Year selection widget.
+* @internal
+* @version $Id$
+* @author Tim Gilman, Mirko Boehm
+*/
+class KDEUI_EXPORT KDateInternalYearSelector : public QLineEdit
+{
+ Q_OBJECT
+protected:
+ QIntValidator *val;
+ int result;
+public slots:
+ void yearEnteredSlot();
+signals:
+ void closeMe(int);
+public:
+ KDateInternalYearSelector( QWidget* parent=0, const char* name=0);
+ int getYear();
+ void setYear(int year);
+
+private:
+ class KDateInternalYearPrivate;
+ KDateInternalYearPrivate *d;
+
+};
+
+/**
+ * Frame with popup menu behavior.
+ * @author Tim Gilman, Mirko Boehm
+ * @version $Id$
+ */
+class KDEUI_EXPORT KPopupFrame : public QFrame
+{
+ Q_OBJECT
+protected:
+ /**
+ * The result. It is returned from exec() when the popup window closes.
+ */
+ int result;
+ /**
+ * Catch key press events.
+ */
+ virtual void keyPressEvent(QKeyEvent* e);
+ /**
+ * The only subwidget that uses the whole dialog window.
+ */
+ QWidget *main;
+public slots:
+ /**
+ * Close the popup window. This is called from the main widget, usually.
+ * @p r is the result returned from exec().
+ */
+ void close(int r);
+ /**
+ * Hides the widget. Reimplemented from QWidget
+ */
+ void hide();
+
+public:
+ /**
+ * The contructor. Creates a dialog without buttons.
+ */
+ KPopupFrame(QWidget* parent=0, const char* name=0);
+ /**
+ * The destructor.
+ */
+ ~KPopupFrame();
+ /**
+ * Set the main widget. You cannot set the main widget from the constructor,
+ * since it must be a child of the frame itselfes.
+ * Be careful: the size is set to the main widgets size. It is up to you to
+ * set the main widgets correct size before setting it as the main
+ * widget.
+ */
+ void setMainWidget(QWidget* m);
+ /**
+ * The resize event. Simply resizes the main widget to the whole
+ * widgets client size.
+ */
+ virtual void resizeEvent(QResizeEvent*);
+ /**
+ * Open the popup window at position pos.
+ */
+ void popup(const QPoint &pos);
+ /**
+ * Execute the popup window.
+ */
+ int exec(QPoint p); // KDE4: const QPoint&
+ /**
+ * Execute the popup window.
+ */
+ int exec(int x, int y);
+
+private:
+
+ virtual bool close(bool alsoDelete) { return QFrame::close(alsoDelete); }
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KPopupFramePrivate;
+ KPopupFramePrivate *d;
+};
+
+/**
+* Validates user-entered dates.
+*/
+class KDEUI_EXPORT KDateValidator : public QValidator
+{
+public:
+ KDateValidator(QWidget* parent=0, const char* name=0);
+ virtual State validate(QString&, int&) const;
+ virtual void fixup ( QString & input ) const;
+ State date(const QString&, QDate&) const;
+};
+
+/**
+ * Date selection table.
+ * This is a support class for the KDatePicker class. It just
+ * draws the calender table without titles, but could theoretically
+ * be used as a standalone.
+ *
+ * When a date is selected by the user, it emits a signal:
+ * dateSelected(QDate)
+ *
+ * @internal
+ * @version $Id$
+ * @author Tim Gilman, Mirko Boehm
+ */
+class KDEUI_EXPORT KDateTable : public QGridView
+{
+ Q_OBJECT
+ Q_PROPERTY( QDate date READ getDate WRITE setDate )
+ Q_PROPERTY( bool popupMenu READ popupMenuEnabled WRITE setPopupMenuEnabled )
+
+public:
+ /**
+ * The constructor.
+ */
+ KDateTable(QWidget *parent=0, QDate date=QDate::currentDate(),
+ const char* name=0, WFlags f=0);
+
+ /**
+ * The constructor.
+ * @since 3.4
+ */
+ KDateTable(QWidget *parent, const char* name, WFlags f=0);
+
+ /**
+ * The destructor.
+ */
+ ~KDateTable();
+
+ /**
+ * Returns a recommended size for the widget.
+ * To save some time, the size of the largest used cell content is
+ * calculated in each paintCell() call, since all calculations have
+ * to be done there anyway. The size is stored in maxCell. The
+ * sizeHint() simply returns a multiple of maxCell.
+ */
+ virtual QSize sizeHint() const;
+ /**
+ * Set the font size of the date table.
+ */
+ void setFontSize(int size);
+ /**
+ * Select and display this date.
+ */
+ bool setDate(const QDate&);
+ // ### KDE 4.0 rename to date()
+ const QDate& getDate() const;
+
+ /**
+ * Enables a popup menu when right clicking on a date.
+ *
+ * When it's enabled, this object emits a aboutToShowContextMenu signal
+ * where you can fill in the menu items.
+ *
+ * @since 3.2
+ */
+ void setPopupMenuEnabled( bool enable );
+
+ /**
+ * Returns if the popup menu is enabled or not
+ */
+ bool popupMenuEnabled() const;
+
+ enum BackgroundMode { NoBgMode=0, RectangleMode, CircleMode };
+
+ /**
+ * Makes a given date be painted with a given foregroundColor, and background
+ * (a rectangle, or a circle/ellipse) in a given color.
+ *
+ * @since 3.2
+ */
+ void setCustomDatePainting( const QDate &date, const QColor &fgColor, BackgroundMode bgMode=NoBgMode, const QColor &bgColor=QColor());
+
+ /**
+ * Unsets the custom painting of a date so that the date is painted as usual.
+ *
+ * @since 3.2
+ */
+ void unsetCustomDatePainting( const QDate &date );
+
+protected:
+ /**
+ * calculate the position of the cell in the matrix for the given date. The result is the 0-based index.
+ */
+ int posFromDate( const QDate &date ); // KDE4: make this virtual, so subclasses can reimplement this and use a different default for the start of the matrix
+ /**
+ * calculate the date that is displayed at a given cell in the matrix. pos is the
+ * 0-based index in the matrix. Inverse function to posForDate().
+ */
+ QDate dateFromPos( int pos ); // KDE4: make this virtual
+
+ /**
+ * Paint a cell.
+ */
+ virtual void paintCell(QPainter*, int, int);
+
+ /**
+ * Paint the empty area (background).
+ */
+ virtual void paintEmptyArea(QPainter*, int, int, int, int);
+
+ /**
+ * Handle the resize events.
+ */
+ virtual void viewportResizeEvent(QResizeEvent *);
+ /**
+ * React on mouse clicks that select a date.
+ */
+ virtual void contentsMousePressEvent(QMouseEvent *);
+ virtual void wheelEvent( QWheelEvent * e );
+ virtual void keyPressEvent( QKeyEvent *e );
+ virtual void focusInEvent( QFocusEvent *e );
+ virtual void focusOutEvent( QFocusEvent *e );
+
+ // ### KDE 4.0 make the following private and mark as members
+
+ /**
+ * The font size of the displayed text.
+ */
+ int fontsize;
+ /**
+ * The currently selected date.
+ */
+ QDate date;
+ /**
+ * The day of the first day in the month [1..7].
+ */
+ int firstday;
+ /**
+ * The number of days in the current month.
+ */
+ int numdays;
+ /**
+ * The number of days in the previous month.
+ */
+ int numDaysPrevMonth;
+ /**
+ * unused
+ * ### remove in KDE 4.0
+ */
+ bool unused_hasSelection;
+ /**
+ * Save the size of the largest used cell content.
+ */
+ QRect maxCell;
+signals:
+ /**
+ * The selected date changed.
+ */
+ // ### KDE 4.0 make parameter a const reference
+ void dateChanged(QDate);
+ /**
+ * This function behaves essentially like the one above.
+ * The selected date changed.
+ * @param cur The current date
+ * @param old The date before the date was changed
+ */
+ void dateChanged(const QDate& cur, const QDate& old);
+ /**
+ * A date has been selected by clicking on the table.
+ */
+ void tableClicked();
+
+ /**
+ * A popup menu for a given date is about to be shown (as when the user
+ * right clicks on that date and the popup menu is enabled). Connect
+ * the slot where you fill the menu to this signal.
+ *
+ * @since 3.2
+ */
+ void aboutToShowContextMenu( KPopupMenu * menu, const QDate &date);
+
+private slots:
+ void nextMonth();
+ void previousMonth();
+ void beginningOfMonth();
+ void endOfMonth();
+ void beginningOfWeek();
+ void endOfWeek();
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KDateTablePrivate;
+ KDateTablePrivate *d;
+
+ void initAccels();
+};
+
+#endif // KDATETBL_H
diff --git a/kdeui/kdatetimewidget.cpp b/kdeui/kdatetimewidget.cpp
new file mode 100644
index 000000000..c696a4fcb
--- /dev/null
+++ b/kdeui/kdatetimewidget.cpp
@@ -0,0 +1,74 @@
+#include <qlayout.h>
+
+#include "kdatewidget.h"
+#include "kdebug.h"
+#include "kdialog.h"
+#include "ktimewidget.h"
+
+#include "kdatetimewidget.h"
+
+class KDateTimeWidget::KDateTimeWidgetPrivate
+{
+public:
+ KDateWidget * dateWidget;
+ KTimeWidget * timeWidget;
+};
+
+KDateTimeWidget::KDateTimeWidget(QWidget * parent, const char * name)
+ : QWidget(parent, name)
+{
+ init();
+}
+
+KDateTimeWidget::KDateTimeWidget(const QDateTime & datetime,
+ QWidget * parent, const char * name)
+ : QWidget(parent, name)
+{
+ init();
+
+ setDateTime(datetime);
+}
+
+KDateTimeWidget::~KDateTimeWidget()
+{
+ delete d;
+}
+
+void KDateTimeWidget::init()
+{
+ d = new KDateTimeWidgetPrivate;
+
+ QHBoxLayout *layout = new QHBoxLayout(this, 0, KDialog::spacingHint());
+ layout->setAutoAdd(true);
+
+ d->dateWidget = new KDateWidget(this);
+ d->timeWidget = new KTimeWidget(this);
+
+ connect(d->dateWidget, SIGNAL(changed(QDate)),
+ SLOT(slotValueChanged()));
+ connect(d->timeWidget, SIGNAL(valueChanged(const QTime &)),
+ SLOT(slotValueChanged()));
+}
+
+void KDateTimeWidget::setDateTime(const QDateTime & datetime)
+{
+ d->dateWidget->setDate(datetime.date());
+ d->timeWidget->setTime(datetime.time());
+}
+
+QDateTime KDateTimeWidget::dateTime() const
+{
+ return QDateTime(d->dateWidget->date(), d->timeWidget->time());
+}
+
+void KDateTimeWidget::slotValueChanged()
+{
+ QDateTime datetime(d->dateWidget->date(),
+ d->timeWidget->time());
+
+ kdDebug() << "slotValueChanged(): " << datetime << "\n";
+
+ emit valueChanged(datetime);
+}
+
+#include "kdatetimewidget.moc"
diff --git a/kdeui/kdatetimewidget.h b/kdeui/kdatetimewidget.h
new file mode 100644
index 000000000..1a3a98ab4
--- /dev/null
+++ b/kdeui/kdatetimewidget.h
@@ -0,0 +1,92 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2002 Hans Petter bieker <bieker@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __KDATETIMEWIDGET__
+#define __KDATETIMEWIDGET__
+
+#include <qwidget.h>
+#include <qdatetime.h>
+
+#include <kdelibs_export.h>
+
+/**
+ * @short A combination of a date and a time selection widget.
+ *
+ * This widget can be used to display or allow user selection of date and time.
+ *
+ * @see KDateWidget
+ *
+ * \image html kdatetimewidget.png "KDE Date Time Widget"
+ *
+ * @author Hans Petter Bieker <bieker@kde.org>
+ * @version $Id$
+ * @since 3.2
+ */
+class KDEUI_EXPORT KDateTimeWidget : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY( QDateTime dateTime READ dateTime WRITE setDateTime )
+
+public:
+ /**
+ * Constructs a date and time selection widget.
+ */
+ KDateTimeWidget(QWidget * parent = 0, const char * name = 0);
+
+ /**
+ * Constructs a date and time selection widget with the initial date and
+ * time set to @p datetime.
+ */
+ KDateTimeWidget(const QDateTime & datetime,
+ QWidget * parent = 0, const char * name = 0 );
+
+ /**
+ * Destructs the date and time selection widget.
+ */
+ virtual ~KDateTimeWidget();
+
+ /**
+ * Returns the currently selected date and time.
+ */
+ QDateTime dateTime() const;
+
+public slots:
+ /**
+ * Changes the selected date and time to @p datetime.
+ */
+ void setDateTime(const QDateTime & datetime);
+
+signals:
+ /**
+ * Emitted whenever the date or time of the widget
+ * is changed, either with setDateTime() or via user selection.
+ */
+ void valueChanged(const QDateTime & datetime);
+
+private:
+ void init();
+
+private slots:
+ void slotValueChanged();
+
+private:
+ class KDateTimeWidgetPrivate;
+ KDateTimeWidgetPrivate *d;
+};
+
+#endif
diff --git a/kdeui/kdatewidget.cpp b/kdeui/kdatewidget.cpp
new file mode 100644
index 000000000..1db6d235b
--- /dev/null
+++ b/kdeui/kdatewidget.cpp
@@ -0,0 +1,177 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2001 Waldo Bastian (bastian@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#include <qpopupmenu.h>
+#include <qcombobox.h>
+#include <qlayout.h>
+#include <qlineedit.h>
+
+#include "knuminput.h"
+#include "kglobal.h"
+#include "klocale.h"
+#include "kcalendarsystem.h"
+//#include "kdatepicker.h"
+#include "kdialog.h"
+
+#include "kdatewidget.h"
+
+class KDateWidgetSpinBox : public QSpinBox
+{
+public:
+ KDateWidgetSpinBox(int min, int max, QWidget *parent)
+ : QSpinBox(min, max, 1, parent)
+ {
+ editor()->setAlignment(AlignRight);
+ }
+};
+
+class KDateWidget::KDateWidgetPrivate
+{
+public:
+ KDateWidgetSpinBox *m_day;
+ QComboBox *m_month;
+ KDateWidgetSpinBox *m_year;
+ QDate m_dat;
+};
+
+
+KDateWidget::KDateWidget( QWidget *parent, const char *name )
+ : QWidget( parent, name )
+{
+ init(QDate());
+ setDate(QDate());
+}
+
+// ### HPB change QDate to const QDate & in KDE 4.0
+KDateWidget::KDateWidget( QDate date, QWidget *parent,
+ const char *name )
+ : QWidget( parent, name )
+{
+ init(date);
+ setDate(date);
+}
+
+// ### CFM Repaced by init(const QDate&). Can be safely removed
+// when no risk of BIC
+void KDateWidget::init()
+{
+ d = new KDateWidgetPrivate;
+ KLocale *locale = KGlobal::locale();
+ QHBoxLayout *layout = new QHBoxLayout(this, 0, KDialog::spacingHint());
+ layout->setAutoAdd(true);
+ d->m_day = new KDateWidgetSpinBox(1, 1, this);
+ d->m_month = new QComboBox(false, this);
+ for (int i = 1; ; ++i)
+ {
+ QString str = locale->calendar()->monthName(i,
+ locale->calendar()->year(QDate()));
+ if (str.isNull()) break;
+ d->m_month->insertItem(str);
+ }
+
+ d->m_year = new KDateWidgetSpinBox(locale->calendar()->minValidYear(),
+ locale->calendar()->maxValidYear(), this);
+
+ connect(d->m_day, SIGNAL(valueChanged(int)), this, SLOT(slotDateChanged()));
+ connect(d->m_month, SIGNAL(activated(int)), this, SLOT(slotDateChanged()));
+ connect(d->m_year, SIGNAL(valueChanged(int)), this, SLOT(slotDateChanged()));
+}
+
+void KDateWidget::init(const QDate& date)
+{
+ d = new KDateWidgetPrivate;
+ KLocale *locale = KGlobal::locale();
+ QHBoxLayout *layout = new QHBoxLayout(this, 0, KDialog::spacingHint());
+ layout->setAutoAdd(true);
+ d->m_day = new KDateWidgetSpinBox(1, 1, this);
+ d->m_month = new QComboBox(false, this);
+ for (int i = 1; ; ++i)
+ {
+ QString str = locale->calendar()->monthName(i,
+ locale->calendar()->year(date));
+ if (str.isNull()) break;
+ d->m_month->insertItem(str);
+ }
+
+ d->m_year = new KDateWidgetSpinBox(locale->calendar()->minValidYear(),
+ locale->calendar()->maxValidYear(), this);
+
+ connect(d->m_day, SIGNAL(valueChanged(int)), this, SLOT(slotDateChanged()));
+ connect(d->m_month, SIGNAL(activated(int)), this, SLOT(slotDateChanged()));
+ connect(d->m_year, SIGNAL(valueChanged(int)), this, SLOT(slotDateChanged()));
+}
+
+KDateWidget::~KDateWidget()
+{
+ delete d;
+}
+
+// ### HPB change QDate to const QDate & in KDE 4.0
+void KDateWidget::setDate( QDate date )
+{
+ const KCalendarSystem * calendar = KGlobal::locale()->calendar();
+
+ d->m_day->blockSignals(true);
+ d->m_month->blockSignals(true);
+ d->m_year->blockSignals(true);
+
+ d->m_day->setMaxValue(calendar->daysInMonth(date));
+ d->m_day->setValue(calendar->day(date));
+ d->m_month->setCurrentItem(calendar->month(date)-1);
+ d->m_year->setValue(calendar->year(date));
+
+ d->m_day->blockSignals(false);
+ d->m_month->blockSignals(false);
+ d->m_year->blockSignals(false);
+
+ d->m_dat = date;
+ emit changed(d->m_dat);
+}
+
+QDate KDateWidget::date() const
+{
+ return d->m_dat;
+}
+
+void KDateWidget::slotDateChanged( )
+{
+ const KCalendarSystem * calendar = KGlobal::locale()->calendar();
+
+ QDate date;
+ int y,m,day;
+
+ y = d->m_year->value();
+ y = QMIN(QMAX(y, calendar->minValidYear()), calendar->maxValidYear());
+
+ calendar->setYMD(date, y, 1, 1);
+ m = d->m_month->currentItem()+1;
+ m = QMIN(QMAX(m,1), calendar->monthsInYear(date));
+
+ calendar->setYMD(date, y, m, 1);
+ day = d->m_day->value();
+ day = QMIN(QMAX(day,1), calendar->daysInMonth(date));
+
+ calendar->setYMD(date, y, m, day);
+ setDate(date);
+}
+
+void KDateWidget::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "kdatewidget.moc"
diff --git a/kdeui/kdatewidget.h b/kdeui/kdatewidget.h
new file mode 100644
index 000000000..a89bbe6d1
--- /dev/null
+++ b/kdeui/kdatewidget.h
@@ -0,0 +1,90 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2001 Waldo Bastian (bastian@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __KDATECTL_H__
+#define __KDATECTL_H__
+
+#include <qwidget.h>
+#include <qdatetime.h>
+
+#include <kdelibs_export.h>
+
+/**
+* @short A pushbutton to display or allow user selection of a date.
+*
+* This widget can be used to display or allow user selection of a date.
+*
+* @see KDatePicker
+*
+* @version $Id$
+*/
+class KDEUI_EXPORT KDateWidget : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY( QDate date READ date WRITE setDate )
+
+public:
+ /**
+ * Constructs a date selection widget.
+ */
+ KDateWidget( QWidget *parent=0, const char *name=0 );
+
+ /**
+ * Constructs a date selection widget with the initial date set to @p date.
+ */
+ KDateWidget( QDate date, QWidget *parent=0, const char *name=0 );
+
+ /**
+ * Destructs the date selection widget.
+ */
+ virtual ~KDateWidget();
+
+ /**
+ * Returns the currently selected date.
+ */
+ QDate date() const;
+
+ /**
+ * Changes the selected date to @p date.
+ */
+ void setDate(QDate date);
+
+
+signals:
+ /**
+ * Emitted whenever the date of the widget
+ * is changed, either with setDate() or via user selection.
+ */
+ void changed(QDate);
+
+protected:
+ void init();
+ void init(const QDate&);
+
+protected slots:
+ void slotDateChanged();
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KDateWidgetPrivate;
+ KDateWidgetPrivate *d;
+};
+
+#endif
+
diff --git a/kdeui/kdcopactionproxy.cpp b/kdeui/kdcopactionproxy.cpp
new file mode 100644
index 000000000..ac1138ab1
--- /dev/null
+++ b/kdeui/kdcopactionproxy.cpp
@@ -0,0 +1,159 @@
+/* This file is part of the KDE project
+ Copyright (C) 1999 Simon Hausmann <hausmann@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kdcopactionproxy.h"
+
+#include <dcopclient.h>
+#include <kapplication.h>
+#include <kaction.h>
+#include <kdebug.h>
+#include <kdcoppropertyproxy.h>
+
+#include <ctype.h>
+
+class KDCOPActionProxy::KDCOPActionProxyPrivate
+{
+public:
+ KDCOPActionProxyPrivate()
+ {
+ }
+ ~KDCOPActionProxyPrivate()
+ {
+ }
+
+ KActionCollection *m_actionCollection;
+ DCOPObject *m_parent;
+ QCString m_prefix;
+ int m_pos;
+};
+
+KDCOPActionProxy::KDCOPActionProxy( KActionCollection *actionCollection, DCOPObject *parent )
+{
+ init( actionCollection, parent );
+}
+
+KDCOPActionProxy::KDCOPActionProxy( DCOPObject *parent )
+{
+ init( 0, parent );
+}
+
+void KDCOPActionProxy::init( KActionCollection *collection, DCOPObject *parent )
+{
+ d = new KDCOPActionProxyPrivate;
+ d->m_actionCollection = collection;
+ d->m_parent = parent;
+ d->m_prefix = parent->objId() + "/action/";
+ d->m_pos = d->m_prefix.length();
+}
+
+KDCOPActionProxy::~KDCOPActionProxy()
+{
+ delete d;
+}
+
+QValueList<KAction *>KDCOPActionProxy::actions() const
+{
+ if ( !d->m_actionCollection )
+ return QValueList<KAction *>();
+
+ return d->m_actionCollection->actions();
+}
+
+KAction *KDCOPActionProxy::action( const char *name ) const
+{
+ if ( !d->m_actionCollection )
+ return 0;
+
+ return d->m_actionCollection->action( name );
+}
+
+QCString KDCOPActionProxy::actionObjectId( const QCString &name ) const
+{
+ return d->m_prefix + name;
+}
+
+QMap<QCString,DCOPRef> KDCOPActionProxy::actionMap( const QCString &appId ) const
+{
+ QMap<QCString,DCOPRef> res;
+
+ QCString id = appId;
+ if ( id.isEmpty() )
+ id = kapp->dcopClient()->appId();
+
+ QValueList<KAction *> lst = actions();
+ QValueList<KAction *>::ConstIterator it = lst.begin();
+ QValueList<KAction *>::ConstIterator end = lst.end();
+ for (; it != end; ++it )
+ res.insert( (*it)->name(), DCOPRef( id, actionObjectId( (*it)->name() ) ) );
+
+ return res;
+}
+
+bool KDCOPActionProxy::process( const QCString &obj, const QCString &fun, const QByteArray &data,
+ QCString &replyType, QByteArray &replyData )
+{
+ if ( obj.left( d->m_pos ) != d->m_prefix )
+ return false;
+
+ KAction *act = action( obj.mid( d->m_pos ) );
+ if ( !act )
+ return false;
+
+ return processAction( obj, fun, data, replyType, replyData, act );
+}
+
+bool KDCOPActionProxy::processAction( const QCString &, const QCString &fun, const QByteArray &data,
+ QCString &replyType, QByteArray &replyData, KAction *action )
+{
+ if ( fun == "activate()" )
+ {
+ replyType = "void";
+ action->activate();
+ return true;
+ }
+
+ if ( fun == "isPlugged()" )
+ {
+ replyType = "bool";
+ QDataStream reply( replyData, IO_WriteOnly );
+ reply << (Q_INT8)action->isPlugged();
+ return true;
+ }
+
+ if ( fun == "functions()" )
+ {
+ QValueList<QCString> res;
+ res << "QCStringList functions()";
+ res << "void activate()";
+ res << "bool isPlugged()";
+
+ res += KDCOPPropertyProxy::functions( action );
+
+ replyType = "QCStringList";
+ QDataStream reply( replyData, IO_WriteOnly );
+ reply << res;
+ return true;
+ }
+
+ return KDCOPPropertyProxy::processPropertyRequest( fun, data, replyType, replyData, action );
+}
+
+void KDCOPActionProxy::virtual_hook( int id, void* data )
+{ DCOPObjectProxy::virtual_hook( id, data ); }
+
diff --git a/kdeui/kdcopactionproxy.h b/kdeui/kdcopactionproxy.h
new file mode 100644
index 000000000..48a7ea9a0
--- /dev/null
+++ b/kdeui/kdcopactionproxy.h
@@ -0,0 +1,112 @@
+/* This file is part of the KDE project
+ Copyright (C) 1999 Simon Hausmann <hausmann@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef __kdcopactionproxy_h__
+#define __kdcopactionproxy_h__
+
+#include <dcopobject.h>
+#include <dcopref.h>
+#include <kdelibs_export.h>
+
+class KActionCollection;
+class KAction;
+
+/**
+ * @short A proxy class publishing a DCOP interface for actions.
+ *
+ * The KDCOPActionProxy class provides an easy way to publish a collection of KAction objects
+ * through DCOP. For the DCOP client the exported actions behave like full-fledged DCOP objects,
+ * providing full access to the KAction object functionality in the server.
+ *
+ * This class can generate DCOP object ids for given action objects, which it automatically
+ * processes, as being a DCOPObjectProxy .
+ */
+class KDEUI_EXPORT KDCOPActionProxy : public DCOPObjectProxy
+{
+public:
+ /**
+ * Constructs a dcop action proxy, being able to export the actions of the provided
+ * KActionCollection through DCOP, using the parent DCOPObject's object id to
+ * generate unique object ids for the actions.
+ */
+ KDCOPActionProxy( KActionCollection *actionCollection, DCOPObject *parent );
+ /**
+ * Use this constructor if do not want to provide the exportable actions through a
+ * KActionCollection . You have to reimplement the virtual actions() and
+ * action() methods if you use this constructor.
+ */
+ KDCOPActionProxy( DCOPObject *parent );
+ /**
+ * Destructor.
+ */
+ ~KDCOPActionProxy();
+
+ /**
+ * Returns a list of exportable actions. The default implementation returns a list of actions
+ * provided by a KActionCollection, if the first constructor has been used.
+ */
+ virtual QValueList<KAction *> actions() const;
+ /**
+ * Returns an action object with the given name. The default implementation queries the action object
+ * from the KActionCollection, if the first constructor has been used.
+ */
+ virtual KAction *action( const char *name ) const;
+
+ /**
+ * Use this method to retrieve a DCOP object id for an action with the given name.
+ * This class automatically takes care of processing DCOP object requests for the returned
+ * object id.
+ *
+ * You can construct a global DCOP object referenence using DCOPRef. For example like
+ * DCOPRef( kapp->dcopClient()->appId, actionProxy->actionObjectId( actionName ) );
+ *
+ * The action with the given name has to be available through the #action method.
+ */
+ virtual QCString actionObjectId( const QCString &name ) const;
+
+ /**
+ * Returns a map of all exported actions, with the action name as keys and a global DCOP reference
+ * as data entries.
+ * The appId argument is used to specify the appid component of the DCOP reference. By default the
+ * global application id is used ( kapp->dcopClient()->appId() ) .
+ */
+ virtual QMap<QCString,DCOPRef> actionMap( const QCString &appId = QCString() ) const;
+
+ /**
+ * Internal reimplementation of DCOPObjectProxy::process .
+ */
+ virtual bool process( const QCString &obj, const QCString &fun, const QByteArray &data,
+ QCString &replyType, QByteArray &replyData );
+
+ /**
+ * Called by the #process method and takes care of processing the object request for an
+ * action object.
+ */
+ virtual bool processAction( const QCString &obj, const QCString &fun, const QByteArray &data,
+ QCString &replyType, QByteArray &replyData, KAction *action );
+private:
+ void init( KActionCollection *collection, DCOPObject *parent );
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KDCOPActionProxyPrivate;
+ KDCOPActionProxyPrivate *d;
+};
+
+#endif
diff --git a/kdeui/kdepackages.h b/kdeui/kdepackages.h
new file mode 100644
index 000000000..f1d7ac284
--- /dev/null
+++ b/kdeui/kdepackages.h
@@ -0,0 +1,1301 @@
+// DO NOT EDIT - EDIT bugs/Maintainers instead
+const char * const packages[] = {
+"Akonadi",
+"Akonadi/libakonadi",
+"Akonadi/server",
+"HIG",
+"KCall",
+"KDE-Eclipse",
+"KExtProcess",
+"KExtProcess/Main Library",
+"KExtProcess/Profile API and GUI",
+"KExtProcess/Protocol Support",
+"KSquares",
+"KSystemLog",
+"Keyboard status applet",
+"Khalkhi",
+"Khalkhi/kicker applet",
+"Oxygen",
+"Oxygen/icons",
+"Oxygen/sound",
+"Oxygen/style",
+"Oxygen/win deco",
+"Phonon",
+"Phonon/KDE platform plugin",
+"Phonon/NMM backend",
+"Phonon/audio device listing",
+"Phonon/avKode Backend",
+"Phonon/frontend",
+"Phonon/settings",
+"Phonon/xine backend",
+"Skanlite",
+"abakus",
+"adept",
+"akodelib",
+"akregator",
+"akregator/akregator konqueror plugin",
+"akregator/feed parser",
+"akregator/internal browser",
+"akregator/kontact plugin",
+"akregator/metakit plugin",
+"aktion",
+"amarok",
+"amarok/AFT",
+"amarok/Collection",
+"amarok/CollectionBrowser",
+"amarok/ContextView",
+"amarok/DAAP",
+"amarok/Engines",
+"amarok/FileBrowser",
+"amarok/Mediabrowser",
+"amarok/OSD",
+"amarok/Playlist",
+"amarok/PlaylistBrowser",
+"amarok/Podcast",
+"amarok/ServiceBrowser",
+"amarok/scripts",
+"amor",
+"ark",
+"ark/Konqueror Plugin",
+"arts",
+"arts/artsbuilder",
+"arts/artscontrol",
+"arts/artsd",
+"arts/kcmarts",
+"arts/knotify",
+"arts/libartskde",
+"arts/xine_artsplugin",
+"artwork",
+"atlantik",
+"atlantik/monopd",
+"atlantikdesigner",
+"basket",
+"binaries",
+"binaries/cygwin",
+"binaries/dpkg",
+"binaries/pkgs",
+"binaries/rpms",
+"bindings",
+"blinken",
+"boson",
+"boson/Editor",
+"boson/Graphics",
+"boson/Packages",
+"bovo",
+"brahms",
+"bugs.kde.org",
+"buildsystem",
+"buildsystem/KDE3 (autotools)",
+"buildsystem/KDE4 (cmake)",
+"cdbakeoven",
+"cervisia",
+"configure",
+"daap ioslave",
+"daap ioslave/daap ioslave",
+"daap ioslave/daap library",
+"datakiosk",
+"dcop",
+"dcop/dcopserver",
+"dcop/kdcop",
+"decibel",
+"digikam",
+"digikam/Albums GUI",
+"digikam/Camera GUI",
+"digikam/Color Management",
+"digikam/Database",
+"digikam/Dates",
+"digikam/Export",
+"digikam/Filter",
+"digikam/Fuzzy Searches",
+"digikam/Geolocation",
+"digikam/Image Editor",
+"digikam/Import",
+"digikam/Kipiinterface",
+"digikam/Light Table",
+"digikam/Map Searches",
+"digikam/Metadata",
+"digikam/Portability",
+"digikam/Preview",
+"digikam/RAW files management",
+"digikam/Searches",
+"digikam/SlideShow",
+"digikam/Tags",
+"digikam/Themes",
+"digikam/Thumbnails",
+"digikam/Time Line",
+"digikam/Usability",
+"digikam/Workflow",
+"digikam/setup",
+"digikamimageplugins",
+"digikamimageplugins/Adjust Curves",
+"digikamimageplugins/AdjustLevels",
+"digikamimageplugins/Anti-Vignetting",
+"digikamimageplugins/BlowUp",
+"digikamimageplugins/Blur Fx",
+"digikamimageplugins/Border",
+"digikamimageplugins/Channel Mixer",
+"digikamimageplugins/Charcoal",
+"digikamimageplugins/ColorFx",
+"digikamimageplugins/Core Plugin",
+"digikamimageplugins/Distortion Fx",
+"digikamimageplugins/Emboss",
+"digikamimageplugins/Filmgrain",
+"digikamimageplugins/Free Rotation",
+"digikamimageplugins/Hot Pixels",
+"digikamimageplugins/Infrared",
+"digikamimageplugins/Inpainting",
+"digikamimageplugins/Insert Text",
+"digikamimageplugins/Lens Distortion",
+"digikamimageplugins/Noise Reduction",
+"digikamimageplugins/OilPaint",
+"digikamimageplugins/Perspective",
+"digikamimageplugins/Raindrops",
+"digikamimageplugins/Refocus",
+"digikamimageplugins/Restoration",
+"digikamimageplugins/Shear",
+"digikamimageplugins/Super-Impose",
+"digikamimageplugins/Texture",
+"digikamimageplugins/Unsharp",
+"digikamimageplugins/White Balance",
+"digikamimageplugins/Wish for new plugin",
+"docs",
+"docs/Corrections",
+"docs/Missing Content",
+"docs/Screenshots",
+"docs/docs.kde.org",
+"docs/faq",
+"docs/ksgmltools",
+"dolphin",
+"dragonplayer",
+"drkonqi",
+"filelight",
+"flashkard",
+"geheimnis",
+"gofai",
+"guidance-power-manager",
+"guidance",
+"gwenview",
+"i18n",
+"i18n/af",
+"i18n/bg",
+"i18n/br",
+"i18n/ca",
+"i18n/cs",
+"i18n/cy",
+"i18n/da",
+"i18n/de",
+"i18n/el",
+"i18n/en_GB",
+"i18n/eo",
+"i18n/es",
+"i18n/et",
+"i18n/eu",
+"i18n/fi",
+"i18n/fr",
+"i18n/ga",
+"i18n/gl",
+"i18n/gu",
+"i18n/he",
+"i18n/hr",
+"i18n/hu",
+"i18n/is",
+"i18n/it",
+"i18n/ja",
+"i18n/ko",
+"i18n/lt",
+"i18n/lv",
+"i18n/mk",
+"i18n/nb",
+"i18n/nl",
+"i18n/nn",
+"i18n/oc",
+"i18n/pl",
+"i18n/pt",
+"i18n/pt-BR",
+"i18n/ro",
+"i18n/ru",
+"i18n/sk",
+"i18n/sl",
+"i18n/sr",
+"i18n/sv",
+"i18n/ta",
+"i18n/th",
+"i18n/tr",
+"i18n/uk",
+"i18n/wa",
+"i18n/zh-CN.GB2312",
+"i18n/zh-TW.Big5",
+"indexlib",
+"juk",
+"k3b",
+"k3b/Audio Project",
+"k3b/Burning/Hardware",
+"k3b/Copying",
+"k3b/Data Project",
+"k3b/GUI/Usability",
+"k3b/Image Formats",
+"k3b/Mixed Mode Project",
+"k3b/Plugins",
+"k3b/Verfication",
+"k3b/Video CD project",
+"k3b/Video DVD",
+"k3b/eMovix project",
+"kab",
+"kaboodle",
+"kaboodle/icons",
+"kaddressbook",
+"kaddressbook/ldap",
+"kaffeine",
+"kafka",
+"kalamaris",
+"kalarm",
+"kalarm/kalarmd",
+"kalcul",
+"kalgebra",
+"kallery",
+"kallery/kallery",
+"kalzium",
+"kalzium/Calculator",
+"kamefu",
+"kanagram",
+"kandy",
+"kappfinder",
+"kapptemplate",
+"karbon",
+"karbon/opendocument",
+"karbon/usability",
+"karchie",
+"karchiver",
+"kard",
+"kasbar",
+"kasteroids",
+"kat",
+"katalog",
+"katapult",
+"kate",
+"kate/application",
+"kate/folding",
+"kate/indentation",
+"kate/kwrite",
+"kate/part",
+"kate/syntax",
+"katomic",
+"kaudiocreator",
+"kbabel",
+"kbabel/CatalogManager",
+"kbabel/KBabel editor",
+"kbabel/KBabelDict",
+"kbabel/db search engine",
+"kbackgammon",
+"kbattleship",
+"kbear",
+"kbfx",
+"kbiff",
+"kblackbox",
+"kblocks",
+"kbounce",
+"kbreakout",
+"kbruch",
+"kbugbuster",
+"kcachegrind",
+"kcalc",
+"kcanvas",
+"kcharselect",
+"kchart",
+"kchart/opendocument",
+"kchart/usability",
+"kchat",
+"kcoloredit",
+"kconfigeditor",
+"kconfigure",
+"kcontrol",
+"kcontrol/kcmaccess",
+"kcontrol/kcmaccessibility",
+"kcontrol/kcmaudiocd",
+"kcontrol/kcmbackground",
+"kcontrol/kcmbell",
+"kcontrol/kcmclock",
+"kcontrol/kcmcolors",
+"kcontrol/kcmcomponentchooser",
+"kcontrol/kcmcrypto",
+"kcontrol/kcmdisplay",
+"kcontrol/kcmdisplayconfig",
+"kcontrol/kcmemail",
+"kcontrol/kcmenergy",
+"kcontrol/kcmfiletypes",
+"kcontrol/kcmfontinst",
+"kcontrol/kcmfonts",
+"kcontrol/kcmicons",
+"kcontrol/kcminfo",
+"kcontrol/kcminit",
+"kcontrol/kcminput",
+"kcontrol/kcmioslaveinfo",
+"kcontrol/kcmjoystick",
+"kcontrol/kcmkabldapconfig",
+"kcontrol/kcmkded",
+"kcontrol/kcmkdm",
+"kcontrol/kcmkeyboard",
+"kcontrol/kcmkeys",
+"kcontrol/kcmkhotkeys",
+"kcontrol/kcmkmix",
+"kcontrol/kcmknotify",
+"kcontrol/kcmkonq",
+"kcontrol/kcmkonqhtml",
+"kcontrol/kcmkresources",
+"kcontrol/kcmksplash",
+"kcontrol/kcmkurifilt",
+"kcontrol/kcmkvaio",
+"kcontrol/kcmkwindecoration",
+"kcontrol/kcmkwinoptions",
+"kcontrol/kcmlanbrowser",
+"kcontrol/kcmlaptop",
+"kcontrol/kcmlilo",
+"kcontrol/kcmlinuz",
+"kcontrol/kcmlocale",
+"kcontrol/kcmmidi",
+"kcontrol/kcmmouse",
+"kcontrol/kcmpanel",
+"kcontrol/kcmpasswords",
+"kcontrol/kcmperformance",
+"kcontrol/kcmprintmgr",
+"kcontrol/kcmprivacy",
+"kcontrol/kcmproxy",
+"kcontrol/kcmsamba",
+"kcontrol/kcmscreensaver",
+"kcontrol/kcmshell",
+"kcontrol/kcmsmserver",
+"kcontrol/kcmspellchecking",
+"kcontrol/kcmstyle",
+"kcontrol/kcmtaskbar",
+"kcontrol/kcmthinkpad",
+"kcontrol/kcmuseraccount",
+"kcontrol/kcmuseragent",
+"kcontrol/kcmuserinfo",
+"kcontrol/krdb",
+"kcontrol/kthememanager",
+"kcontrol/kthememgr",
+"kcpuload",
+"kcron",
+"kdat",
+"kde-bluetooth",
+"kde-bluetooth/kbemusedsrv",
+"kde-bluetooth/kbluelock",
+"kde-bluetooth/kbluemon",
+"kde-bluetooth/kbluetoothd",
+"kde-bluetooth/kbthandsfree",
+"kde-bluetooth/kbtobexclient",
+"kde-bluetooth/kbtobexsrv",
+"kde-bluetooth/kbtserialchat",
+"kde-bluetooth/khciconfig",
+"kde-bluetooth/kinputwizard",
+"kde-bluetooth/kio_bluetooth",
+"kde-bluetooth/kio_obex",
+"kde-bluetooth/kio_sdp",
+"kde-windows",
+"kde-windows/buildsystem",
+"kde-windows/gui",
+"kde-windows/installer",
+"kde-windows/network&amp;files",
+"kde-windows/other",
+"kde",
+"kde/clipboard",
+"kde/dualhead",
+"kde/xinerama",
+"kdeaddons",
+"kdeaddons/dirfilter-plugin",
+"kdeaddons/kate-cppsymbolviewer",
+"kdeaddons/kate-filelistloader",
+"kdeaddons/kate-filetemplates",
+"kdeaddons/kate-insertcommand",
+"kdeaddons/kate-xmltools",
+"kdeaddons/khtmlsettings-plugin",
+"kdeaddons/useragent-plugin",
+"kdebugdialog",
+"kdelibs",
+"kdelibs/kbugreport",
+"kdelibs/kcertpart",
+"kdelibs/kdecore",
+"kdelibs/kded",
+"kdelibs/kdeinit",
+"kdelibs/kdesasl",
+"kdelibs/kdeui",
+"kdelibs/kedittoolbar",
+"kdelibs/kimgio",
+"kdelibs/klauncher",
+"kdelibs/klocale",
+"kdelibs/kmdi",
+"kdelibs/knetwork",
+"kdelibs/knewstuff",
+"kdelibs/knotify",
+"kdelibs/kspell",
+"kdelibs/kstyle",
+"kdelibs/ksycoca",
+"kdelibs/kwallet",
+"kdelibs/qt",
+"kdelirc",
+"kdelirc/irkick",
+"kdelirc/kcmlirc",
+"kdemultimedia",
+"kdepasswd",
+"kdepimlibs",
+"kdepimlibs/gpgme++",
+"kdepimlibs/kabc",
+"kdepimlibs/kblog",
+"kdepimlibs/kcal",
+"kdepimlibs/kldap",
+"kdepimlibs/kmime",
+"kdepimlibs/kpimidentities",
+"kdepimlibs/mailtransport",
+"kdepimlibs/qgpgme",
+"kdepimlibs/syndication",
+"kdeprint",
+"kdeprint/kdeprintfax",
+"kdeprint/kjobviewer",
+"kdesdk-scripts",
+"kdesdk-scripts/Miscellaneous",
+"kdesdk-scripts/cmake",
+"kdesdk-scripts/source_control",
+"kdesktop",
+"kdesktop/icons",
+"kdesktop/minicli",
+"kdesktop/wallpaper",
+"kdessh",
+"kdesu",
+"kdesu/kdesu",
+"kdesu/kdesud",
+"kdesvn-build",
+"kdetv",
+"kdevelop",
+"kdevelop/Appwizard Templates",
+"kdevelop/Build tools: ANT",
+"kdevelop/Build tools: Automake",
+"kdevelop/Build tools: Custom Makefiles",
+"kdevelop/Build tools: QMake",
+"kdevelop/Buildtools: Make",
+"kdevelop/CPP Debugger",
+"kdevelop/CTags",
+"kdevelop/Language Support: Ada",
+"kdevelop/Language Support: CPP",
+"kdevelop/Language Support: Java",
+"kdevelop/Language Support: PHP",
+"kdevelop/Language Support: Pascal",
+"kdevelop/Language Support: Perl",
+"kdevelop/Language Support: Python",
+"kdevelop/Language Support: Ruby",
+"kdevelop/Output Views",
+"kdevelop/Profiles",
+"kdevelop/Qt Designer Integration",
+"kdevelop/UI: IDEAl",
+"kdevelop/UI: all modes",
+"kdevelop/UI: childframe window",
+"kdevelop/UI: tabbed pages",
+"kdevelop/UI: toplevel window",
+"kdevelop/VCS: CVS",
+"kdevelop/VCS: CVSService",
+"kdevelop/VCS: Clearcase",
+"kdevelop/VCS: Perforce",
+"kdevelop/VCS: SVN",
+"kdevelop/abbreviation plugin",
+"kdevelop/all build tools",
+"kdevelop/all editors",
+"kdevelop/appwizard",
+"kdevelop/astyle",
+"kdevelop/bookmarks part",
+"kdevelop/classview",
+"kdevelop/code completion",
+"kdevelop/cpp-parser",
+"kdevelop/distpart",
+"kdevelop/doctreeview",
+"kdevelop/documentation viewer",
+"kdevelop/doxygen integration",
+"kdevelop/file create",
+"kdevelop/file groups",
+"kdevelop/file selector",
+"kdevelop/file tree",
+"kdevelop/grep frontend",
+"kdevelop/kate integration",
+"kdevelop/kdevelop 2.x (obsolete)",
+"kdevelop/konsole part",
+"kdevelop/partexplorer",
+"kdevelop/php support",
+"kdevelop/problem reporter",
+"kdevelop/qeditor",
+"kdevelop/replace part",
+"kdevelop/scriptproject",
+"kdevelop/valgrind integration",
+"kdevplatform",
+"kdevplatform/classbrowser",
+"kdevplatform/contextbrowser",
+"kdevplatform/filemanager",
+"kdevplatform/konsole integration",
+"kdevplatform/language",
+"kdevplatform/outputview",
+"kdevplatform/problemreporter",
+"kdevplatform/project",
+"kdevplatform/quickopen",
+"kdevplatform/run support",
+"kdevplatform/shell",
+"kdevplatform/snippet",
+"kdevplatform/sublime",
+"kdevplatform/subversion",
+"kdevplatform/util",
+"kdevplatform/vcs",
+"kdevplatform/veritas",
+"kdf",
+"kdialog",
+"kdiamond",
+"kdict",
+"kdiff3",
+"kdiff3/KDiff3Part",
+"kdm",
+"kdm/kdmdesktop",
+"kdm/krootimage",
+"kdoc",
+"kdom",
+"kdvi",
+"kedit",
+"keditbookmarks",
+"keduca",
+"keep",
+"kenolaba",
+"kepas",
+"kerry",
+"kexi",
+"kexi/Forms Designer",
+"kexi/General",
+"kexi/KexiDB",
+"kexi/Migration/Import/Export",
+"kexi/Query Designer",
+"kexi/Reports and Printouts",
+"kexi/Scripting",
+"kexi/Table Designer",
+"kexi/Usability",
+"keystone",
+"kfax",
+"kfile-plugins",
+"kfile-plugins/OOo",
+"kfile-plugins/PNG",
+"kfile-plugins/avi",
+"kfile-plugins/exr",
+"kfile-plugins/jpeg",
+"kfile-plugins/mp3",
+"kfile-plugins/mpeg",
+"kfile-plugins/ogg",
+"kfile-plugins/pdf",
+"kfile-plugins/ps",
+"kfile-plugins/wav",
+"kfile",
+"kfile/kfileplacesview",
+"kfilereplace",
+"kfind",
+"kfinger",
+"kfloppy",
+"kformula",
+"kformula/filters",
+"kformula/usability",
+"kfortune",
+"kfouleggs",
+"kfourinline",
+"kftpgrabber",
+"kgeo",
+"kgeography",
+"kget",
+"kget/Core",
+"kget/Multisegkio",
+"kget/UI",
+"kget/konqextension",
+"kget/metalink",
+"kget/plasmoid",
+"kget/torrent",
+"kget/webinterface",
+"kghostview",
+"kghostview/Ghostscript",
+"kgoldrunner",
+"kgoodstuff",
+"kgpg",
+"kgrab",
+"kgraphviewer",
+"khangman",
+"khelpcenter",
+"khexedit",
+"khexedit2",
+"khexedit2/KPart",
+"khexedit2/Standalone application",
+"khexedit2/designer plugin",
+"khexedit2/interface",
+"khexedit2/library",
+"khotkeys",
+"khotkeys/Voice recognition",
+"kicker",
+"kicker/Drag &apos;n Drop",
+"kicker/Panel Strut Management",
+"kicker/appletproxy",
+"kicker/devicesapplet",
+"kicker/dockbar",
+"kicker/kbinaryclock",
+"kicker/kclockapplet",
+"kicker/mediaapplet",
+"kicker/minipagerapplet",
+"kicker/multiscreen",
+"kicker/naughtyapplet",
+"kicker/quicklauncher",
+"kicker/sidebar",
+"kicker/systemtray",
+"kicker/taskbarapplet",
+"kicker/transparency",
+"kicker/trashapplet",
+"kiconedit",
+"kig",
+"kile",
+"kile/editor",
+"kile/user interface",
+"kim",
+"kimagemapeditor",
+"kimdaba",
+"kinkatta",
+"kio",
+"kio/audiocd",
+"kio/cgi",
+"kio/devices",
+"kio/file",
+"kio/fish",
+"kio/floppy",
+"kio/ftp",
+"kio/gopher",
+"kio/help",
+"kio/home",
+"kio/http",
+"kio/imap",
+"kio/info",
+"kio/kamera",
+"kio/kfile",
+"kio/kioslave",
+"kio/kssl",
+"kio/man",
+"kio/media",
+"kio/nfs",
+"kio/nntp",
+"kio/pop3",
+"kio/remote",
+"kio/settings",
+"kio/sftp",
+"kio/sieve",
+"kio/smb",
+"kio/smbro",
+"kio/smtp",
+"kio/svn",
+"kio/system",
+"kio/tar",
+"kio/thumbnail",
+"kio/trash",
+"kio/uiserver",
+"kio/webdav",
+"kio/zeroconf",
+"kio/zip",
+"kiosk",
+"kiosk/kiosktool",
+"kipiplugins",
+"kipiplugins/GPSSync",
+"kipiplugins/HTMLExport",
+"kipiplugins/IpodExport",
+"kipiplugins/Wish For New Plugins",
+"kipiplugins/acquireimages",
+"kipiplugins/batchprocessimages",
+"kipiplugins/calendar",
+"kipiplugins/cdarchiving",
+"kipiplugins/findimages",
+"kipiplugins/flickrexport",
+"kipiplugins/galleryexport",
+"kipiplugins/imageviewer",
+"kipiplugins/jpeglossless",
+"kipiplugins/kameraklient",
+"kipiplugins/libkdcraw",
+"kipiplugins/libkexiv2",
+"kipiplugins/libkipi",
+"kipiplugins/metadataedit",
+"kipiplugins/mpegencoder",
+"kipiplugins/picasawebexport",
+"kipiplugins/printwizard",
+"kipiplugins/rawconverter",
+"kipiplugins/sendimages",
+"kipiplugins/simpleviewerexport",
+"kipiplugins/slideshow",
+"kipiplugins/timeadjust",
+"kipiplugins/wallpaper",
+"kiriki",
+"kit",
+"kit/icons",
+"kitchensync",
+"kiten",
+"kivio",
+"kivio/usability",
+"kjots",
+"kjsembed",
+"kjsembed/Core",
+"kjsembed/Docs and examples",
+"kjsembed/Plugins",
+"kjukebox",
+"kjumpingcube",
+"klaptopdaemon",
+"klatin",
+"klegacyimport",
+"kleopatra",
+"kleopatra/Assuan UI Server",
+"kless",
+"klettres",
+"klickety",
+"klines",
+"klinkstatus",
+"klipper",
+"klyx",
+"kmag",
+"kmago",
+"kmahjongg",
+"kmail",
+"kmail/GUI",
+"kmail/IMAP",
+"kmail/MDN",
+"kmail/addressbook",
+"kmail/calender",
+"kmail/composer",
+"kmail/config compatibility",
+"kmail/disconnected IMAP",
+"kmail/encryption",
+"kmail/filtering",
+"kmail/folder list",
+"kmail/index",
+"kmail/keys and menus",
+"kmail/kmailcvt",
+"kmail/maildir",
+"kmail/mbox",
+"kmail/message list",
+"kmail/messageviewer",
+"kmail/mime",
+"kmail/pop3",
+"kmail/search",
+"kmail/sending",
+"kmail/templates",
+"kmameleon",
+"kmameleon/interface",
+"kmameleon/tools",
+"kmapnotify",
+"kmenuedit",
+"kmerlin",
+"kmessedwords",
+"kmid",
+"kmidi",
+"kmilo",
+"kmilo/Asus",
+"kmilo/Dell i8k",
+"kmilo/Generic MM module",
+"kmilo/Powerbook2 module",
+"kmilo/Thinkpad",
+"kmilo/vaio",
+"kmines",
+"kmix",
+"kmix/KMix Panel Applet",
+"kmix/KMix Panel Docking",
+"kmix/Soundcard specific",
+"kmldonkey",
+"kmldonkey/libkmldonkey",
+"kmobiletools",
+"kmobiletools/AT Engine",
+"kmobiletools/Gammu Engine",
+"kmoon",
+"kmousetool",
+"kmouth",
+"kmplayer",
+"kmplot",
+"kmrml",
+"kmtrace",
+"kmymoney2",
+"knapster2",
+"knemo",
+"knetattach",
+"knetload",
+"knetload/Linux Statistics",
+"knetwalk",
+"knetworkconf",
+"knetworkmanager",
+"knetworkmanager/802.1x",
+"knetworkmanager/cellular",
+"knetworkmanager/openvpn",
+"knetworkmanager/ppp",
+"knetworkmanager/pptp",
+"knetworkmanager/vpnc",
+"knetworkmanager/wep",
+"knetworkmanager/wpa-eap",
+"knetworkmanager/wpa-psk",
+"knewmail",
+"knewsticker",
+"knode",
+"knorskverbs",
+"knotes",
+"knu",
+"kodo",
+"koffice",
+"koffice/filters",
+"koffice/usability",
+"kolf",
+"kollision",
+"kolourpaint",
+"kolourpaint/general-kde4",
+"kolourpaint/imagelib",
+"kolourpaint/ui",
+"kolourpaint/ui-kde4",
+"kommander",
+"kommander/Kommander editor",
+"kommander/Kommander executor",
+"kompare",
+"kompare/navigationpart",
+"kompare/parser",
+"kompare/viewpart",
+"koncd",
+"konqueror",
+"konqueror/New Plugin wishes",
+"konqueror/bookmarks",
+"konqueror/file icon view",
+"konqueror/file list view",
+"konqueror/fsview",
+"konqueror/imagerotation",
+"konqueror/kcookiejar",
+"konqueror/khtml adblock",
+"konqueror/khtml ecma",
+"konqueror/khtml event",
+"konqueror/khtml forms",
+"konqueror/khtml image part",
+"konqueror/khtml parsing",
+"konqueror/khtml part",
+"konqueror/khtml printing",
+"konqueror/khtml renderer",
+"konqueror/khtml xml",
+"konqueror/khtml",
+"konqueror/kimgalleryplugin",
+"konqueror/kjava",
+"konqueror/kjs",
+"konqueror/konq-e",
+"konqueror/kuick",
+"konqueror/nsplugins",
+"konqueror/nspluginscan",
+"konqueror/nspluginviewer",
+"konqueror/photobook",
+"konqueror/reaktivate",
+"konqueror/rellinks",
+"konqueror/searchbarplugin",
+"konqueror/servicemenus",
+"konqueror/sidebar media player",
+"konqueror/sidebar newsticker",
+"konqueror/sidebar",
+"konqueror/tabbing",
+"konqueror/webarchiverplugin",
+"konquest",
+"konsole",
+"konsole/kwrited",
+"konsolekalendar",
+"konstruct",
+"kontact",
+"kontact/akregator",
+"kontact/calendar",
+"kontact/contacts",
+"kontact/journal",
+"kontact/ktimetracker",
+"kontact/mail",
+"kontact/new plugin wishes",
+"kontact/news",
+"kontact/newsticker",
+"kontact/notes",
+"kontact/special dates",
+"kontact/summary",
+"kontact/todo",
+"kontour",
+"kontour/filters",
+"konversation",
+"konversation/ircview",
+"konversation/protocol",
+"kooka",
+"kooka/libkscan",
+"kopennap",
+"kopete",
+"kopete/Add Contact Wizard",
+"kopete/Addressbook integration",
+"kopete/Alias Plugin",
+"kopete/Audio/Video Plugin",
+"kopete/Auto-Away Plugin",
+"kopete/Autoreplace plugin",
+"kopete/Bonjour Plugin",
+"kopete/Bookmarks plugin",
+"kopete/Chat Window",
+"kopete/Chatwindow Styles",
+"kopete/Connection Status Plugin",
+"kopete/Contact Notes Plugin",
+"kopete/Contact list",
+"kopete/Cryptography Plugin",
+"kopete/DBus",
+"kopete/DCOP Interface",
+"kopete/Gadu-Gadu Plugin",
+"kopete/History Plugin",
+"kopete/ICQ and AIM Plugins",
+"kopete/IRC Plugin",
+"kopete/Importer plugin",
+"kopete/Jabber Plugin",
+"kopete/Latex Plugin",
+"kopete/Lotus Sametime Plugin",
+"kopete/MSN Plugin",
+"kopete/Main Application",
+"kopete/Meanwhile plugin",
+"kopete/New plugin wishes",
+"kopete/Notifications",
+"kopete/Novell GroupWise Messenger Plugin",
+"kopete/Now Listening Plugin",
+"kopete/Privacy Plugin",
+"kopete/SMS Plugin",
+"kopete/SpellCheck Plugin",
+"kopete/Statistics plugin",
+"kopete/Testbed Plugin",
+"kopete/Texteffect Plugin",
+"kopete/Translator Plugin",
+"kopete/Web Presence Plugin",
+"kopete/WinPopup Plugin",
+"kopete/Yahoo Plugin",
+"kopete/libkopete",
+"korganizer",
+"korganizer/embedded",
+"korganizer/exchangeplugin",
+"korganizer/groupware",
+"korganizer/korgac",
+"korn",
+"koshell",
+"koshell/usability",
+"kpackage",
+"kpager",
+"kpaint",
+"kpat",
+"kpdf",
+"kpercentage",
+"kpersonalizer",
+"kpf",
+"kphotoalbum",
+"kphotoalbum/Annotation Dialog",
+"kphotoalbum/Backend",
+"kphotoalbum/Browser",
+"kphotoalbum/Datebar",
+"kphotoalbum/EXIF viewer/search",
+"kphotoalbum/HTML generator",
+"kphotoalbum/Import/Export",
+"kphotoalbum/SQL backend",
+"kphotoalbum/Thumbnail Viewer",
+"kphotoalbum/Viewer",
+"kphotoalbum/XML backend",
+"kpilot",
+"kpilot/Internal editors",
+"kpilot/Memo conduit (KNotes)",
+"kpilot/Other conduits",
+"kpilot/addressbook conduit",
+"kpilot/calendar conduits",
+"kpilot/kpilotDaemon",
+"kplato",
+"kplato/usability",
+"kpm",
+"kpoker",
+"kpovmodeler",
+"kppp",
+"kpresenter",
+"kpresenter/filters",
+"kpresenter/opendocument",
+"kpresenter/usability",
+"kqf",
+"kquick",
+"krandr",
+"krandr/control center",
+"krandr/krandrtray",
+"krdc",
+"kreatecd",
+"krec",
+"krec/mp3_export",
+"krec/ogg_export",
+"krec/wave_export",
+"krecord",
+"kregexpeditor",
+"kresources",
+"kresources/SLOX",
+"kresources/birthdays",
+"kresources/blogging",
+"kresources/bugzilla",
+"kresources/egroupware",
+"kresources/exchange",
+"kresources/featureplan",
+"kresources/framework",
+"kresources/groupdav",
+"kresources/groupwise",
+"kresources/imap",
+"kresources/ldap",
+"kresources/local",
+"kresources/newexchange",
+"kresources/remote",
+"kreversi",
+"krfb",
+"krichtexteditor",
+"krita",
+"krita/Color models",
+"krita/Documentation",
+"krita/File formats",
+"krita/Filters",
+"krita/Tile manager",
+"krita/Tools",
+"krita/adjustment layers",
+"krita/transform",
+"krita/usability",
+"kruler",
+"krunner",
+"krusader",
+"ksame",
+"ksayit",
+"kscd",
+"kscreensaver",
+"kscreensaver/kcheckpass",
+"kscreensaver/kpartsaver",
+"kscreensaver/ktux",
+"kscreensaver/kxsrun",
+"kscreensaver/screensavers",
+"kshisen",
+"ksim",
+"ksirc",
+"ksirk",
+"ksirtet",
+"ksmiletris",
+"ksmserver",
+"ksnake",
+"ksnapshot",
+"ksokoban",
+"kspaceduel",
+"ksplash",
+"kspread",
+"kspread/filters",
+"kspread/opendocument",
+"kspread/usability",
+"kst",
+"kst/datasources",
+"kst/documentation",
+"kst/elog extension",
+"kst/equations",
+"kst/i18n",
+"kst/packaging",
+"kst/plotting",
+"kst/plugins",
+"kst/scripting",
+"kst/ui",
+"kst/view objects",
+"kstars",
+"kstart",
+"kstartperf",
+"ksteak",
+"kstockticker",
+"ksudoku",
+"ksvg",
+"ksvg/Animations",
+"ksvg/JavaScript",
+"ksvg2",
+"ksynaptics",
+"ksynaptics/syndock",
+"ksysctrl",
+"ksysguard",
+"ksysguard/Plasmoid / Applet",
+"ksysguard/Process Controller - krunner part",
+"ksysguard/ksysguard",
+"ksysguard/ksysguardd",
+"ksysv",
+"ktalk",
+"ktalkd",
+"kteatime",
+"ktelnet2",
+"kthesaurus",
+"ktimemon",
+"ktimer",
+"ktimetracker",
+"ktimetracker/reporting",
+"ktip",
+"ktnef",
+"ktop",
+"ktorrent",
+"ktouch",
+"ktron",
+"kttsd",
+"kttsd/festival plugin",
+"kttsd/kcmkttsmgr",
+"kttsd/kttsd",
+"kttsd/kttsmgr",
+"kttt",
+"ktuberling",
+"kturtle",
+"kubrick",
+"kugar",
+"kugar/kudesigner",
+"kugar/usability",
+"kuickshow",
+"kuiviewer",
+"kuser",
+"kverbos",
+"kvidmode",
+"kview",
+"kview/kviewcanvas",
+"kview/kviewviewer",
+"kview/plugins",
+"kviewerpart",
+"kviewshell",
+"kvim",
+"kvim/Vim KPart",
+"kvoctrain",
+"kwalletmanager",
+"kweather",
+"kwebget",
+"kwifimanager",
+"kwikdisk",
+"kwin",
+"kwin/compatibility",
+"kwin/compositing",
+"kwin/decorations",
+"kwin/eyecandy",
+"kwin/multihead",
+"kwin/xinerama",
+"kwin4",
+"kwintv",
+"kwireless",
+"kword",
+"kword/filters",
+"kword/opendocument",
+"kword/tables",
+"kword/usability",
+"kwordquiz",
+"kworldclock",
+"kwuftpd",
+"kxconfig",
+"kxkb",
+"kxmlrpcd",
+"kxsldbg",
+"kxsldbg/kxsldbg",
+"kxsldbg/xsldbg",
+"lanbrowsing",
+"libkcddb",
+"libkdegames",
+"libkdepim",
+"libkdepim/libkpgp",
+"libksane",
+"lilo-config",
+"lokalize",
+"lokalize/editor",
+"lokalize/glossary",
+"lokalize/project management",
+"lokalize/translation memory",
+"lskat",
+"mailody",
+"marble",
+"marble/data",
+"mediacontrol",
+"mediacontrol/amarok support",
+"megami",
+"metabar",
+"mp3kult",
+"mpeglib",
+"nepomuk",
+"noatun",
+"noatun/Young Hickory",
+"noatun/dub",
+"noatun/excellent",
+"noatun/hayes",
+"noatun/htmlexport",
+"noatun/infrared",
+"noatun/kjofol-skin",
+"noatun/metatag",
+"noatun/oblique",
+"noatun/simple",
+"noatun/split",
+"noatun/winskin",
+"okteta",
+"okular",
+"okular/CHM backend",
+"okular/DVI backend",
+"okular/DjVu backend",
+"okular/New backend wishes",
+"okular/ODT backend",
+"okular/PDF backend",
+"okular/PS backend",
+"okular/TIFF backend",
+"parley",
+"pixieplus",
+"plasma",
+"plasma/containment-desktop",
+"plasma/containment-panel",
+"plasma/desktop",
+"plasma/multiscreen",
+"plasma/panel",
+"plasma/widget browser",
+"plasma/widget-battery",
+"plasma/widget-clock",
+"plasma/widget-comic",
+"plasma/widget-fifteenpuzzle",
+"plasma/widget-folderview",
+"plasma/widget-frame",
+"plasma/widget-kickoff",
+"plasma/widget-misc",
+"plasma/widget-notifier",
+"plasma/widget-systemtray",
+"plasma/widget-taskbar",
+"plasma/widget-twitter",
+"printer-applet",
+"qca",
+"quanta",
+"quanta/VPL",
+"rsibreak",
+"sanetracker",
+"showfoto",
+"spreadkde.org",
+"step",
+"step/stepcore",
+"superkaramba",
+"sweeper",
+"systemsettings-kde3",
+"systemsettings",
+"systemsettings/accessibility",
+"systemsettings/autostart",
+"systemsettings/bell",
+"systemsettings/clock",
+"systemsettings/colors",
+"systemsettings/componentchooser",
+"systemsettings/desktoppath",
+"systemsettings/emoticons",
+"systemsettings/energy",
+"systemsettings/fileshare",
+"systemsettings/fontinst",
+"systemsettings/fonts",
+"systemsettings/icons",
+"systemsettings/joystick",
+"systemsettings/kcm_useraccount",
+"systemsettings/kcmkded",
+"systemsettings/kcmkdnssd",
+"systemsettings/kcmknotify",
+"systemsettings/kcmlaunch",
+"systemsettings/kdm",
+"systemsettings/keyboard",
+"systemsettings/keyboard_layout",
+"systemsettings/keys",
+"systemsettings/khotkeys",
+"systemsettings/ksplashthememgr",
+"systemsettings/kthememanager",
+"systemsettings/kwincompositing",
+"systemsettings/kwindecoration",
+"systemsettings/kwinoptions",
+"systemsettings/language",
+"systemsettings/mouse",
+"systemsettings/netpref",
+"systemsettings/proxy",
+"systemsettings/randr",
+"systemsettings/samba",
+"systemsettings/screensaver",
+"systemsettings/sound",
+"systemsettings/style",
+"taglib",
+"umbrello",
+"unknown",
+"www.kde.org",
+"yakuake",
+0 };
diff --git a/kdeui/kdetrayproxy/Makefile.am b/kdeui/kdetrayproxy/Makefile.am
new file mode 100644
index 000000000..49d823d31
--- /dev/null
+++ b/kdeui/kdetrayproxy/Makefile.am
@@ -0,0 +1,13 @@
+kde_module_LTLIBRARIES = kded_kdetrayproxy.la
+
+INCLUDES= -I$(top_srcdir)/kded $(all_includes)
+kded_kdetrayproxy_la_SOURCES = kdetrayproxy.cpp module.cpp module.skel
+kded_kdetrayproxy_la_LDFLAGS = $(all_libraries) -module -avoid-version
+kded_kdetrayproxy_la_LIBADD = $(LIB_KDECORE) $(LIB_KDED)
+
+METASOURCES = AUTO
+
+noinst_HEADERS = kdetrayproxy.h module.h
+
+servicesdir = $(kde_servicesdir)/kded
+services_DATA = kdetrayproxy.desktop
diff --git a/kdeui/kdetrayproxy/kdetrayproxy.cpp b/kdeui/kdetrayproxy/kdetrayproxy.cpp
new file mode 100644
index 000000000..b41b337b3
--- /dev/null
+++ b/kdeui/kdetrayproxy/kdetrayproxy.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2004 Lubos Lunak <l.lunak@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.
+ *
+ */
+
+#include "kdetrayproxy.h"
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <netwm.h>
+#include <X11/Xlib.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <assert.h>
+
+KDETrayProxy::KDETrayProxy()
+ : selection( makeSelectionAtom())
+ {
+ connect( &selection, SIGNAL( newOwner( Window )), SLOT( newOwner( Window )));
+ connect( &module, SIGNAL( windowAdded( WId )), SLOT( windowAdded( WId )));
+ selection.owner();
+ for( QValueList< WId >::ConstIterator it = module.windows().begin();
+ it != module.windows().end();
+ ++it )
+ windowAdded( *it );
+ kapp->installX11EventFilter( this ); // XSelectInput( StructureNotifyMask ) on windows is done by KWinModule
+// kdDebug() << "Init done" << endl;
+ }
+
+Atom KDETrayProxy::makeSelectionAtom()
+ {
+ return XInternAtom( qt_xdisplay(), "_NET_SYSTEM_TRAY_S" + QCString().setNum( qt_xscreen()), False );
+ }
+
+extern Time qt_x_time;
+
+void KDETrayProxy::windowAdded( WId w )
+ {
+ NETWinInfo ni( qt_xdisplay(), w, qt_xrootwin(), NET::WMKDESystemTrayWinFor );
+ WId trayWinFor = ni.kdeSystemTrayWinFor();
+ if ( !trayWinFor ) // not a KDE tray window
+ return;
+// kdDebug() << "New tray window:" << w << endl;
+ if( !tray_windows.contains( w ))
+ tray_windows.append( w );
+ withdrawWindow( w );
+ // window will be removed from pending_windows when after docked
+ if( !pending_windows.contains( w ))
+ pending_windows.append( w );
+ docked_windows.remove( w );
+ Window owner = selection.owner();
+ if( owner == None ) // no tray owner, sorry
+ {
+// kdDebug() << "No owner, left in pending" << endl;
+ return;
+ }
+ dockWindow( w, owner );
+ }
+
+void KDETrayProxy::newOwner( Window owner )
+ {
+// kdDebug() << "New owner:" << owner << endl;
+ for( QValueList< Window >::ConstIterator it = pending_windows.begin();
+ it != pending_windows.end();
+ ++it )
+ dockWindow( *it, owner );
+ // remove from pending_windows only in windowRemoved(), after it's really docked
+ }
+
+bool KDETrayProxy::x11Event( XEvent* e )
+ {
+ if( tray_windows.isEmpty())
+ return false;
+ if( e->type == DestroyNotify && tray_windows.contains( e->xdestroywindow.window ))
+ {
+ tray_windows.remove( e->xdestroywindow.window );
+ pending_windows.remove( e->xdestroywindow.window );
+ docked_windows.remove( e->xdestroywindow.window );
+ }
+ if( e->type == ReparentNotify && tray_windows.contains( e->xreparent.window ))
+ {
+ if( e->xreparent.parent == qt_xrootwin())
+ {
+ if( !docked_windows.contains( e->xreparent.window ) || e->xreparent.serial >= docked_windows[ e->xreparent.window ] )
+ {
+// kdDebug() << "Window released:" << e->xreparent.window << endl;
+ docked_windows.remove( e->xreparent.window );
+ if( !pending_windows.contains( e->xreparent.window ))
+ pending_windows.append( e->xreparent.window );
+ }
+ }
+ else
+ {
+// kdDebug() << "Window away:" << e->xreparent.window << ":" << e->xreparent.parent << endl;
+ pending_windows.remove( e->xreparent.window );
+ }
+ }
+ if( e->type == UnmapNotify && tray_windows.contains( e->xunmap.window ))
+ {
+ if( docked_windows.contains( e->xunmap.window ) && e->xunmap.serial >= docked_windows[ e->xunmap.window ] )
+ {
+// kdDebug() << "Window unmapped:" << e->xunmap.window << endl;
+ XReparentWindow( qt_xdisplay(), e->xunmap.window, qt_xrootwin(), 0, 0 );
+ // ReparentNotify will take care of the rest
+ }
+ }
+ return false;
+ }
+
+void KDETrayProxy::dockWindow( Window w, Window owner )
+ {
+// kdDebug() << "Docking " << w << " into " << owner << endl;
+ docked_windows[ w ] = XNextRequest( qt_xdisplay());
+ static Atom prop = XInternAtom( qt_xdisplay(), "_XEMBED_INFO", False );
+ long data[ 2 ] = { 0, 1 };
+ XChangeProperty( qt_xdisplay(), w, prop, prop, 32, PropModeReplace, (unsigned char*)data, 2 );
+ XSizeHints hints;
+ hints.flags = PMinSize | PMaxSize;
+ hints.min_width = 24;
+ hints.max_width = 24;
+ hints.min_height = 24;
+ hints.max_height = 24;
+ XSetWMNormalHints( qt_xdisplay(), w, &hints );
+// kxerrorhandler ?
+ XEvent ev;
+ memset(&ev, 0, sizeof( ev ));
+ static Atom atom = XInternAtom( qt_xdisplay(), "_NET_SYSTEM_TRAY_OPCODE", False );
+ ev.xclient.type = ClientMessage;
+ ev.xclient.window = owner;
+ ev.xclient.message_type = atom;
+ ev.xclient.format = 32;
+ ev.xclient.data.l[ 0 ] = qt_x_time;
+ ev.xclient.data.l[ 1 ] = 0; // SYSTEM_TRAY_REQUEST_DOCK
+ ev.xclient.data.l[ 2 ] = w;
+ ev.xclient.data.l[ 3 ] = 0; // unused
+ ev.xclient.data.l[ 4 ] = 0; // unused
+ XSendEvent( qt_xdisplay(), owner, False, NoEventMask, &ev );
+ }
+
+void KDETrayProxy::withdrawWindow( Window w )
+ {
+ XWithdrawWindow( qt_xdisplay(), w, qt_xscreen());
+ static Atom wm_state = XInternAtom( qt_xdisplay(), "WM_STATE", False );
+ for(;;)
+ {
+ Atom type;
+ int format;
+ unsigned long length, after;
+ unsigned char *data;
+ int r = XGetWindowProperty( qt_xdisplay(), w, wm_state, 0, 2,
+ False, AnyPropertyType, &type, &format,
+ &length, &after, &data );
+ bool withdrawn = true;
+ if ( r == Success && data && format == 32 )
+ {
+ withdrawn = ( *( long* )data == WithdrawnState );
+ XFree( (char *)data );
+ }
+ if( withdrawn )
+ return; // --->
+ struct timeval tm;
+ tm.tv_sec = 0;
+ tm.tv_usec = 10 * 1000; // 10ms
+ select(0, NULL, NULL, NULL, &tm);
+ }
+ }
+
+#include "kdetrayproxy.moc"
+
+#if 0
+#include <kcmdlineargs.h>
+int main( int argc, char* argv[] )
+ {
+ KCmdLineArgs::init( argc, argv, "a", "b", "c", "d" );
+ KApplication app( false ); // no styles
+ app.disableSessionManagement();
+ KDETrayProxy proxy;
+ return app.exec();
+ }
+#endif
diff --git a/kdeui/kdetrayproxy/kdetrayproxy.desktop b/kdeui/kdetrayproxy/kdetrayproxy.desktop
new file mode 100644
index 000000000..59006a5eb
--- /dev/null
+++ b/kdeui/kdetrayproxy/kdetrayproxy.desktop
@@ -0,0 +1,134 @@
+[Desktop Entry]
+Type=Service
+Name=KDE Tray Proxy Module
+Name[af]=KDE Skinkbord Proksie Module
+Name[bn]=কে.ডি.ই. টà§à¦°à§‡ পà§à¦°à¦•à§à¦¸à¦¿ মডিউল
+Name[bs]=KDE proxy modul za tray
+Name[ca]=Mòdul de safata d'intermediari del KDE
+Name[cs]=Proxy modul panelu KDE
+Name[csb]=Mòduł pòstrzédnika systemòwégò tablëtkù KDE
+Name[da]=KDE-statusfelt proxy-modul
+Name[de]=Proxy-Modul für den KDE-Systemabschnitt
+Name[el]=ΆÏθÏωμα διαμεσολαβητή πλαισίου συστήματος του KDE
+Name[eo]=KDE-sistelistela prokurmodulo
+Name[es]=Módulo Proxy de bandeja de KDE
+Name[et]=KDE süsteemse salve proxy moodul
+Name[eu]=KDEren erretiluko proxy-modulua
+Name[fa]=پیمانۀ پیشکار سینی KDE
+Name[fi]=KDE:n ilmoitusalueen välityspalvelinmoduuli
+Name[fr]=Serveur mandataire pour les miniatures de KDE
+Name[fy]=KDE Systeemfak Proxy Module
+Name[ga]=Modúl Seachfhreastalaí do Thráidire KDE
+Name[gl]=Módulo de simulación da bandexa de KDE
+Name[he]=מתווך מגש מערכת של KDE
+Name[hi]=केडीई टà¥à¤°à¥‡ पà¥à¤°à¥‰à¤•à¥à¤¸à¥€ मॉडà¥à¤¯à¥‚ल
+Name[hr]=KDE sistemski modul Proxy
+Name[hu]=KDE paneltálca-proxy modul
+Name[id]=Modul Proxy Baki KDE
+Name[is]=KDE milliþjónseining spjaldsins
+Name[it]=Modulo proxy per il vassoio di KDE
+Name[ja]=KDE トレイプロキシモジュール
+Name[ka]=KDE სისტემური ზáƒáƒšáƒ˜áƒ¡ პრáƒáƒ¥áƒ¡áƒ˜ მáƒáƒ“ული
+Name[kk]=KDE жүйелік ÑөреÑінің прокÑи модулі
+Name[km]=ម៉ូឌុល​ប្រូកស៊ី KDE Tray
+Name[lb]=Proxymodul fir KDE-Symbolleescht
+Name[lt]=KDE dÄ—klo proxy modulis
+Name[mk]=KDE Модул за прокÑи во ÑиÑ. лента
+Name[ms]=Modul Dulang Proksi KDE
+Name[nb]=KDE mellommodul
+Name[nds]=Systeemafsnitt-Proxymoduul
+Name[ne]=KDE टà¥à¤°à¥‡ पà¥à¤°à¥‹à¤•à¥à¤¸à¥€ मोडà¥à¤¯à¥à¤²
+Name[nl]=Proxy-module voor het KDE-systeemvak
+Name[nn]=KDE-mellommodul for systemtrauet
+Name[pa]=KDE ਟਰੇ ਪਰਾਕਸੀ ਮੈਡੀਊਲ
+Name[pl]=Moduł pośrednika tacki systemowej KDE
+Name[pt]=Módulo de 'Proxy' de Bandeja do KDE
+Name[pt_BR]=Módulo de Proxy do Painel do KDE
+Name[ro]=Modul proxy pentru tava de sistem KDE
+Name[ru]=Модуль прокÑи ÑиÑтемного лотка KDE
+Name[rw]=Igice Igitwara Nyabubasha KDE
+Name[se]=KDE-gaskamoduvla vuogádatgárccu várás
+Name[sk]=Modul pre proxy lišty KDE
+Name[sl]=Modul posrednika sistemske vrstice KDE
+Name[sr]=ПрокÑи модул KDE-ове каÑете
+Name[sr@Latn]=Proksi modul KDE-ove kasete
+Name[sv]=KDE-proxymodul för systembricka
+Name[ta]=KDE தடà¯à®Ÿà¯ மாறà¯à®±à¯ பதிலாள௠கூறà¯
+Name[te]=కెడిఈ à°Ÿà±à°°à±‡ à°ªà±à°°à°¾à°•à±à°¸à±€ మాడà±à°¯à±‚à°²à±
+Name[tg]=Ðоваи KDE-и модули прокÑи
+Name[th]=โมดูลถาดพร็อà¸à¸‹à¸µà¸‚อง KDE
+Name[tr]=KDE Görev Çubuğu Vekil Birimi
+Name[tt]=KDE Tiräsenä Proxy Modulı
+Name[uk]=Модуль поÑередника Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼ в ÑиÑтемному лотку
+Name[vi]=Mô-đun ủy nhiệm khay KDE
+Name[zh_CN]=KDE 托盘代ç†æ¨¡å—
+Name[zh_TW]=KDE 系統匣代ç†æ¨¡çµ„
+Comment=Proxy enabling KDE systray applications to work without KWin
+Comment[af]=Proksie wat KDE 'systray' programme toelaat om sonder KWin te werk
+Comment[bg]=Модул, който позволÑва на програмите от KDE да работÑÑ‚ в ÑиÑÑ‚ÐµÐ¼Ð½Ð¸Ñ Ð¿Ð°Ð½ÐµÐ» Ñ Ð´Ñ€ÑƒÐ³Ð¸ мениджъри на прозорци
+Comment[bn]=কে.ডি.ই. সিস-টà§à¦°à§‡ অà§à¦¯à¦¾à¦ªà¦²à¦¿à¦•à§‡à¦¶à¦¨ কে-উইন ছাড়াই কাজ করাবার জনà§à¦¯ পà§à¦°à¦•à§à¦¸à¦¿
+Comment[bs]=Proxy koji omogućuje KDE systray programima da rade izvan KWin-a
+Comment[ca]=Habilitació d'intermediari per a les aplicacions de safata del sistema per a treballar sense KWin
+Comment[cs]=Proxy umožňuje, aby KDE zabudované aplikace fungovaly i bez KWin
+Comment[csb]=Pòstrzédnik dôwôjący mòżnotã robòtë programów brëkùjącëch systemòwégò tablëtkù KDE wëłączając z tegò KWin
+Comment[da]=Proxy aktivering af KDE's statusfelt programmer til at virke uden KWin
+Comment[de]=Proxy, der Programme im Systemabschnitt der Kontrollleiste auch ohne KWin als Fenstermanager funktionieren lässt
+Comment[el]=Διαμεσολαβητής που επιτÏέπει σε εφαÏμογές πλαισίου συστήματος του KDE να λειτουÏγοÏν χωÏίς το KWin
+Comment[eo]=Prokuro ebligas KDEajn aplikaĵojn labori sen KWin
+Comment[es]=Activación de Proxy de aplicaciones systray de KDE sin KWin
+Comment[et]=Proxy, mis võimaldab KDE süsteemse salve rakendustel töötada ilma KWin'ita
+Comment[eu]=KDEren erretiluko proxy-gaitze aplikazioak KWin gabe lan egiteko
+Comment[fa]=پیشکار، کاربردهایKDE systray را برای کار کردن بدون KWin Ùعال می‌سازد
+Comment[fi]=Välimuistipalvelin, jonka avulla ilmoitusalueen sovellukset voivat toimia ilman KWiniä
+Comment[fr]=Serveur mandataire autorisant le fonctionnement des miniatures sans KWin
+Comment[fy]=Troch Proxy kinne KDE systeemfak applikaasjes wurkje sûnder KWin
+Comment[ga]=Seachfhreastalaí a cheadaíonn d'fheidhmchláir i dtráidire an chórais a oibriú gan KWin
+Comment[gl]=Proxy que permite que as aplicación de KDE que usen a bandexa traballen sen KWin
+Comment[he]=שרת המ×פשל לתוכניות KDE להתחבר למגש המערכת ×œ×œ× KWin
+Comment[hi]=पà¥à¤°à¥‰à¤•à¥à¤¸à¥€ जो के-विन के बगैर कारà¥à¤¯ करने के लिठकेडीई सिसà¥à¤Ÿà¥à¤°à¥‡ अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤—ों को सकà¥à¤·à¤® करता है
+Comment[hr]=Aplikacije za omogućavanje proxyja smještene u KDE sistemskoj traci, bez primjene KWin
+Comment[hu]=KDE-s paneltálca-alkalmazások futtatása a KWin-től eltérő ablakkezelőknél
+Comment[id]=Proxy untuk membuat aplikasi systray KDE berfungsi tanpa KWin
+Comment[is]=Milliþjónseining fyrir KDE spjaldið sem virkar án KWin
+Comment[it]=Permette alle applicazioni per il vassoio di KDE di funzionare senza KWin
+Comment[ja]=KWin ãªã—㧠KDE systray アプリケーションを動作å¯èƒ½ã«ã™ã‚‹ãƒ—ロキシ
+Comment[ka]=KDE სისტემური ზáƒáƒšáƒ˜áƒ¡ პრáƒáƒ¥áƒ¡áƒ˜ მáƒáƒ“ული პრáƒáƒ’რáƒáƒ›áƒ”ბისთვის KWin-ის გáƒáƒ áƒ”შე სáƒáƒ›áƒ£áƒ¨áƒáƒáƒ“
+Comment[kk]=KDE жүйелік Ñөредегі қолданбаға KWin-Ñіз Ð¶Ò±Ð¼Ñ‹Ñ Ñ–Ñтеуге мүмкіншілік беретін прокÑи
+Comment[km]=ប្រូកស៊ី​ដែល​អនុញ្ញាážâ€‹áž²áŸ’យ​កម្មវិធី KDE systray ធ្វើការ​ដោយ​គ្មាន KWin
+Comment[lb]=Proxy, deen et erméiglecht, dass Programmer fir d'KDE-Symbolleescht ouni de KWin funktionéieren
+Comment[lt]=Proxy įgalinantis KDE sistemos dėklo taikomasias programas dirbti be KWin
+Comment[mk]=ПрокÑи кое им овозможува на KDE апликациите од ÑиÑ. лента да работат без KWin
+Comment[ms]=Aplikasi dulang sys dengan fungsi proksi untuk berfungsi tanpa KWin
+Comment[nb]=Modul som gjør at systemkurvprogrammet for KDE kan fungere uten KWin
+Comment[nds]=Disse Proxy lett Systeemafsnitt-Programmen ok ahn KWin lopen
+Comment[ne]= KWin बाहेक कारà¥à¤¯ गरà¥à¤¨ पà¥à¤°à¥‹à¤•à¥à¤¸à¥€ सकà¥à¤·à¤® पारà¥à¤¨à¥‡ KDE सिसà¥à¤Ÿà¥à¤°à¥‡
+Comment[nl]=Proxy-module om toepassingen in het KDE-systeemvak te plaatsen die geen KWin ondersteuning hebben.
+Comment[nn]=Modul som gjer at systemtrauprogram for KDE kan fungera uavhengig av KWin
+Comment[pa]=KWin ਬਿਨਾਂ ਕੰਮ ਕਰਨ ਲਈ KDE systray ਕਾਰਜਾਂ ਲਈ ਪਰਾਕਸੀ ਯੋਗ
+Comment[pl]=Pośrednik, umożliwiający działanie programów wymagających tacki systemowej KDE bez KWin
+Comment[pt]='Proxy' que permite aplicações da bandeja de sistema do KDE funcionarem sem o KWin
+Comment[pt_BR]=Habilita o funcionamento do proxy em aplicativos sem o KWin
+Comment[ro]=Permite aplicaţiilor pentru tava de sistem KDE să lucreze fără suport din partea KWin
+Comment[ru]=ПрокÑи Ð´Ð»Ñ ÑиÑтемного лотка KDE Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ð¹, работающих без KWin
+Comment[rw]=Nyabubasha ibashisha Amaporogaramu y'igitwarasisitemu KDE gukora nta KWmo
+Comment[se]=Moduvla mii dagaha ahte KDE:a vuogádatgárcoprográmmat doibmet KWin haga.
+Comment[sk]=Proxy pre aplikácie z lišty KDE, aby nevyžadovali KWin
+Comment[sl]=Posrednik, ki omogoÄa programom sistemske vrstice KDE, da delujejo brez KWin
+Comment[sr]=ПрокÑи који омогућава KDE програмима за ÑиÑтемÑку каÑету да раде без KWin-а
+Comment[sr@Latn]=Proksi koji omogućava KDE programima za sistemsku kasetu da rade bez KWin-a
+Comment[sv]=Proxymodul som gör det möjligt för KDE:s program i systembrickan att fungera utan Kwin
+Comment[ta]=மாறà¯à®±à¯ பதிலாள௠KDE அமைபà¯à®ªà¯ தடà¯à®Ÿà¯ பயனà¯à®ªà®¾à®Ÿà¯à®Ÿà¯ˆ KWin இலà¯à®²à®¾à®®à®²à¯ வேலை செயà¯à®¯ செயலà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®•à®¿à®±à®¤à¯
+Comment[te]=కెవినౠలేకà±à°‚à°¡à°¾ à°ªà±à°°à°¾à°•à±à°¸à°¿ నౠవాడె కెడీఈ సిసౠటà±à°°à±‡ కారà±à°¯à°•à±à°°à°®à°¾à°²à°¨à± పని చెYఇసà±à°¤à±à°‚ది
+Comment[tg]=Proxy барномаҳои KDE systray-ро барои корнамоӣ, бидуни KWin фаъол меÑозад
+Comment[th]=à¹à¸­à¸žà¸žà¸¥à¸´à¹€à¸„ชันถาดระบบของ KDE ที่เปิดความสามารถพร็อà¸à¸‹à¸µ สำหรับทำงานโดยไม่ต้องมี KWin
+Comment[tr]=Vekil sunucu etkinleştirme KDE sistem çubuğu uygulamalarının KWin olmadan çalıştırır.
+Comment[tt]=KWin'sız eşläwçe yazılımnar öçen KDE sistiräseneñ Proxy
+Comment[uk]=Програма поÑередник, Ñка дозволÑÑ” працювати програмам Ð´Ð»Ñ KDE, що викориÑтовують ÑиÑтемний лоток, без KWin
+Comment[vi]=Bộ ủy nhiệm hiệu lực các ứng dụng khay hệ thống KDE hoạt động, không cần KWin.
+Comment[zh_CN]=å…许 KDE 系统托盘应用程åºåœ¨æ²¡æœ‰ KWin 的情况下工作
+Comment[zh_TW]=系統匣代ç†æ¨¡çµ„讓系統匣應用程å¼ä¸å¿…é  KWin é‹ä½œ
+ServiceTypes=KDEDModule
+X-KDE-ModuleType=Library
+X-KDE-Library=kdetrayproxy
+X-KDE-FactoryName=kdetrayproxy
+X-KDE-Kded-autoload=false
diff --git a/kdeui/kdetrayproxy/kdetrayproxy.h b/kdeui/kdetrayproxy/kdetrayproxy.h
new file mode 100644
index 000000000..67c9c6299
--- /dev/null
+++ b/kdeui/kdetrayproxy/kdetrayproxy.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2004 Lubos Lunak <l.lunak@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.
+ *
+ */
+
+#ifndef _KDE_TRAY_PROXY_H_
+#define _KDE_TRAY_PROXY_H_
+
+#include <qvaluelist.h>
+#include <kmanagerselection.h>
+#include <kwinmodule.h>
+#include <qwidget.h>
+
+class KDETrayProxy
+ : public QWidget
+ {
+ Q_OBJECT
+ public:
+ KDETrayProxy();
+ public slots:
+ void windowAdded( WId );
+ void newOwner( Window );
+ protected:
+ virtual bool x11Event( XEvent* );
+ private:
+ void dockWindow( Window w, Window owner );
+ void withdrawWindow( Window w );
+ static Atom makeSelectionAtom();
+ KSelectionWatcher selection;
+ KWinModule module;
+ QValueList< Window > pending_windows;
+ QValueList< Window > tray_windows;
+ QMap< Window, unsigned long > docked_windows;
+ };
+
+#endif
diff --git a/kdeui/kdetrayproxy/module.cpp b/kdeui/kdetrayproxy/module.cpp
new file mode 100644
index 000000000..c3a6a7b0c
--- /dev/null
+++ b/kdeui/kdetrayproxy/module.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2004 Lubos Lunak <l.lunak@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.
+ *
+ */
+
+#include "module.h"
+
+KDETrayModule::KDETrayModule( const QCString& obj )
+ : KDEDModule( obj )
+ {
+ }
+
+extern "C"
+KDE_EXPORT KDEDModule *create_kdetrayproxy( const QCString& obj )
+ {
+ return new KDETrayModule( obj );
+ }
+
+#include "module.moc"
diff --git a/kdeui/kdetrayproxy/module.h b/kdeui/kdetrayproxy/module.h
new file mode 100644
index 000000000..f5ef55f6d
--- /dev/null
+++ b/kdeui/kdetrayproxy/module.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2004 Lubos Lunak <l.lunak@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.
+ *
+ */
+
+#ifndef _KDE_TRAY_MODULE_H_
+#define _KDE_TRAY_MODULE_H_
+
+#include <kdedmodule.h>
+#include <dcopobject.h>
+
+#include "kdetrayproxy.h"
+
+class KDETrayModule
+ : public KDEDModule
+ {
+ Q_OBJECT
+ K_DCOP
+ public:
+ KDETrayModule( const QCString& obj );
+ private:
+ KDETrayProxy proxy;
+ };
+
+#endif
diff --git a/kdeui/kdialog.cpp b/kdeui/kdialog.cpp
new file mode 100644
index 000000000..b61ea9089
--- /dev/null
+++ b/kdeui/kdialog.cpp
@@ -0,0 +1,321 @@
+/* This file is part of the KDE Libraries
+ * Copyright (C) 1998 Thomas Tanghus (tanghus@earthling.net)
+ * Additions 1999-2000 by Espen Sand (espen@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <kconfig.h>
+#include <kapplication.h>
+#include <kdialog.h>
+#include <kwhatsthismanager_p.h>
+#include <kdebug.h>
+#include <kstaticdeleter.h>
+
+#include <qlayout.h>
+#include <qobjectlist.h>
+#include <qguardedptr.h>
+#include <qlineedit.h>
+#include <qvaluelist.h>
+#include <qtimer.h>
+#include <qcursor.h>
+
+#include "config.h"
+#ifdef Q_WS_X11
+#include <netwm.h>
+#endif
+
+const int KDialog::mMarginSize = 11;
+const int KDialog::mSpacingSize = 6;
+
+template class QPtrList<QLayoutItem>;
+
+KDialog::KDialog(QWidget *parent, const char *name, bool modal, WFlags f)
+ : QDialog(parent, name, modal, f), d(0)
+{
+ KWhatsThisManager::init ();
+}
+
+//
+// Grab QDialogs keypresses if non-modal.
+//
+void KDialog::keyPressEvent(QKeyEvent *e)
+{
+ if ( e->state() == 0 )
+ {
+ switch ( e->key() )
+ {
+ case Key_Escape:
+ case Key_Enter:
+ case Key_Return:
+ {
+ if(testWFlags(WType_Dialog | WShowModal))
+ {
+ QDialog::keyPressEvent(e);
+ }
+ else
+ {
+ e->ignore();
+ }
+ }
+ break;
+ default:
+ e->ignore();
+ return;
+ }
+ }
+ else
+ {
+ // accept the dialog when Ctrl-Return is pressed
+ if ( e->state() == ControlButton &&
+ (e->key() == Key_Return || e->key() == Key_Enter) )
+ {
+ e->accept();
+ accept();
+ }
+ else
+ {
+ e->ignore();
+ }
+ }
+}
+
+
+int KDialog::marginHint()
+{
+ return mMarginSize;
+}
+
+
+int KDialog::spacingHint()
+{
+ return mSpacingSize;
+}
+
+// KDE4: Remove me
+void KDialog::polish()
+{
+ QDialog::polish();
+}
+
+
+void KDialog::setCaption( const QString &_caption )
+{
+ QString caption = kapp ? kapp->makeStdCaption( _caption ) : _caption;
+ setPlainCaption( caption );
+}
+
+
+void KDialog::setPlainCaption( const QString &caption )
+{
+ QDialog::setCaption( caption );
+
+#ifdef Q_WS_X11
+ NETWinInfo info( qt_xdisplay(), winId(), qt_xrootwin(), 0 );
+ info.setName( caption.utf8().data() );
+#endif
+}
+
+
+void KDialog::resizeLayout( QWidget *w, int margin, int spacing )
+{
+ if( w->layout() )
+ {
+ resizeLayout( w->layout(), margin, spacing );
+ }
+
+ if( w->children() )
+ {
+ const QObjectList * const l = w->children();
+ QObjectListIterator itr(*l);
+ QObject *o;
+ while ((o = itr.current()) != 0) {
+ if( o->isWidgetType() )
+ {
+ resizeLayout( (QWidget*)o, margin, spacing );
+ }
+ ++itr;
+ }
+ }
+}
+
+
+void KDialog::resizeLayout( QLayoutItem *lay, int margin, int spacing )
+{
+ QLayoutIterator it = lay->iterator();
+ QLayoutItem *child;
+ while ( (child = it.current() ) )
+ {
+ resizeLayout( child, margin, spacing );
+ ++it;
+ }
+ if( lay->layout() )
+ {
+ lay->layout()->setMargin( margin );
+ lay->layout()->setSpacing( spacing );
+ }
+}
+
+static QRect screenRect( QWidget *w, int screen )
+{
+ QDesktopWidget *desktop = QApplication::desktop();
+ KConfig gc("kdeglobals", false, false);
+ gc.setGroup("Windows");
+ if (desktop->isVirtualDesktop() &&
+ gc.readBoolEntry("XineramaEnabled", true) &&
+ gc.readBoolEntry("XineramaPlacementEnabled", true)) {
+ if ( screen < 0 || screen >= desktop->numScreens() ) {
+ if ( screen == -1 ) {
+ screen = desktop->primaryScreen();
+ } else if ( screen == -3 ) {
+ screen = desktop->screenNumber( QCursor::pos() );
+ } else {
+ screen = desktop->screenNumber( w );
+ }
+ }
+ return desktop->availableGeometry(screen);
+ } else {
+ return desktop->geometry();
+ }
+}
+
+void KDialog::centerOnScreen( QWidget *w, int screen )
+{
+ if ( !w )
+ return;
+ QRect r = screenRect( w, screen );
+
+ w->move( r.center().x() - w->width()/2,
+ r.center().y() - w->height()/2 );
+}
+
+bool KDialog::avoidArea( QWidget *w, const QRect& area, int screen )
+{
+ if ( !w )
+ return false;
+ QRect fg = w->frameGeometry();
+ if ( !fg.intersects( area ) )
+ return true; // nothing to do.
+
+ QRect scr = screenRect( w, screen );
+ QRect avoid( area ); // let's add some margin
+ avoid.moveBy( -5, -5 );
+ avoid.rRight() += 10;
+ avoid.rBottom() += 10;
+
+ if ( QMAX( fg.top(), avoid.top() ) <= QMIN( fg.bottom(), avoid.bottom() ) )
+ {
+ // We need to move the widget up or down
+ int spaceAbove = QMAX(0, avoid.top() - scr.top());
+ int spaceBelow = QMAX(0, scr.bottom() - avoid.bottom());
+ if ( spaceAbove > spaceBelow ) // where's the biggest side?
+ if ( fg.height() <= spaceAbove ) // big enough?
+ fg.setY( avoid.top() - fg.height() );
+ else
+ return false;
+ else
+ if ( fg.height() <= spaceBelow ) // big enough?
+ fg.setY( avoid.bottom() );
+ else
+ return false;
+ }
+
+ if ( QMAX( fg.left(), avoid.left() ) <= QMIN( fg.right(), avoid.right() ) )
+ {
+ // We need to move the widget left or right
+ int spaceLeft = QMAX(0, avoid.left() - scr.left());
+ int spaceRight = QMAX(0, scr.right() - avoid.right());
+ if ( spaceLeft > spaceRight ) // where's the biggest side?
+ if ( fg.width() <= spaceLeft ) // big enough?
+ fg.setX( avoid.left() - fg.width() );
+ else
+ return false;
+ else
+ if ( fg.width() <= spaceRight ) // big enough?
+ fg.setX( avoid.right() );
+ else
+ return false;
+ }
+ //kdDebug() << "Moving window to " << fg.x() << "," << fg.y() << endl;
+ w->move(fg.x(), fg.y());
+ return true;
+}
+
+class KDialogQueuePrivate
+{
+public:
+ QValueList< QGuardedPtr<QDialog> > queue;
+ bool busy;
+};
+
+static KStaticDeleter<KDialogQueue> ksdkdq;
+
+KDialogQueue *KDialogQueue::_self=0;
+
+KDialogQueue* KDialogQueue::self()
+{
+ if (!_self)
+ _self = ksdkdq.setObject(_self, new KDialogQueue);
+ return _self;
+}
+
+KDialogQueue::KDialogQueue() : d(new KDialogQueuePrivate)
+{
+ d->busy = false;
+}
+
+KDialogQueue::~KDialogQueue()
+{
+ delete d;
+ _self = 0;
+}
+
+// static
+void KDialogQueue::queueDialog(QDialog *dialog)
+{
+ KDialogQueue *_this = self();
+ _this->d->queue.append(dialog);
+ QTimer::singleShot(0, _this, SLOT(slotShowQueuedDialog()));
+}
+
+void KDialogQueue::slotShowQueuedDialog()
+{
+ if (d->busy)
+ return;
+ QDialog *dialog;
+ do {
+ if(d->queue.isEmpty())
+ return;
+ dialog = d->queue.first();
+ d->queue.pop_front();
+ }
+ while(!dialog);
+
+ d->busy = true;
+ dialog->exec();
+ d->busy = false;
+ delete dialog;
+
+ if (!d->queue.isEmpty())
+ QTimer::singleShot(20, this, SLOT(slotShowQueuedDialog()));
+ else
+ ksdkdq.destructObject(); // Suicide.
+}
+
+void KDialog::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "kdialog.moc"
diff --git a/kdeui/kdialog.h b/kdeui/kdialog.h
new file mode 100644
index 000000000..c012a7266
--- /dev/null
+++ b/kdeui/kdialog.h
@@ -0,0 +1,211 @@
+/* This file is part of the KDE Libraries
+ * Copyright (C) 1998 Thomas Tanghus (tanghus@earthling.net)
+ * Additions 1999-2000 by Espen Sand (espen@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _KDIALOG_H_
+#define _KDIALOG_H_
+
+class QLayoutItem;
+
+#include <qdialog.h>
+
+#include <kdelibs_export.h>
+
+/**
+ * Dialog with extended non-modal support and methods for %KDE standard
+ * compliance.
+ *
+ * Generally, you should not use this class directly, but KDialogBase
+ * which inherits KDialog.
+ *
+ * If the dialog is non-modal and has a parent, the default keybindings
+ * (@p escape = @p reject(), @p enter = @p accept(), etc.) are disabled.
+ *
+ * The marginHint() and spacingHint() sizes shall be used
+ * whenever you layout the interior of a dialog. One special note. If
+ * you make your own action buttons (OK, Cancel etc), the space
+ * beteween the buttons shall be spacingHint(), whereas the space
+ * above, below, to the right and to the left shall be marginHint().
+ * If you add a separator line above the buttons, there shall be a
+ * marginHint() between the buttons and the separator and a
+ * marginHint() above the separator as well.
+ *
+ * @see KDialogBase
+ * @author Thomas Tanghus <tanghus@earthling.net>, Espen Sand <espensa@online.no>
+ */
+class KDEUI_EXPORT KDialog : public QDialog
+{
+ Q_OBJECT
+
+ public:
+
+ /**
+ * Constructor.
+ *
+ * Takes the same arguments as QDialog.
+ */
+ KDialog(QWidget *parent = 0, const char *name = 0,
+ bool modal = false, WFlags f = 0);
+
+ /**
+ * Return the number of pixels you shall use between a
+ * dialog edge and the outermost widget(s) according to the KDE standard.
+ **/
+ static int marginHint();
+
+ /**
+ * Return the number of pixels you shall use between
+ * widgets inside a dialog according to the KDE standard.
+ */
+ static int spacingHint();
+
+ /**
+ * Resize every layout manager used in @p widget and its nested children.
+ *
+ * @param widget The widget used.
+ * @param margin The new layout margin.
+ * @param spacing The new layout spacing.
+ */
+ static void resizeLayout( QWidget *widget, int margin, int spacing );
+
+ /**
+ * Resize every layout associated with @p lay and its children.
+ *
+ * @param lay layout to be resized
+ * @param margin The new layout margin
+ * @param spacing The new layout spacing
+ */
+ static void resizeLayout( QLayoutItem *lay, int margin, int spacing );
+
+ /**
+ * Centers @p widget on the desktop, taking multi-head setups into
+ * account. If @p screen is -1, @p widget will be centered on its
+ * current screen (if it was shown already) or on the primary screen.
+ * If @p screen is -3, @p widget will be centered on the screen that
+ * currently contains the mouse pointer.
+ * @p screen will be ignored if a merged display (like Xinerama) is not
+ * in use, or merged display placement is not enabled in kdeglobals.
+ * @since 3.1
+ */
+ static void centerOnScreen( QWidget *widget, int screen = -1 );
+
+ /**
+ * Places @p widget so that it doesn't cover a certain @p area of the screen.
+ * This is typically used by the "find dialog" so that the match it finds can
+ * be read.
+ * For @p screen, see centerOnScreen
+ * @return true on success (widget doesn't cover area anymore, or never did),
+ * false on failure (not enough space found)
+ * @since 3.2
+ */
+ static bool avoidArea( QWidget *widget, const QRect& area, int screen = -1 );
+
+ public slots:
+ /**
+ * If the dialog starts with focus in a QLineEdit child,
+ * then call selectAll() on the child.
+ */
+ virtual void polish();
+
+ /**
+ * Make a KDE compliant caption.
+ *
+ * @param caption Your caption. Do @p not include the application name
+ * in this string. It will be added automatically according to the KDE
+ * standard.
+ */
+ virtual void setCaption( const QString &caption );
+
+ /**
+ * Make a plain caption without any modifications.
+ *
+ * @param caption Your caption. This is the string that will be
+ * displayed in the window title.
+ */
+ virtual void setPlainCaption( const QString &caption );
+
+
+ protected:
+ /**
+ * @internal
+ */
+ virtual void keyPressEvent(QKeyEvent*);
+
+
+ signals:
+ /**
+ * Emitted when the margin size and/or spacing size
+ * have changed.
+ *
+ * Use marginHint() and spacingHint() in your slot
+ * to get the new values.
+ */
+ void layoutHintChanged();
+
+ private:
+ static const int mMarginSize;
+ static const int mSpacingSize;
+
+ protected:
+ virtual void virtual_hook( int id, void* data );
+ private:
+ class KDialogPrivate;
+ KDialogPrivate* const d;
+
+};
+
+
+ /**
+ * \brief Queue for showing modal dialogs one after the other.
+ *
+ * This is useful if you want to show a modal dialog but are not in the
+ * position to start a new event loop at that point in your code.
+ *
+ * The disadvantage is that you will not be able to get any information from
+ * the dialog, so it can currently only be used for simple dialogs.
+ *
+ * You probably want to use KMessageBox::queueMessageBox() instead
+ * of this class directly.
+ *
+ * @author Waldo Bastian <bastian@kde.org>
+ */
+class KDialogQueuePrivate;
+class KDEUI_EXPORT KDialogQueue : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ static void queueDialog(QDialog *);
+
+ ~KDialogQueue();
+
+protected:
+ KDialogQueue();
+ static KDialogQueue *self();
+
+private slots:
+ void slotShowQueuedDialog();
+
+protected:
+ KDialogQueuePrivate* const d;
+ static KDialogQueue *_self;
+};
+
+#endif // __KDIALOG_H
diff --git a/kdeui/kdialogbase.cpp b/kdeui/kdialogbase.cpp
new file mode 100644
index 000000000..a0ef23f32
--- /dev/null
+++ b/kdeui/kdialogbase.cpp
@@ -0,0 +1,1844 @@
+/*
+ * This file is part of the KDE Libraries
+ * Copyright (C) 1999-2001 Mirko Boehm (mirko@kde.org) and
+ * Espen Sand (espen@kde.org)
+ * Holger Freyther <freyther@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "kdialogbase.h"
+#include <stdlib.h>
+
+#include <qgrid.h>
+#include <qhbox.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qvbox.h>
+#include <qwhatsthis.h>
+#include <qtimer.h>
+#include <qfocusdata.h>
+
+#include <kapplication.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kiconloader.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+#include <kseparator.h>
+#include <kurllabel.h>
+#include <kdebug.h>
+
+#include "kdialogbase_priv.h"
+#include "kdialogbase_priv.moc"
+
+KDialogBaseTile *KDialogBase::mTile = 0;
+
+int KDialogBaseButton::id()
+{
+ return mKey;
+}
+
+template class QPtrList<KDialogBaseButton>;
+
+/**
+ * @internal
+ */
+namespace
+{
+struct SButton : public Qt
+{
+ SButton()
+ {
+ box = 0;
+ mask = 0;
+ style = 0;
+ }
+
+ KPushButton *append( int key, const KGuiItem &item );
+
+ void resize( bool sameWidth, int margin, int spacing, int orientation );
+
+ KPushButton *button( int key );
+
+ QWidget *box;
+ int mask;
+ int style;
+ QPtrList<KDialogBaseButton> list;
+};
+}// namespace
+
+class KDialogBase::KDialogBasePrivate {
+public:
+ KDialogBasePrivate() : bDetails(false), bFixed(false), bSettingDetails(false), detailsWidget(0) { }
+
+ bool bDetails;
+ bool bFixed;
+ bool bSettingDetails;
+ QWidget *detailsWidget;
+ QSize incSize;
+ QSize minSize;
+ QString detailsButton;
+ SButton mButton;
+};
+
+KDialogBase::KDialogBase( QWidget *parent, const char *name, bool modal,
+ const QString &caption, int buttonMask,
+ ButtonCode defaultButton, bool separator,
+ const KGuiItem &user1, const KGuiItem &user2,
+ const KGuiItem &user3 )
+ :KDialog( parent, name, modal, WStyle_DialogBorder ),
+ mTopLayout(0), mMainWidget(0), mUrlHelp(0), mJanus(0), mActionSep(0),
+ mIsActivated(false), mShowTile(false), mMessageBoxMode(false),
+ mButtonOrientation(Horizontal), d(new KDialogBasePrivate)
+{
+ setCaption( caption );
+
+ makeRelay();
+ connect( this, SIGNAL(layoutHintChanged()), SLOT(updateGeometry()) );
+
+ enableButtonSeparator( separator );
+ makeButtonBox( buttonMask, defaultButton, user1, user2, user3 );
+
+ mIsActivated = true;
+ setupLayout();
+}
+
+KDialogBase::KDialogBase( int dialogFace, const QString &caption,
+ int buttonMask, ButtonCode defaultButton,
+ QWidget *parent, const char *name, bool modal,
+ bool separator, const KGuiItem &user1,
+ const KGuiItem &user2, const KGuiItem &user3 )
+ :KDialog( parent, name, modal, WStyle_DialogBorder ),
+ mTopLayout(0), mMainWidget(0), mUrlHelp(0), mJanus(0), mActionSep(0),
+ mIsActivated(false), mShowTile(false), mMessageBoxMode(false),
+ mButtonOrientation(Horizontal), d(new KDialogBasePrivate)
+{
+ setCaption( caption );
+
+ makeRelay();
+ connect( this, SIGNAL(layoutHintChanged()), SLOT(updateGeometry()) );
+
+ mJanus = new KJanusWidget( this, "janus", dialogFace );
+ connect(mJanus, SIGNAL(aboutToShowPage(QWidget *)),
+ this, SIGNAL(aboutToShowPage(QWidget *)));
+
+ if( !mJanus || !mJanus->isValid() ) { return; }
+
+ enableButtonSeparator( separator );
+ makeButtonBox( buttonMask, defaultButton, user1, user2, user3 );
+
+ mIsActivated = true;
+ setupLayout();
+}
+
+KDialogBase::KDialogBase( KDialogBase::DialogType dialogFace, WFlags f, QWidget *parent, const char *name,
+ bool modal,
+ const QString &caption, int buttonMask,
+ ButtonCode defaultButton, bool separator,
+ const KGuiItem &user1, const KGuiItem &user2,
+ const KGuiItem &user3 )
+ :KDialog( parent, name, modal, f ),
+ mTopLayout(0), mMainWidget(0), mUrlHelp(0), mJanus(0), mActionSep(0),
+ mIsActivated(false), mShowTile(false), mMessageBoxMode(false),
+ mButtonOrientation(Horizontal), d(new KDialogBasePrivate)
+{
+ setCaption( caption );
+
+ makeRelay();
+ connect( this, SIGNAL(layoutHintChanged()), SLOT(updateGeometry()) );
+
+ mJanus = new KJanusWidget( this, "janus", dialogFace );
+ connect(mJanus, SIGNAL(aboutToShowPage(QWidget *)),
+ this, SIGNAL(aboutToShowPage(QWidget *)));
+
+ if( !mJanus || !mJanus->isValid() ) { return; }
+
+ enableButtonSeparator( separator );
+ makeButtonBox( buttonMask, defaultButton, user1, user2, user3 );
+
+ mIsActivated = true;
+ setupLayout();
+}
+
+KDialogBase::KDialogBase( const QString &caption, int buttonMask,
+ ButtonCode defaultButton, ButtonCode escapeButton,
+ QWidget *parent, const char *name, bool modal,
+ bool separator, const KGuiItem &yes,
+ const KGuiItem &no, const KGuiItem &cancel )
+ :KDialog( parent, name, modal, WStyle_DialogBorder ),
+ mTopLayout(0), mMainWidget(0), mUrlHelp(0), mJanus(0), mActionSep(0),
+ mIsActivated(false), mShowTile(false), mMessageBoxMode(true),
+ mButtonOrientation(Horizontal),mEscapeButton(escapeButton),
+ d(new KDialogBasePrivate)
+{
+ setCaption( caption );
+
+ makeRelay();
+ connect( this, SIGNAL(layoutHintChanged()), SLOT(updateGeometry()) );
+
+ enableButtonSeparator( separator );
+
+ buttonMask &= Details|Yes|No|Cancel;
+
+ makeButtonBox( buttonMask, defaultButton,
+ no.text().isEmpty() ? KStdGuiItem::no() : no,
+ yes.text().isEmpty() ? KStdGuiItem::yes() : yes );
+
+ setButtonCancel( cancel.text().isEmpty() ?
+ KStdGuiItem::cancel() : cancel );
+
+ mIsActivated = true;
+ setupLayout();
+}
+
+
+
+KDialogBase::~KDialogBase()
+{
+ delete d;
+}
+
+KPushButton *SButton::append( int key, const KGuiItem &item )
+{
+ KDialogBaseButton *p = new KDialogBaseButton( item, key, box );
+ list.append( p );
+ return p;
+}
+
+void SButton::resize( bool sameWidth, int margin,
+ int spacing, int orientation )
+{
+ KDialogBaseButton *p;
+ int h = 0;
+ int w = 0;
+ int t = 0;
+
+ for( p = list.first(); p; p = list.next() )
+ {
+ const QSize s( p->sizeHint() );
+ if( s.height() > h ) { h = s.height(); }
+ if( s.width() > w ) { w = s.width(); }
+ }
+
+ if( orientation == Horizontal )
+ {
+ for( p = list.first(); p; p = list.next() )
+ {
+ QSize s( p->sizeHint() );
+ if( sameWidth ) { s.setWidth( w ); }
+ p->setFixedWidth( s.width() );
+ t += s.width() + spacing;
+ }
+
+ box->setMinimumHeight( margin*2 + h );
+ box->setMinimumWidth( margin*2 + t - spacing );
+ }
+ else
+ {
+ // sameWidth has no effect here
+ for( p = list.first(); p; p = list.next() )
+ {
+ QSize s( p->sizeHint() );
+ s.setWidth( w );
+ p->setFixedSize( s );
+ t += s.height() + spacing;
+ }
+ box->setMinimumHeight( margin*2 + t - spacing );
+ box->setMinimumWidth( margin*2 + w );
+ }
+}
+
+KPushButton *SButton::button( int key )
+{
+ KDialogBaseButton *p;
+ for( p = list.first(); p; p = list.next() )
+ {
+ if( p->id() == key )
+ {
+ return p;
+ }
+ }
+ return 0;
+}
+
+void
+KDialogBase::delayedDestruct()
+{
+ if (isVisible())
+ hide();
+ QTimer::singleShot( 0, this, SLOT(slotDelayedDestruct()));
+}
+
+void
+KDialogBase::slotDelayedDestruct()
+{
+ delete this;
+}
+
+void KDialogBase::setupLayout()
+{
+ if( mTopLayout )
+ {
+ delete mTopLayout;
+ }
+ // mTopLayout = new QVBoxLayout( this, marginHint(), spacingHint() );
+
+
+ if( mButtonOrientation == Horizontal )
+ {
+ mTopLayout = new QBoxLayout( this, QBoxLayout::TopToBottom,
+ marginHint(), spacingHint() );
+ }
+ else
+ {
+ mTopLayout = new QBoxLayout( this, QBoxLayout::LeftToRight,
+ marginHint(), spacingHint() );
+ }
+
+ if( mUrlHelp )
+ {
+ mTopLayout->addWidget( mUrlHelp, 0, AlignRight );
+ }
+
+ if( mJanus )
+ {
+ mTopLayout->addWidget( mJanus, 10 );
+ }
+ else if( mMainWidget )
+ {
+ mTopLayout->addWidget( mMainWidget, 10 );
+ }
+
+ if ( d->detailsWidget )
+ {
+ mTopLayout->addWidget( d->detailsWidget );
+ }
+
+ if( mActionSep )
+ {
+ mTopLayout->addWidget( mActionSep );
+ }
+
+ if( d->mButton.box )
+ {
+ mTopLayout->addWidget( d->mButton.box );
+ }
+}
+
+
+
+void KDialogBase::setButtonBoxOrientation( int orientation )
+{
+ if( mButtonOrientation != orientation )
+ {
+ mButtonOrientation = orientation;
+ if( mActionSep )
+ {
+ mActionSep->setOrientation( mButtonOrientation == Horizontal ?
+ QFrame::HLine : QFrame::VLine );
+ }
+ if( mButtonOrientation == Vertical )
+ {
+ enableLinkedHelp(false); // 2000-06-18 Espen: No support for this yet.
+ }
+ setupLayout();
+ setButtonStyle( d->mButton.style );
+ }
+}
+
+
+void KDialogBase::setEscapeButton( ButtonCode id )
+{
+ mEscapeButton = id;
+}
+
+
+
+void KDialogBase::makeRelay()
+{
+ if( mTile )
+ {
+ connect( mTile, SIGNAL(pixmapChanged()), SLOT(updateBackground()) );
+ return;
+ }
+
+ mTile = new KDialogBaseTile;
+ if( mTile )
+ {
+ connect( mTile, SIGNAL(pixmapChanged()), SLOT(updateBackground()) );
+ connect( qApp, SIGNAL(aboutToQuit()), mTile, SLOT(cleanup()) );
+ }
+}
+
+
+void KDialogBase::enableButtonSeparator( bool state )
+{
+ if( state )
+ {
+ if( mActionSep )
+ {
+ return;
+ }
+ mActionSep = new KSeparator( this );
+ mActionSep->setFocusPolicy(QWidget::NoFocus);
+ mActionSep->setOrientation( mButtonOrientation == Horizontal ?
+ QFrame::HLine : QFrame::VLine );
+ mActionSep->show();
+ }
+ else
+ {
+ if( !mActionSep )
+ {
+ return;
+ }
+ delete mActionSep; mActionSep = 0;
+ }
+
+ if( mIsActivated )
+ {
+ setupLayout();
+ }
+}
+
+
+
+QFrame *KDialogBase::plainPage()
+{
+ return ( mJanus ? mJanus->plainPage() : 0 );
+}
+
+
+
+void KDialogBase::adjustSize()
+{
+// if (layout())
+// layout()->activate();
+ if( d->bFixed )
+ setFixedSize( sizeHint() );
+ else
+ resize( sizeHint() );
+}
+
+QSize KDialogBase::sizeHint() const
+{
+ return d->minSize.expandedTo( minimumSizeHint() ) + d->incSize;
+}
+
+QSize KDialogBase::minimumSizeHint() const
+{
+ const int m = marginHint();
+ const int s = spacingHint();
+
+ const QSize zeroByS(0, s);
+
+ QSize s1(0,0);
+ QSize s2(0,0);
+
+ //
+ // Url help area
+ //
+ if( mUrlHelp )
+ {
+ s2 = mUrlHelp->minimumSize() + zeroByS;
+ }
+ s1.rwidth() = QMAX( s1.rwidth(), s2.rwidth() );
+ s1.rheight() += s2.rheight();
+
+ //
+ // User widget
+ //
+ if( mJanus )
+ {
+ s2 = mJanus->minimumSizeHint() + zeroByS;
+ }
+ else if( mMainWidget )
+ {
+ s2 = mMainWidget->sizeHint() + zeroByS;
+ s2 = s2.expandedTo( mMainWidget->minimumSize() );
+ s2 = s2.expandedTo( mMainWidget->minimumSizeHint() );
+ if( s2.isEmpty() )
+ {
+ s2 = QSize( 100, 100+s );
+ }
+ }
+ else
+ {
+ s2 = QSize( 100, 100+s );
+ }
+ s1.rwidth() = QMAX( s1.rwidth(), s2.rwidth() );
+ s1.rheight() += s2.rheight();
+
+ if (d->detailsWidget && d->bDetails)
+ {
+ s2 = d->detailsWidget->sizeHint() + zeroByS;
+ s2 = s2.expandedTo( d->detailsWidget->minimumSize() );
+ s2 = s2.expandedTo( d->detailsWidget->minimumSizeHint() );
+ s1.rwidth() = QMAX( s1.rwidth(), s2.rwidth() );
+ s1.rheight() += s2.rheight();
+ }
+
+ //
+ // Button separator
+ //
+ if( mActionSep )
+ {
+ s1.rheight() += mActionSep->minimumSize().height() + s;
+ }
+
+ //
+ // The button box
+ //
+ if( d->mButton.box )
+ {
+ s2 = d->mButton.box->minimumSize();
+ if( mButtonOrientation == Horizontal )
+ {
+ s1.rwidth() = QMAX( s1.rwidth(), s2.rwidth() );
+ s1.rheight() += s2.rheight();
+ }
+ else
+ {
+ s1.rwidth() += s2.rwidth();
+ s1.rheight() = QMAX( s1.rheight(), s2.rheight() );
+ }
+ }
+
+ //
+ // Outer margings
+ //
+ s1.rheight() += 2*m;
+ s1.rwidth() += 2*m;
+
+ return s1;
+}
+
+
+void KDialogBase::disableResize()
+{
+ setFixedSize( sizeHint() );
+}
+
+
+void KDialogBase::setInitialSize( const QSize &s, bool noResize )
+{
+ d->minSize = s;
+ d->bFixed = noResize;
+ adjustSize();
+}
+
+
+void KDialogBase::incInitialSize( const QSize &s, bool noResize )
+{
+ d->incSize = s;
+ d->bFixed = noResize;
+ adjustSize();
+}
+
+
+void KDialogBase::makeButtonBox( int buttonMask, ButtonCode defaultButton,
+ const KGuiItem &user1, const KGuiItem &user2,
+ const KGuiItem &user3 )
+{
+ if( buttonMask == 0 )
+ {
+ d->mButton.box = 0;
+ return; // When we want no button box
+ }
+
+ if( buttonMask & Cancel ) { buttonMask &= ~Close; }
+ if( buttonMask & Apply ) { buttonMask &= ~Try; }
+ if( buttonMask & Details ) { buttonMask &= ~Default; }
+
+ if( !mMessageBoxMode )
+ {
+ mEscapeButton = (buttonMask&Cancel) ? Cancel : Close;
+ }
+
+ d->mButton.box = new QWidget( this );
+
+ d->mButton.mask = buttonMask;
+ if( d->mButton.mask & Help )
+ {
+ KPushButton *pb = d->mButton.append( Help, KStdGuiItem::help() );
+
+ connect( pb, SIGNAL(clicked()), SLOT(slotHelp()) );
+ }
+ if( d->mButton.mask & Default )
+ {
+ KPushButton *pb = d->mButton.append( Default, KStdGuiItem::defaults() );
+
+ connect( pb, SIGNAL(clicked()), SLOT(slotDefault()) );
+ }
+ if( d->mButton.mask & Details )
+ {
+ KPushButton *pb = d->mButton.append( Details, QString::null );
+ connect( pb, SIGNAL(clicked()), SLOT(slotDetails()) );
+ setDetails(false);
+ }
+ if( d->mButton.mask & User3 )
+ {
+ KPushButton *pb = d->mButton.append( User3, user3 );
+ connect( pb, SIGNAL(clicked()), SLOT(slotUser3()) );
+ }
+ if( d->mButton.mask & User2 )
+ {
+ KPushButton *pb = d->mButton.append( User2, user2 );
+ if( mMessageBoxMode )
+ {
+ connect( pb, SIGNAL(clicked()), SLOT(slotYes()) );
+ }
+ else
+ {
+ connect( pb, SIGNAL(clicked()), this, SLOT(slotUser2()) );
+ }
+ }
+ if( d->mButton.mask & User1 )
+ {
+ KPushButton *pb = d->mButton.append( User1, user1 );
+ if( mMessageBoxMode )
+ {
+ connect( pb, SIGNAL(clicked()), this, SLOT(slotNo()) );
+ }
+ else
+ {
+ connect( pb, SIGNAL(clicked()), SLOT(slotUser1()) );
+ }
+ }
+ if( d->mButton.mask & Ok )
+ {
+ KPushButton *pb = d->mButton.append( Ok, KStdGuiItem::ok() );
+ connect( pb, SIGNAL(clicked()), SLOT(slotOk()) );
+ }
+ if( d->mButton.mask & Apply )
+ {
+ KPushButton *pb = d->mButton.append( Apply, KStdGuiItem::apply() );
+ connect( pb, SIGNAL(clicked()), SLOT(slotApply()) );
+ connect( pb, SIGNAL(clicked()), SLOT(applyPressed()) );
+ }
+ if( d->mButton.mask & Try )
+ {
+ KPushButton *pb = d->mButton.append( Try,
+ i18n( "&Try" ) );
+ connect( pb, SIGNAL(clicked()), SLOT(slotTry()) );
+ }
+ if( d->mButton.mask & Cancel )
+ {
+ KPushButton *pb = d->mButton.append( Cancel, KStdGuiItem::cancel() );
+ connect( pb, SIGNAL(clicked()), SLOT(slotCancel()) );
+ }
+ if( d->mButton.mask & Close )
+ {
+ KPushButton *pb = d->mButton.append( Close, KStdGuiItem::close() );
+ connect( pb, SIGNAL(clicked()), SLOT(slotClose()) );
+ }
+
+ if( defaultButton != NoDefault )
+ {
+ QPushButton *pb = actionButton( defaultButton );
+ if( pb )
+ {
+ setButtonFocus( pb, true, false );
+ }
+ }
+
+ setButtonStyle( KGlobalSettings::buttonLayout() );
+}
+
+
+
+void KDialogBase::setButtonStyle( int style )
+{
+ if( !d->mButton.box )
+ {
+ return;
+ }
+
+ if( style < 0 || style >= ActionStyleMAX ) { style = ActionStyle0; }
+ d->mButton.style = style;
+
+ const int *layout;
+ int layoutMax = 0;
+ if (mMessageBoxMode)
+ {
+ static const int layoutRule[5][6] =
+ {
+ {Details,Stretch,User2|Stretch,User1|Stretch,Cancel|Stretch, Details|Filler},
+ {Details,Stretch,User2|Stretch,User1|Stretch,Cancel|Stretch, Details|Filler},
+ {Details,Stretch,User2|Stretch,User1|Stretch,Cancel|Stretch, Details|Filler},
+ {Details|Filler,Stretch,Cancel|Stretch,User2|Stretch,User1|Stretch,Details},
+ {Details|Filler,Stretch,Cancel|Stretch,User2|Stretch,User1|Stretch,Details}
+ };
+ layoutMax = 6;
+ layout = layoutRule[ d->mButton.style ];
+ }
+ else if (mButtonOrientation == Horizontal)
+ {
+ static const int layoutRule[5][10] =
+ {
+ {Details,Help,Default,Stretch,User3,User2,User1,Ok,Apply|Try,Cancel|Close},
+ {Details,Help,Default,Stretch,User3,User2,User1,Cancel|Close,Apply|Try,Ok},
+ {Details,Help,Default,Stretch,User3,User2,User1,Apply|Try,Cancel|Close,Ok},
+ {Ok,Apply|Try,Cancel|Close,User3,User2,User1,Stretch,Default,Help,Details},
+ {Ok,Cancel|Close,Apply|Try,User3,User2,User1,Stretch,Default,Help,Details}
+ };
+ layoutMax = 10;
+ layout = layoutRule[ d->mButton.style ];
+ }
+ else
+ {
+ static const int layoutRule[5][10] =
+ {
+ {Ok,Apply|Try,User1,User2,User3,Stretch,Default,Cancel|Close,Help, Details},
+ //{Ok,Apply|Try,Cancel|Close,User1,User2,User3,Stretch, Default,Help, Details},
+ {Details,Help,Default,Stretch,User3,User2,User1,Cancel|Close,Apply|Try,Ok},
+ {Details,Help,Default,Stretch,User3,User2,User1,Apply|Try,Cancel|Close,Ok},
+ {Ok,Apply|Try,Cancel|Close,User3,User2,User1,Stretch,Default,Help,Details},
+ {Ok,Cancel|Close,Apply|Try,User3,User2,User1,Stretch,Default,Help,Details}
+ };
+ layoutMax = 10;
+ layout = layoutRule[ d->mButton.style ];
+ }
+
+ if( d->mButton.box->layout() )
+ {
+ delete d->mButton.box->layout();
+ }
+
+ QBoxLayout *lay;
+ if( mButtonOrientation == Horizontal )
+ {
+ lay = new QBoxLayout( d->mButton.box, QBoxLayout::LeftToRight, 0,
+ spacingHint());
+ }
+ else
+ {
+ lay = new QBoxLayout( d->mButton.box, QBoxLayout::TopToBottom, 0,
+ spacingHint());
+ }
+
+ int numButton = 0;
+ QPushButton *prevButton = 0;
+ QPushButton *newButton;
+
+ for( int i=0; i<layoutMax; ++i )
+ {
+ if(((ButtonCode) layout[i]) == Stretch) // Unconditional Stretch
+ {
+ lay->addStretch(1);
+ continue;
+ }
+ else if (layout[i] & Filler) // Conditional space
+ {
+ if (d->mButton.mask & layout[i])
+ {
+ newButton = actionButton( (ButtonCode) (layout[i] & ~(Stretch | Filler)));
+ if (newButton)
+ lay->addSpacing(newButton->sizeHint().width());
+ }
+ continue;
+ }
+ else if( d->mButton.mask & Help & layout[i] )
+ {
+ newButton = actionButton( Help );
+ lay->addWidget( newButton ); ++numButton;
+ }
+ else if( d->mButton.mask & Default & layout[i] )
+ {
+ newButton = actionButton( Default );
+ lay->addWidget( newButton ); ++numButton;
+ }
+ else if( d->mButton.mask & User3 & layout[i] )
+ {
+ newButton = actionButton( User3 );
+ lay->addWidget( newButton ); ++numButton;
+ }
+ else if( d->mButton.mask & User2 & layout[i] )
+ {
+ newButton = actionButton( User2 );
+ lay->addWidget( newButton ); ++numButton;
+ }
+ else if( d->mButton.mask & User1 & layout[i] )
+ {
+ newButton = actionButton( User1 );
+ lay->addWidget( newButton ); ++numButton;
+ }
+ else if( d->mButton.mask & Ok & layout[i] )
+ {
+ newButton = actionButton( Ok );
+ lay->addWidget( newButton ); ++numButton;
+ }
+ else if( d->mButton.mask & Apply & layout[i] )
+ {
+ newButton = actionButton( Apply );
+ lay->addWidget( newButton ); ++numButton;
+ }
+ else if( d->mButton.mask & Try & layout[i] )
+ {
+ newButton = actionButton( Try );
+ lay->addWidget( newButton ); ++numButton;
+ }
+ else if( d->mButton.mask & Cancel & layout[i] )
+ {
+ newButton = actionButton( Cancel );
+ lay->addWidget( newButton ); ++numButton;
+ }
+ else if( d->mButton.mask & Close & layout[i] )
+ {
+ newButton = actionButton( Close );
+ lay->addWidget( newButton ); ++numButton;
+ }
+ else if( d->mButton.mask & Details & layout[i] )
+ {
+ newButton = actionButton( Details );
+ lay->addWidget( newButton ); ++numButton;
+ }
+ else
+ {
+ continue;
+ }
+
+ // Add conditional stretch (Only added if a button was added)
+ if(layout[i] & Stretch)
+ {
+ lay->addStretch(1);
+ }
+
+ if( prevButton )
+ {
+ setTabOrder( prevButton, newButton );
+ }
+ prevButton = newButton;
+ }
+
+ d->mButton.resize( false, 0, spacingHint(), mButtonOrientation );
+}
+
+
+QPushButton *KDialogBase::actionButton( ButtonCode id )
+{
+ return d->mButton.button(id);
+}
+
+
+void KDialogBase::enableButton( ButtonCode id, bool state )
+{
+ QPushButton *pb = actionButton( id );
+ if( pb )
+ {
+ pb->setEnabled( state );
+ }
+}
+
+
+void KDialogBase::enableButtonOK( bool state )
+{
+ enableButton( Ok, state );
+}
+
+
+void KDialogBase::enableButtonApply( bool state )
+{
+ enableButton( Apply, state );
+}
+
+
+void KDialogBase::enableButtonCancel( bool state )
+{
+ enableButton( Cancel, state );
+}
+
+
+void KDialogBase::showButton( ButtonCode id, bool state )
+{
+ QPushButton *pb = actionButton( id );
+ if( pb )
+ {
+ state ? pb->show() : pb->hide();
+ }
+}
+
+
+void KDialogBase::showButtonOK( bool state )
+{
+ showButton( Ok, state );
+}
+
+
+void KDialogBase::showButtonApply( bool state )
+{
+ showButton( Apply, state );
+}
+
+
+void KDialogBase::showButtonCancel( bool state )
+{
+ showButton( Cancel, state );
+}
+
+
+void KDialogBase::setButtonOKText( const QString &text,
+ const QString &tooltip,
+ const QString &quickhelp )
+{
+ QPushButton *pb = actionButton( Ok );
+ if( !pb )
+ {
+ return;
+ }
+
+ const QString whatsThis = i18n( ""
+ "If you press the <b>OK</b> button, all changes\n"
+ "you made will be used to proceed.");
+
+ pb->setText( text.isEmpty() ? i18n("&OK") : text );
+ d->mButton.resize( false, 0, spacingHint(), mButtonOrientation );
+
+ QToolTip::add( pb, tooltip.isEmpty() ? i18n("Accept settings") : tooltip );
+ QWhatsThis::add( pb, quickhelp.isEmpty() ? whatsThis : quickhelp );
+}
+
+
+void KDialogBase::setButtonOK( const KGuiItem &item /* = KStdGuiItem::ok() */ )
+{
+ setButtonGuiItem( Ok, item );
+}
+
+
+void KDialogBase::setButtonApplyText( const QString &text,
+ const QString &tooltip,
+ const QString &quickhelp )
+{
+ QPushButton *pb = actionButton( Apply );
+ if( !pb )
+ {
+ return;
+ }
+
+ const QString whatsThis = i18n( ""
+ "When clicking <b>Apply</b>, the settings will be\n"
+ "handed over to the program, but the dialog\n"
+ "will not be closed. "
+ "Use this to try different settings. ");
+
+ pb->setText( text.isEmpty() ? i18n("&Apply") : text );
+ d->mButton.resize( false, 0, spacingHint(), mButtonOrientation );
+
+ QToolTip::add( pb, tooltip.isEmpty() ? i18n("Apply settings") : tooltip );
+ QWhatsThis::add( pb, quickhelp.isEmpty() ? whatsThis : quickhelp );
+}
+
+
+void KDialogBase::setButtonApply( const KGuiItem &item /* = KStdGuiItem::apply() */ )
+{
+ setButtonGuiItem( Apply, item );
+}
+
+
+void KDialogBase::setButtonCancelText( const QString& text,
+ const QString& tooltip,
+ const QString& quickhelp )
+{
+ QPushButton *pb = actionButton( Cancel );
+ if( !pb )
+ {
+ return;
+ }
+
+ pb->setText( text.isEmpty() ? i18n("&Cancel") : text );
+ d->mButton.resize( false, 0, spacingHint(), mButtonOrientation );
+
+ QToolTip::add( pb, tooltip );
+ QWhatsThis::add( pb, quickhelp );
+}
+
+
+void KDialogBase::setButtonCancel( const KGuiItem &item /* = KStdGuiItem::cancel() */ )
+{
+ setButtonGuiItem( Cancel, item );
+}
+
+void KDialogBase::setButtonGuiItem( ButtonCode id, const KGuiItem &item )
+{
+ KPushButton *pb = static_cast<KPushButton *>( actionButton( id ) );
+ if( !pb )
+ return;
+
+ pb->setGuiItem( item );
+ d->mButton.resize( false, 0, spacingHint(), mButtonOrientation );
+}
+
+
+void KDialogBase::setButtonText( ButtonCode id, const QString &text )
+{
+ if (!d->bSettingDetails && (id == Details))
+ {
+ d->detailsButton = text;
+ setDetails(d->bDetails);
+ return;
+ }
+ QPushButton *pb = actionButton( id );
+ if( pb )
+ {
+ pb->setText( text );
+ d->mButton.resize( false, 0, spacingHint(), mButtonOrientation );
+ }
+}
+
+
+void KDialogBase::setButtonTip( ButtonCode id, const QString &text )
+{
+ QPushButton *pb = actionButton( id );
+ if( pb )
+ {
+ if (text.isEmpty())
+ QToolTip::remove( pb );
+ else
+ QToolTip::add( pb, text );
+ }
+}
+
+
+void KDialogBase::setButtonWhatsThis( ButtonCode id, const QString &text )
+{
+ QPushButton *pb = actionButton( id );
+ if( pb )
+ {
+ if (text.isEmpty())
+ QWhatsThis::remove( pb );
+ else
+ QWhatsThis::add( pb, text );
+ }
+}
+
+
+void KDialogBase::setButtonFocus( QPushButton *p,bool isDefault, bool isFocus )
+{
+ p->setDefault( isDefault );
+ if( isFocus )
+ p->setFocus();
+}
+
+
+void KDialogBase::setTreeListAutoResize( bool state )
+{
+ if( mJanus )
+ {
+ mJanus->setTreeListAutoResize( state );
+ }
+}
+
+void KDialogBase::setShowIconsInTreeList(bool state)
+{
+ if( mJanus )
+ {
+ mJanus->setShowIconsInTreeList( state );
+ }
+}
+
+void KDialogBase::setRootIsDecorated( bool state )
+{
+ if( mJanus )
+ {
+ mJanus->setRootIsDecorated( state );
+ }
+}
+
+void KDialogBase::unfoldTreeList( bool persist )
+{
+ if( mJanus )
+ mJanus->unfoldTreeList( persist );
+}
+
+void KDialogBase::addWidgetBelowList( QWidget * widget )
+{
+ if( mJanus )
+ mJanus->addWidgetBelowList( widget );
+}
+
+void KDialogBase::addButtonBelowList( const QString & text, QObject * recv, const char * slot )
+{
+ if( mJanus )
+ mJanus->addButtonBelowList( text, recv, slot );
+}
+
+void KDialogBase::addButtonBelowList( const KGuiItem & item, QObject * recv, const char * slot )
+{
+ if( mJanus )
+ mJanus->addButtonBelowList( item, recv, slot );
+}
+
+void KDialogBase::setIconListAllVisible( bool state )
+{
+ if( mJanus )
+ {
+ mJanus->setIconListAllVisible( state );
+ }
+}
+
+
+void KDialogBase::slotHelp()
+{
+ emit helpClicked();
+ if ( kapp ) // may be null when used inside designer
+ kapp->invokeHelp( mAnchor, mHelpApp );
+}
+
+
+void KDialogBase::slotDefault()
+{
+ emit defaultClicked();
+}
+
+void KDialogBase::slotDetails()
+{
+ setDetails(!d->bDetails);
+}
+
+void KDialogBase::setDetailsWidget(QWidget *detailsWidget)
+{
+ delete d->detailsWidget;
+ d->detailsWidget = detailsWidget;
+ if (d->detailsWidget->parentWidget() != this)
+ d->detailsWidget->reparent(this, QPoint(0,0));
+ d->detailsWidget->hide();
+ if( mIsActivated )
+ {
+ setupLayout();
+ }
+ if (!d->bSettingDetails)
+ setDetails(d->bDetails);
+}
+
+void KDialogBase::setDetails(bool showDetails)
+{
+ if (d->detailsButton.isEmpty())
+ d->detailsButton = i18n("&Details");
+ d->bSettingDetails = true;
+ d->bDetails = showDetails;
+ if (d->bDetails)
+ {
+ emit aboutToShowDetails();
+ setButtonText(Details, d->detailsButton+ " <<");
+ if (d->detailsWidget)
+ {
+ if (layout())
+ layout()->setEnabled(false);
+ adjustSize();
+ d->detailsWidget->show();
+ if (layout())
+ {
+ layout()->activate();
+ layout()->setEnabled(true);
+ }
+ }
+ }
+ else
+ {
+ setButtonText(Details, d->detailsButton+" >>");
+ if (d->detailsWidget)
+ {
+ d->detailsWidget->hide();
+ }
+ if (layout())
+ layout()->activate();
+ adjustSize();
+ }
+ d->bSettingDetails = false;
+}
+
+void KDialogBase::slotOk()
+{
+ emit okClicked();
+ accept();
+}
+
+
+void KDialogBase::slotApply()
+{
+ emit applyClicked();
+}
+
+
+void KDialogBase::slotTry()
+{
+ emit tryClicked();
+}
+
+
+void KDialogBase::slotUser3()
+{
+ emit user3Clicked();
+}
+
+
+void KDialogBase::slotUser2()
+{
+ emit user2Clicked();
+}
+
+
+void KDialogBase::slotUser1()
+{
+ emit user1Clicked();
+}
+
+
+void KDialogBase::slotYes()
+{
+ emit yesClicked();
+ done( Yes );
+}
+
+
+void KDialogBase::slotNo()
+{
+ emit noClicked();
+ done( No );
+}
+
+
+void KDialogBase::slotCancel()
+{
+ emit cancelClicked();
+ done( mMessageBoxMode ? (int)Cancel : (int)Rejected );
+}
+
+
+void KDialogBase::slotClose()
+{
+ emit closeClicked();
+ reject();
+}
+
+
+void KDialogBase::helpClickedSlot( const QString & )
+{
+ slotHelp();
+}
+
+
+void KDialogBase::applyPressed()
+{
+ emit apply();
+}
+
+
+void KDialogBase::enableLinkedHelp( bool state )
+{
+ if( state )
+ {
+ if( mUrlHelp )
+ {
+ return;
+ }
+
+ mUrlHelp = new KURLLabel( this, "url" );
+ mUrlHelp->setText( helpLinkText() );
+ mUrlHelp->setFloat(true);
+ mUrlHelp->setUnderline(true);
+ if( mShowTile && mTile->get() )
+ {
+ mUrlHelp->setBackgroundPixmap(*mTile->get());
+ }
+ mUrlHelp->setMinimumHeight( fontMetrics().height() + marginHint() );
+ connect(mUrlHelp,SIGNAL(leftClickedURL(const QString &)),
+ SLOT(helpClickedSlot(const QString &)));
+ mUrlHelp->show();
+ }
+ else
+ {
+ if( !mUrlHelp )
+ {
+ return;
+ }
+ delete mUrlHelp; mUrlHelp = 0;
+ }
+
+ if( mIsActivated )
+ {
+ setupLayout();
+ }
+}
+
+
+void KDialogBase::setHelp( const QString &anchor, const QString &appname )
+{
+ mAnchor = anchor;
+ mHelpApp = appname;
+}
+
+
+void KDialogBase::setHelpLinkText( const QString &text )
+{
+ mHelpLinkText = text;
+ if( mUrlHelp )
+ {
+ mUrlHelp->setText( helpLinkText() );
+ }
+}
+
+
+QFrame *KDialogBase::addPage( const QString &itemName, const QString &header,
+ const QPixmap &pixmap )
+{
+ return ( mJanus ? mJanus->addPage( itemName, header, pixmap ) : 0);
+}
+
+QFrame *KDialogBase::addPage( const QStringList &items, const QString &header,
+ const QPixmap &pixmap )
+{
+ return ( mJanus ? mJanus->addPage( items, header, pixmap ) : 0);
+}
+
+
+QVBox *KDialogBase::addVBoxPage( const QString &itemName,
+ const QString &header, const QPixmap &pixmap )
+{
+ return ( mJanus ? mJanus->addVBoxPage( itemName, header, pixmap) : 0);
+}
+
+QVBox *KDialogBase::addVBoxPage( const QStringList &items,
+ const QString &header, const QPixmap &pixmap )
+{
+ return ( mJanus ? mJanus->addVBoxPage( items, header, pixmap) : 0);
+}
+
+
+QHBox *KDialogBase::addHBoxPage( const QString &itemName,
+ const QString &header,
+ const QPixmap &pixmap )
+{
+ return ( mJanus ? mJanus->addHBoxPage( itemName, header, pixmap ) : 0);
+}
+
+QHBox *KDialogBase::addHBoxPage( const QStringList &items,
+ const QString &header,
+ const QPixmap &pixmap )
+{
+ return ( mJanus ? mJanus->addHBoxPage( items, header, pixmap ) : 0);
+}
+
+
+QGrid *KDialogBase::addGridPage( int n, Orientation dir,
+ const QString &itemName,
+ const QString &header, const QPixmap &pixmap )
+{
+ return ( mJanus ? mJanus->addGridPage( n, dir, itemName, header, pixmap) : 0);
+}
+
+QGrid *KDialogBase::addGridPage( int n, Orientation dir,
+ const QStringList &items,
+ const QString &header, const QPixmap &pixmap )
+{
+ return ( mJanus ? mJanus->addGridPage( n, dir, items, header, pixmap) : 0);
+}
+
+void KDialogBase::setFolderIcon(const QStringList &path, const QPixmap &pixmap)
+{
+ if (!mJanus)
+ return;
+
+ mJanus->setFolderIcon(path,pixmap);
+}
+
+QFrame *KDialogBase::makeMainWidget()
+{
+ if( mJanus || mMainWidget )
+ {
+ printMakeMainWidgetError();
+ return 0;
+ }
+
+ QFrame *mainWidget = new QFrame( this );
+ setMainWidget( mainWidget );
+ return mainWidget;
+}
+
+
+QVBox *KDialogBase::makeVBoxMainWidget()
+{
+ if( mJanus || mMainWidget )
+ {
+ printMakeMainWidgetError();
+ return 0;
+ }
+
+ QVBox *mainWidget = new QVBox( this );
+ mainWidget->setSpacing( spacingHint() );
+ setMainWidget( mainWidget );
+ return mainWidget;
+}
+
+
+QHBox *KDialogBase::makeHBoxMainWidget()
+{
+ if( mJanus || mMainWidget )
+ {
+ printMakeMainWidgetError();
+ return 0;
+ }
+
+ QHBox *mainWidget = new QHBox( this );
+ mainWidget->setSpacing( spacingHint() );
+ setMainWidget( mainWidget );
+ return mainWidget;
+}
+
+
+QGrid *KDialogBase::makeGridMainWidget( int n, Orientation dir )
+{
+ if( mJanus || mMainWidget )
+ {
+ printMakeMainWidgetError();
+ return 0;
+ }
+
+ QGrid *mainWidget = new QGrid( n, dir, this );
+ mainWidget->setSpacing( spacingHint() );
+ setMainWidget( mainWidget );
+ return mainWidget;
+}
+
+
+void KDialogBase::printMakeMainWidgetError()
+{
+ if( mJanus )
+ {
+ kdDebug() << "makeMainWidget: Illegal mode (wrong constructor)" << endl;
+ }
+ else if( mMainWidget )
+ {
+ kdDebug() << "makeMainWidget: Main widget already defined" << endl;
+ }
+}
+
+
+void KDialogBase::setMainWidget( QWidget *widget )
+{
+ if( mJanus )
+ {
+ if( mJanus->setSwallowedWidget(widget) )
+ {
+ mMainWidget = widget;
+ }
+ }
+ else
+ {
+ mMainWidget = widget;
+ if( mIsActivated )
+ {
+ setupLayout();
+ }
+ }
+ if( mMainWidget != NULL )
+ {
+ QFocusData* fd = focusData();
+ QWidget* prev = fd->last();
+ for( QPtrListIterator<KDialogBaseButton> it( d->mButton.list );
+ it != NULL;
+ ++it )
+ {
+ if( prev != *it )
+ setTabOrder( prev, *it );
+ prev = *it;
+ }
+ }
+}
+
+
+QWidget *KDialogBase::mainWidget()
+{
+ return mMainWidget;
+}
+
+
+bool KDialogBase::showPage( int index )
+{
+ return ( mJanus ? mJanus->showPage(index) : false);
+}
+
+
+int KDialogBase::activePageIndex() const
+{
+ return ( mJanus ? mJanus->activePageIndex() : -1);
+}
+
+
+int KDialogBase::pageIndex( QWidget *widget ) const
+{
+ return ( mJanus ? mJanus->pageIndex( widget) : -1);
+}
+
+
+// Deprecated
+QRect KDialogBase::getContentsRect() const
+{
+ QRect r;
+ r.setLeft( marginHint() );
+ r.setTop( marginHint() + (mUrlHelp ? mUrlHelp->height() : 0) );
+ r.setRight( width() - marginHint() );
+ int h = (!mActionSep ? 0 : mActionSep->minimumSize().height()+marginHint());
+ if( d->mButton.box )
+ {
+ r.setBottom( height() - d->mButton.box->minimumSize().height() - h );
+ }
+ else
+ {
+ r.setBottom( height() - h );
+ }
+
+ return r;
+}
+
+
+// Deprecated
+void KDialogBase::getBorderWidths(int& ulx, int& uly, int& lrx, int& lry) const
+{
+ ulx = marginHint();
+ uly = marginHint();
+ if( mUrlHelp )
+ {
+ uly += mUrlHelp->minimumSize().height();
+ }
+
+ lrx = marginHint();
+ lry = d->mButton.box ? d->mButton.box->minimumSize().height() : 0;
+ if( mActionSep )
+ {
+ lry += mActionSep->minimumSize().height() + marginHint();
+ }
+}
+
+
+QSize KDialogBase::calculateSize(int w, int h) const
+{
+ int ulx, uly, lrx, lry;
+ getBorderWidths(ulx, uly, lrx, lry);
+ return QSize(ulx+w+lrx,uly+h+lry);
+}
+
+
+QString KDialogBase::helpLinkText() const
+{
+ return ( mHelpLinkText.isNull() ? i18n("Get help...") : mHelpLinkText );
+}
+
+
+void KDialogBase::updateGeometry()
+{
+ if( mTopLayout )
+ {
+ mTopLayout->setMargin( marginHint() );
+ mTopLayout->setSpacing(spacingHint() );
+ }
+}
+
+
+
+void KDialogBase::keyPressEvent( QKeyEvent *e )
+{
+ //
+ // Reimplemented from KDialog to remove the default behavior
+ // and to add F1 (help) sensitivity and some animation.
+ //
+ if( e->state() == 0 )
+ {
+ if( e->key() == Key_F1 )
+ {
+ QPushButton *pb = actionButton( Help );
+ if( pb )
+ {
+ pb->animateClick();
+ e->accept();
+ return;
+ }
+ }
+ if( e->key() == Key_Escape )
+ {
+ QPushButton *pb = actionButton( mEscapeButton );
+ if( pb )
+ {
+ pb->animateClick();
+ e->accept();
+ return;
+ }
+
+ }
+ }
+ else if( e->key() == Key_F1 && e->state() == ShiftButton )
+ {
+ QWhatsThis::enterWhatsThisMode();
+ e->accept();
+ return;
+ }
+
+ // accept the dialog when Ctrl-Return is pressed
+ else if ( e->state() == ControlButton &&
+ (e->key() == Key_Return || e->key() == Key_Enter) )
+ {
+ QPushButton *pb = actionButton( Ok );
+ if ( pb )
+ {
+ pb->animateClick();
+ e->accept();
+ return;
+ }
+ }
+
+ //
+ // Do the default action instead. Note KDialog::keyPressEvent is bypassed
+ //
+ QDialog::keyPressEvent(e);
+}
+
+
+
+void KDialogBase::hideEvent( QHideEvent *ev )
+{
+ emit hidden();
+ if (!ev->spontaneous())
+ {
+ emit finished();
+ }
+}
+
+
+
+void KDialogBase::closeEvent( QCloseEvent *e )
+{
+ QPushButton *pb = actionButton( mEscapeButton );
+ if( pb && isShown() ) {
+ pb->animateClick();
+ } else {
+ QDialog::closeEvent( e );
+ }
+}
+
+void KDialogBase::cancel()
+{
+ switch ( mEscapeButton ) {
+ case Ok:
+ slotOk();
+ break;
+ case User1: // == No
+ if ( mMessageBoxMode )
+ slotNo();
+ else
+ slotUser1();
+ break;
+ case User2: // == Yes
+ if ( mMessageBoxMode )
+ slotYes();
+ else
+ slotUser2();
+ break;
+ case User3:
+ slotUser3();
+ break;
+ case Close:
+ slotClose();
+ break;
+ case Cancel:
+ default:
+ slotCancel();
+ }
+}
+
+bool KDialogBase::haveBackgroundTile()
+{
+ return ( !mTile || mTile->get() );
+}
+
+// Deprecated. For compatibility only.
+const QPixmap *KDialogBase::getBackgroundTile() { return backgroundTile(); }
+
+const QPixmap *KDialogBase::backgroundTile()
+{
+ return ( mTile ? mTile->get() : 0);
+}
+
+
+void KDialogBase::setBackgroundTile( const QPixmap *pix )
+{
+ if( mTile )
+ {
+ mTile->set( pix );
+ }
+}
+
+
+void KDialogBase::updateBackground()
+{
+ if( !mTile || !mTile->get() )
+ {
+ QPixmap nullPixmap;
+ setBackgroundPixmap(nullPixmap);
+ if( d->mButton.box )
+ {
+ d->mButton.box->setBackgroundPixmap(nullPixmap);
+ d->mButton.box->setBackgroundMode(PaletteBackground);
+ }
+ setBackgroundMode(PaletteBackground);
+ }
+ else
+ {
+ const QPixmap *pix = mTile->get();
+ setBackgroundPixmap(*pix);
+ if( d->mButton.box )
+ {
+ d->mButton.box->setBackgroundPixmap(*pix);
+ }
+ showTile( mShowTile );
+ }
+}
+
+
+void KDialogBase::showTile( bool state )
+{
+ mShowTile = state;
+ if( !mShowTile || !mTile || !mTile->get() )
+ {
+ setBackgroundMode(PaletteBackground);
+ if( d->mButton.box )
+ {
+ d->mButton.box->setBackgroundMode(PaletteBackground);
+ }
+ if( mUrlHelp )
+ {
+ mUrlHelp->setBackgroundMode(PaletteBackground);
+ }
+ }
+ else
+ {
+ const QPixmap *pix = mTile->get();
+ setBackgroundPixmap(*pix);
+ if( d->mButton.box )
+ {
+ d->mButton.box->setBackgroundPixmap(*pix);
+ }
+ if( mUrlHelp )
+ {
+ mUrlHelp->setBackgroundPixmap(*pix);
+ }
+ }
+}
+
+QSize KDialogBase::configDialogSize( const QString& groupName ) const
+{
+ return configDialogSize( *KGlobal::config(), groupName );
+}
+
+
+QSize KDialogBase::configDialogSize( KConfig& config,
+ const QString& groupName ) const
+{
+ int w, h;
+ int scnum = QApplication::desktop()->screenNumber(parentWidget());
+ QRect desk = QApplication::desktop()->screenGeometry(scnum);
+
+ w = sizeHint().width();
+ h = sizeHint().height();
+
+ KConfigGroupSaver cs(&config, groupName);
+ w = config.readNumEntry( QString::fromLatin1("Width %1").arg( desk.width()), w );
+ h = config.readNumEntry( QString::fromLatin1("Height %1").arg( desk.height()), h );
+
+ return QSize( w, h );
+}
+
+
+void KDialogBase::saveDialogSize( const QString& groupName, bool global )
+{
+ saveDialogSize( *KGlobal::config(), groupName, global );
+}
+
+
+void KDialogBase::saveDialogSize( KConfig& config, const QString& groupName,
+ bool global ) const
+{
+ int scnum = QApplication::desktop()->screenNumber(parentWidget());
+ QRect desk = QApplication::desktop()->screenGeometry(scnum);
+
+ KConfigGroupSaver cs(&config, groupName);
+ QSize sizeToSave = size();
+
+ config.writeEntry( QString::fromLatin1("Width %1").arg( desk.width()),
+ QString::number( sizeToSave.width()), true, global);
+ config.writeEntry( QString::fromLatin1("Height %1").arg( desk.height()),
+ QString::number( sizeToSave.height()), true, global);
+}
+
+
+KDialogBaseButton::KDialogBaseButton( const KGuiItem &item, int key,
+ QWidget *parent, const char *name )
+ : KPushButton( item, parent, name ), mKey(key)
+{
+}
+
+
+
+
+KDialogBaseTile::KDialogBaseTile( QObject *parent, const char *name )
+ : QObject( parent, name ), mPixmap(0)
+{
+}
+
+
+KDialogBaseTile::~KDialogBaseTile()
+{
+ cleanup();
+}
+
+
+void KDialogBaseTile::set( const QPixmap *pix )
+{
+ if( !pix )
+ {
+ cleanup();
+ }
+ else
+ {
+ if( !mPixmap )
+ {
+ mPixmap = new QPixmap(*pix);
+ }
+ else
+ {
+ *mPixmap = *pix;
+ }
+ }
+
+ emit pixmapChanged();
+}
+
+
+const QPixmap *KDialogBaseTile::get() const
+{
+ return mPixmap;
+}
+
+
+void KDialogBaseTile::cleanup()
+{
+ delete mPixmap; mPixmap = 0;
+}
+
+void KDialogBase::virtual_hook( int id, void* data )
+{ KDialog::virtual_hook( id, data ); }
+
+#include "kdialogbase.moc"
diff --git a/kdeui/kdialogbase.h b/kdeui/kdialogbase.h
new file mode 100644
index 000000000..fb46587ad
--- /dev/null
+++ b/kdeui/kdialogbase.h
@@ -0,0 +1,1632 @@
+/*
+ * This file is part of the KDE Libraries
+ * Copyright (C) 1999-2001 Mirko Boehm (mirko@kde.org) and
+ * Espen Sand (espen@kde.org)
+ * Holger Freyther <freyther@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#ifndef _KDIALOG_BASE_H_
+#define _KDIALOG_BASE_H_
+
+#include <kdialog.h>
+#include <kjanuswidget.h>
+#include <kguiitem.h>
+#include <kstdguiitem.h>
+#include <qptrlist.h>
+
+class QPushButton;
+class KSeparator;
+class KURLLabel;
+class QBoxLayout;
+class QPixmap;
+class KGuiItem;
+/**
+ * Used internally by KDialogBase.
+ * @internal
+ */
+class KDialogBaseButton;
+
+/**
+ * Used internally by KDialogBase.
+ * @internal
+ */
+class KDialogBaseTile;
+
+/**
+ * @short A dialog base class with standard buttons and predefined layouts.
+ *
+ * Provides basic functionality needed by nearly all dialogs.
+ *
+ * It offers the standard action buttons you'd expect to find in a
+ * dialog as well as the capability to define at most three configurable
+ * buttons. You can define a main widget that contains your specific
+ * dialog layout or you can use a predefined layout. Currently, @p
+ * TreeList/Paged, @p Tabbed, @p Plain, @p Swallow and @p IconList
+ * mode layouts (faces) are available.
+ *
+ * The class takes care of the geometry management. You only need to define
+ * a minimum size for the widget you want to use as the main widget.
+ *
+ * You can set a background tile (pixmap) for parts of the dialog. The
+ * tile you select is shared by all instances of this class in your
+ * application so that they all get the same look and feel.
+ *
+ * There is a tutorial available on http://developer.kde.org/ (NOT YET)
+ * that contains
+ * copy/paste examples as well a screenshots on how to use this class.
+ *
+ * <b>Standard buttons (action buttons):</b>\n
+ *
+ * You select which buttons should be displayed, but you do not choose the
+ * order in which they are displayed. This ensures a standard interface in
+ * KDE. The button order can be changed, but this ability is only available
+ * for a central KDE control tool. The following buttons are available:
+ * OK, Cancel/Close, Apply/Try, Default, Help and three user definable
+ * buttons: User1, User2 and User3. You must specify the text of the UserN
+ * buttons. Each button has a virtual slot so you can overload the method
+ * when required. The default slots emit a signal as well, so you can choose
+ * to connect a signal instead of overriding the slot.
+ * The default implementation of slotHelp() will automatically enable
+ * the help system if you have provided a path to the help text.
+ * slotCancel() and slotClose() will run QDialog::reject()
+ * while slotOk() will run QDialog::accept(). You define a default
+ * button in the constructor.
+ *
+ * If you don't want any buttons at all because your dialog is special
+ * in some way, then set the buttonMask argument in the constructor to zero
+ * (0). The optional button box separator line should not be enabled
+ * in this case. Note that the KDialogBase will animate a button press
+ * when the user press Escape. The button that is enabled is either Cancel,
+ * Close or the button that is defined by setEscapeButton() The
+ * animation will not take place when the buttonMask is zero. Your
+ * custom dialog code should reimplement the keyPressEvent and
+ * animate the cancel button so that the dialog behaves like regular
+ * dialogs. NOTE: None of the regular slots (like slotOk() ) or
+ * signals that are related to the standard action buttons will be used
+ * when you don't use these buttons.
+ *
+ * <b>Dialog shapes:</b>\n
+ *
+ * You can either use one of the prebuilt, easy to use, faces or
+ * define your own main widget. The dialog provides ready to use
+ * TreeList, Tabbed, Plain, Swallow and IconList faces. KDialogBase uses
+ * the KJanusWidget class internally to accomplish this. If you
+ * use TreeList, Tabbed or IconList mode, then add pages with addPage().
+ *
+ * Pages that have been added can be removed again by simply deleting
+ * the page.
+ *
+ * If you want complete control of how the dialog contents should look,
+ * then you can define a main widget by using setMainWidget(). You
+ * only need to set the minimum size of that widget and the dialog will
+ * resize itself to fit this minimum size. The dialog is resizeable, but
+ * cannot be made smaller than its minimum size.
+ *
+ * <b>Layout:</b>\n
+ *
+ * The dialog consists of a help area on top (becomes visible if you define
+ * a help path and use enableLinkedHelp()), the main area which is
+ * the built-in dialog face or your own widget in the middle and by default
+ * a button box at the bottom. The button box can also be placed at the
+ * right edge (to the right of the main widget). Use
+ * setButtonBoxOrientation() to control this behavior. A separator
+ * can be placed above the button box (or to the left when the button box
+ * is at the right edge). Normally you specify that you want a separator
+ * in the constructor, but you can use enableButtonSeparator() as well.
+ *
+ * <b>Standard compliance:</b>\n
+ *
+ * The class is derived from KDialog, so you get automatic access to
+ * the KDialog::marginHint(), KDialog::spacingHint() and the
+ * extended KDialog::setCaption() method. NOTE: The main widget you
+ * use will be positioned inside the dialog using a margin (or border)
+ * equal to KDialog::marginHint(). You should not add a margin yourself,
+ * since one will be added automatically.
+ * The example below (from kedit) shows how you use the top level widget
+ * and its layout. The second argument (the border) to QVBoxLayout
+ * is 0. This situation is valid for addPage , addVBoxPage ,
+ * addHBoxPage , addGridPage , makeMainWidget ,
+ * makeVBoxMainWidget , makeHBoxMainWidget and
+ * makeGridMainWidget as well.
+ *
+ * Example:
+ *
+ * \code
+ * UrlDlg::UrlDlg( QWidget *parent, const QString& caption,
+ * const QString& urltext)
+ * : KDialogBase( parent, "urldialog", true, caption, Ok|Cancel, Ok, true )
+ * {
+ * QWidget *page = new QWidget( this );
+ * setMainWidget(page);
+ * QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
+ *
+ * QLabel *label = new QLabel( caption, page, "caption" );
+ * topLayout->addWidget( label );
+ *
+ * lineedit = new QLineEdit( urltext, page, "lineedit" );
+ * lineedit->setMinimumWidth(fontMetrics().maxWidth()*20);
+ * topLayout->addWidget( lineedit );
+ *
+ * topLayout->addStretch(10);
+ * }
+ * \endcode
+ *
+ * If you use makeVBoxMainWidget(), then the dialog above can be made
+ * simpler but you lose the ability to add a stretchable area:
+ *
+ * \code
+ * UrlDlg::UrlDlg( QWidget *parent, const QString& caption,
+ * const QString& urltext)
+ * : KDialogBase( parent, "urldialog", true, caption, Ok|Cancel, Ok, true )
+ * {
+ * QVBox *page = makeVBoxMainWidget();
+ * QLabel *label = new QLabel( caption, page, "caption" );
+ *
+ * lineedit = new QLineEdit( urltext, page, "lineedit" );
+ * lineedit->setMinimumWidth(fontMetrics().maxWidth()*20);
+ * }
+ * \endcode
+ *
+ * This class can be used in many ways. Note that most KDE ui widgets
+ * and many of KDE core applications use the KDialogBase so for more
+ * inspiration you should study the code for these.
+ *
+ * @author Mirko Boehm (mirko@kde.org) and Espen Sand (espen@kde.org)
+ */
+class KDEUI_EXPORT KDialogBase : public KDialog
+{
+ Q_OBJECT
+
+ public:
+
+ enum ButtonCode
+ {
+ Help = 0x00000001, ///< Show Help button.
+ Default = 0x00000002, ///< Show Default button.
+ Ok = 0x00000004, ///< Show Ok button.
+ Apply = 0x00000008, ///< Show Apply button.
+ Try = 0x00000010, ///< Show Try button.
+ Cancel = 0x00000020, ///< Show Cancel-button.
+ Close = 0x00000040, ///< Show Close-button.
+ User1 = 0x00000080, ///< Show User defined button 1.
+ User2 = 0x00000100, ///< Show User defined button 2.
+ User3 = 0x00000200, ///< Show User defined button 3.
+ No = 0x00000080, ///< Show No button.
+ Yes = 0x00000100, ///< Show Yes button.
+ Details = 0x00000400, ///< Show Details button.
+ Filler = 0x40000000, ///< @internal Ignored when used in a constructor.
+ Stretch = 0x80000000, ///< @internal Ignored when used in a constructor.
+ NoDefault ///< Used when specifying a default button; indicates that no button should be marked by default. @since 3.3
+ };
+
+ enum ActionButtonStyle
+ {
+ ActionStyle0=0, // KDE std
+ ActionStyle1,
+ ActionStyle2,
+ ActionStyle3,
+ ActionStyle4,
+ ActionStyleMAX
+ };
+
+ /**
+ * @li @p TreeList - A dialog with a tree on the left side and a
+ * representation of the contents on the right side.
+ * @li @p Tabbed - A dialog using a QTabWidget.
+ * @li @p Plain - A normal dialog. Use plainPage() as parent for widgets.
+ * @li @p Swallow - Simplifes the usage of existing widgets. You specify
+ * the widget to be displayed by setMainWidget().
+ * @li @p IconList - A dialog with an iconlist on the left side and a
+ * representation of the contents on the right side.
+ */
+ enum DialogType
+ {
+ TreeList = KJanusWidget::TreeList,
+ Tabbed = KJanusWidget::Tabbed,
+ Plain = KJanusWidget::Plain,
+ Swallow = KJanusWidget::Swallow,
+ IconList = KJanusWidget::IconList
+ };
+
+ public:
+
+ /**
+ * Constructor for the standard mode where you must specify the main
+ * widget with setMainWidget() .
+ *
+ * @param parent Parent of the dialog.
+ * @param name Dialog name (for internal use only)
+ * @param modal Controls dialog modality. If @p false, the rest of the
+ * program interface (example: other dialogs) is accessible while
+ * the dialog is open.
+ * @param caption The dialog caption. Do not specify the application name
+ * here. The class will take care of that.
+ * @param buttonMask Specifies which buttons will be visible. If zero
+ * (0) no button box will be made.
+ * @param defaultButton Specifies which button will be marked as
+ * the default. Use ButtonCode::NoDefault to indicate that no button
+ * should be marked as the default button.
+ * @param separator If @p true, a separator line is drawn between the
+ * action buttons and the main widget.
+ * @param user1 User button1 item.
+ * @param user2 User button2 item.
+ * @param user3 User button3 item.
+ */
+ KDialogBase( QWidget *parent=0, const char *name=0, bool modal=true,
+ const QString &caption=QString::null,
+ int buttonMask=Ok|Apply|Cancel, ButtonCode defaultButton=Ok,
+ bool separator=false,
+ const KGuiItem &user1=KGuiItem(),
+ const KGuiItem &user2=KGuiItem(),
+ const KGuiItem &user3=KGuiItem() );
+
+ /**
+ * In KDE4 a WFlag paramater should be added after modal and next
+ * function can be removed.
+ *
+ * Constructor for the predefined layout mode where you specify the
+ * kind of layout (face).
+ *
+ * @param dialogFace You can use TreeList, Tabbed, Plain, Swallow or
+ * IconList.
+ * @param caption The dialog caption. Do not specify the application name
+ * here. The class will take care of that.
+ * @param buttonMask Specifies which buttons will be visible. If zero
+ * (0) no button box will be made.
+ * @param defaultButton Specifies which button will be marked as
+ * the default. Use ButtonCode::NoDefault to indicate that no button
+ * should be marked as the default button.
+ * @param parent Parent of the dialog.
+ * @param name Dialog name (for internal use only).
+ * @param modal Controls dialog modality. If @p false, the rest of the
+ * program interface (example: other dialogs) is accessible while
+ * the dialog is open.
+ * @param separator If @p true, a separator line is drawn between the
+ * action buttons and the main widget.
+ * @param user1 User button1 text item.
+ * @param user2 User button2 text item.
+ * @param user3 User button3 text item.
+ */
+ KDialogBase( int dialogFace, const QString &caption,
+ int buttonMask, ButtonCode defaultButton,
+ QWidget *parent=0, const char *name=0, bool modal=true,
+ bool separator=false,
+ const KGuiItem &user1=KGuiItem(),
+ const KGuiItem &user2=KGuiItem(),
+ const KGuiItem &user3=KGuiItem() );
+
+
+ /**
+ * Constructor for the predefined layout mode where you specify the
+ * kind of layout (face).
+ *
+ * @param dialogFace You can use TreeList, Tabbed, Plain, Swallow or
+ * IconList.
+ * @param f widget flags, by default it is just set to WStyle_DialogBorder.
+ * @param caption The dialog caption. Do not specify the application name
+ * here. The class will take care of that.
+ * @param parent Parent of the dialog.
+ * @param name Dialog name (for internal use only).
+ * @param modal Controls dialog modality. If @p false, the rest of the
+ * program interface (example: other dialogs) is accessible while
+ * the dialog is open.
+ * @param buttonMask Specifies which buttons will be visible. If zero
+ * (0) no button box will be made.
+ * @param defaultButton Specifies which button will be marked as
+ * the default. Use ButtonCode::NoDefault to indicate that no button
+ * should be marked as the default button.
+ * @param separator If @p true, a separator line is drawn between the
+ * action buttons and the main widget.
+ * @param user1 User button1 text item.
+ * @param user2 User button2 text item.
+ * @param user3 User button3 text item.
+ * @since: 3.2
+ */
+
+ KDialogBase( KDialogBase::DialogType dialogFace, WFlags f,
+ QWidget *parent=0, const char *name=0, bool modal=true,
+ const QString &caption=QString::null,
+ int buttonMask=Ok|Apply|Cancel, ButtonCode defaultButton=Ok,
+ bool separator=false,
+ const KGuiItem &user1=KGuiItem(),
+ const KGuiItem &user2=KGuiItem(),
+ const KGuiItem &user3=KGuiItem() );
+
+ /**
+ * Constructor for a message box mode where the @p buttonMask can only
+ * contain Yes, No, or Cancel.
+ *
+ * If you need other names you can rename
+ * the buttons with setButtonText(). The dialog box is not resizable
+ * by default but this can be changed by setInitialSize(). If you
+ * select 'modal' to be true, the dialog will return Yes, No, or Cancel
+ * when closed otherwise you can use the signals yesClicked(),
+ * noClicked(), or cancelClicked() to determine the state.
+ *
+ * @param caption The dialog caption. Do not specify the application name
+ * here. The class will take care of that.
+ * @param buttonMask Specifies which buttons will be visible. If zero
+ * (0) no button box will be made.
+ * @param defaultButton Specifies which button will be marked as
+ * the default. Use ButtonCode::NoDefault to indicate that no button
+ * should be marked as the default button.
+ * @param escapeButton Specifies which button will be activated by
+ * when the dialog receives a @p Key_Escape keypress.
+ * @param parent Parent of the dialog.
+ * @param name Dialog name (for internal use only).
+ * @param modal Controls dialog modality. If @p false, the rest of the
+ * program interface (example: other dialogs) is accessible
+ * while the dialog is open.
+ * @param separator If @p true, a separator line is drawn between the
+ * action buttons and the main widget.
+ * @param yes Text to use for the first button (defaults to i18n("Yes"))
+ * @param no Text to use for the second button (defaults to i18n("No"))
+ * @param cancel Text to use for the third button (defaults to i18n("Cancel"))
+ */
+ KDialogBase( const QString &caption, int buttonMask=Yes|No|Cancel,
+ ButtonCode defaultButton=Yes, ButtonCode escapeButton=Cancel,
+ QWidget *parent=0, const char *name=0,
+ bool modal=true, bool separator=false,
+ const KGuiItem &yes = KStdGuiItem::yes(), // i18n("&Yes")
+ const KGuiItem &no = KStdGuiItem::no(), // i18n("&No"),
+ const KGuiItem &cancel = KStdGuiItem::cancel() // i18n("&Cancel")
+ );
+
+ /**
+ * Destructor.
+ */
+ ~KDialogBase();
+
+ /**
+ * Sets the orientation of the button box.
+ *
+ * It can be @p Vertical or @p Horizontal. If @p Horizontal
+ * (default), the button box is positioned at the bottom of the
+ * dialog. If @p Vertical it will be placed at the right edge of the
+ * dialog.
+ *
+ * @param orientation The button box orientation.
+ */
+ void setButtonBoxOrientation( int orientation );
+
+ /**
+ * Sets the button that will be activated when the Escape key
+ * is pressed.
+ *
+ * Normally you should not use this function. By default,
+ * the Escape key is mapped to either the Cancel or the Close button
+ * if one of these buttons are defined. The user expects that Escape will
+ * cancel an operation so use this function with caution.
+ *
+ * @param id The button code.
+ */
+ void setEscapeButton( ButtonCode id );
+
+
+ /**
+ * Adjust the size of the dialog to fit the contents just before
+ * QDialog::exec() or QDialog::show() is called.
+ *
+ * This method will not be called if the dialog has been explicitly
+ * resized before showing it.
+ **/
+ virtual void adjustSize();
+ virtual QSize sizeHint() const;
+ virtual QSize minimumSizeHint() const;
+
+ /**
+ * Retrieve the empty page when the predefined layout is used in @p Plain
+ * mode.
+ *
+ * This widget must be used as the toplevel widget of your dialog
+ * code.
+ *
+ * @return The widget or 0 if the predefined layout mode is not @p Plain
+ * or if you don't use any predefined layout.
+ */
+ QFrame *plainPage();
+
+ /**
+ * Add a page to the dialog when the class is used in @p TreeList ,
+ * @p IconList or @p Tabbed mode.
+ *
+ * The returned widget must be used as the
+ * toplevel widget for this particular page.
+ * Note: The returned frame widget has no
+ * layout manager associated with it. In order to use it you must
+ * create a layout yourself as the example below illustrates:
+ *
+ * \code
+ * QFrame *page = addPage( i18n("Layout") );
+ * QVBoxLayout *topLayout = new QVBoxLayout( page, 0, KDialog::spacingHint() );
+ * QLabel *label = new QLabel( i18n("Layout type"), page );
+ * topLayout->addWidget( label );
+ * ..
+ * \endcode
+ *
+ * @param itemName String used in the list or as tab item name.
+ * @param header Header text use in the list modes. Ignored in @p Tabbed
+ * mode. If empty, the item text is used instead.
+ * @param pixmap Used in @p IconList mode. You should prefer a pixmap
+ * with size 32x32 pixels.
+ *
+ * @return The page widget which must be used as the toplevel widget for
+ * the page.
+ */
+ QFrame *addPage( const QString &itemName,
+ const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * This is like addPage() just above, with the difference that the first
+ * element is a list of strings.
+ *
+ * These strings are used to form a path
+ * of folders down to the given page. The initial elements are names
+ * for the folders, while the last element is the name of the page.
+ * Note: This does yet only work for the @p TreeList face. Later this may
+ * be added for the @p IconList face too. In other faces than the
+ * @p TreeList, all the strings except the last one is ignored.
+ **/
+ QFrame *addPage( const QStringList &items,
+ const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * Add a page to the dialog when the class is used in @p TreeList,
+ * @p IconList or @p Tabbed mode.
+ *
+ * The returned widget must be used as the toplevel widget for
+ * this particular page. The widget contains a QVBoxLayout
+ * layout so the widget children are lined up vertically. You can
+ * use it as follows:
+ *
+ * \code
+ * QVBox *page = addVBoxPage( i18n("Layout") );
+ * QLabel *label = new QLabel( i18n("Layout type"), page );
+ * ..
+ * \endcode
+ *
+ * @param itemName String used in the list or as tab item name.
+ * @param header Header text use in the list modes. Ignored in @p Tabbed
+ * mode. If empty, the item text is used instead.
+ * @param pixmap Used in @p IconList mode. You should prefer a pixmap
+ * with size 32x32 pixels.
+ *
+ * @return The page widget which must be used as the toplevel widget for
+ * the page.
+ */
+ QVBox *addVBoxPage( const QString &itemName,
+ const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * This is like addVBoxPage() just above, with the difference
+ * that the first element is a list of strings.
+ *
+ * These strings are used to form a path
+ * of folders down to the given page. The initial elements are names
+ * for the folders, while the last element is the name of the page.
+ * Note: This does yet only work for the @p TreeList face. Later this may
+ * be added for the @p IconList face too. In other faces than the
+ * @p TreeList, all the strings except the last one is ignored.
+ **/
+ QVBox *addVBoxPage( const QStringList &items,
+ const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * Add a page to the dialog when the class is used in @p TreeList,
+ * @p IconList or @p Tabbed mode.
+ *
+ * The returned widget must be used as the
+ * toplevel widget for this particular page. The widget contains a
+ * QHBoxLayout layout so the widget children are lined up horizontally.
+ * You can use it as follows:
+ *
+ * @param itemName String used in the list or as tab item name.
+ * @param header Header text use in the list modes. Ignored in Tabbed
+ * mode. If empty, the item text is used instead.
+ * @param pixmap Used in IconList mode. You should prefer a pixmap
+ * with size 32x32 pixels.
+ *
+ * @return The page widget which must be used as the toplevel widget for
+ * the page.
+ */
+ QHBox *addHBoxPage( const QString &itemName,
+ const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * This is like addHBoxPage() just above, with the
+ * difference that the first element is a list of strings.
+ *
+ * These strings are used to form a path
+ * of folders down to the given page. The initial elements are names
+ * for the folders, while the last element is the name of the page.
+ * Note: This does yet only work for the @p TreeList face. Later this may
+ * be added for the @p IconList face too. In other faces than the
+ * @p TreeList, all the strings except the last one is ignored.
+ **/
+ QHBox *addHBoxPage( const QStringList &items,
+ const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * Add a page to the dialog when the class is used in @p TreeList,
+ * @p IconList or @p Tabbed mode.
+ *
+ * The returned widget must be used as the
+ * toplevel widget for this particular page. The widget contains a
+ * QGridLayout layout so the widget children are positioned in a grid.
+ *
+ * @param n Specifies the number of columns if @p dir is Qt::Horizontal
+ * or the number of rows if @p dir is Qt::Vertical.
+ * @param dir Can be Qt::Horizontal or Qt::Vertical.
+ * @param itemName String used in the list or as tab item name.
+ * @param header Header text use in the list modes @p Ignored in @p Tabbed
+ * mode. If empty, the item text is used instead.
+ * @param pixmap Used in @p IconList mode. You should prefer a pixmap
+ * with size 32x32 pixels.
+ *
+ * @return The page widget which must be used as the toplevel widget for
+ * the page.
+ */
+ QGrid *addGridPage( int n, Orientation dir,
+ const QString &itemName,
+ const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+
+ /**
+ * This is like addGridPage() just above, with the difference
+ * that the first element is a list of strings.
+ *
+ * These strings are used to form a path
+ * of folders down to the given page. The initial elements are names
+ * for the folders, while the last element is the name of the page.
+ * Note: This does yet only work for the @p TreeList face. Later this may
+ * be added for the @p IconList face too. In other faces than the
+ * @p TreeList, all the strings except the last one is ignored.
+ **/
+ QGrid *addGridPage( int n, Orientation dir,
+ const QStringList &items,
+ const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+
+ /**
+ * Sets the icon used in @p TreeList Mode for the given path.
+ *
+ * @param path The path for which this icon should be shown.
+ * @param pixmap The icon used.
+ **/
+ void setFolderIcon(const QStringList &path,const QPixmap &pixmap);
+
+ /**
+ * Make a main widget.
+ *
+ * The function will make a QFrame widget
+ * and use setMainWidget() to register it. You can @em not use this
+ * function more than once, @em not if you have already defined a
+ * main widget with setMainWidget() and @em not if you have used the
+ * constructor where you define the face (@p Plain, @p Swallow, @p Tabbed,
+ * @p TreeList).
+ *
+ * @return The main widget or 0 if any of the rules described above
+ * were broken.
+ */
+ QFrame *makeMainWidget();
+
+ /**
+ * Make a main widget.
+ *
+ * The function will make a QVBox widget
+ * and use setMainWidget() to register it. You @em can use this
+ * function more than once, but @em not if you have already defined a
+ * main widget with setMainWidget() and @em not if you have used the
+ * constructor where you define the face (@p Plain, @p Swallow, @p Tabbed,
+ * @p TreeList, @p IconList).
+ *
+ * @return The main widget or 0 if any of the rules described above
+ * were broken.
+ */
+ QVBox *makeVBoxMainWidget();
+
+ /**
+ * Make a main widget.
+ *
+ * The function will make a QHBox widget
+ * and use setMainWidget() to register it. You can @em not use this
+ * function more than once, @em not if you have already defined a
+ * main widget with setMainWidget() and @p not if you have used the
+ * constructor where you define the face (@p Plain, @p Swallow, @p Tabbed,
+ * @p TreeList, @p IconList).
+ *
+ * @return The main widget or 0 if any of the rules described above
+ * were broken.
+ */
+ QHBox *makeHBoxMainWidget();
+
+ /**
+ * Make a main widget.
+ *
+ * The function will make a QGrid widget
+ * and use setMainWidget() to register it. You can @em not use this
+ * function more than once, @em not if you have already defined a
+ * main widget with setMainWidget and @em not if you have used the
+ * constructor where you define the face (Plain, Swallow, Tabbed,
+ * TreeList, IconList).
+ *
+ * @param n Specifies the number of columns if 'dir' is Qt::Horizontal
+ * or the number of rows if 'dir' is Qt::Vertical.
+ * @param dir Can be Qt::Horizontal or Qt::Vertical.
+ *
+ * @return The main widget or 0 if any of the rules described above
+ * were broken.
+ */
+ QGrid *makeGridMainWidget( int n, Orientation dir );
+
+
+ /**
+ * Hide or display the a separator line drawn between the action
+ * buttons an the main widget.
+ */
+ void enableButtonSeparator( bool state );
+
+ /**
+ * Hide or display a general action button.
+ *
+ * Only buttons that have
+ * been created in the constructor can be displayed. This method will
+ * not create a new button.
+ *
+ * @param id Button identifier.
+ * @param state true display the button(s).
+ */
+ void showButton( ButtonCode id, bool state );
+
+ /**
+ * Hide or display the OK button.
+ *
+ * The OK button must have
+ * been created in the constructor to be displayed.
+ *
+ * @param state If @p true, display the button(s).
+ */
+ void showButtonOK( bool state );
+
+ /**
+ * Hide or display the Apply button.
+ *
+ * The Apply button must have
+ * been created in the constructor to be displayed.
+ *
+ * @param state true display the button(s).
+ */
+ void showButtonApply( bool state );
+
+ /**
+ * Hide or display the Cancel button. The Cancel button must have
+ * been created in the constructor to be displayed.
+ *
+ * @param state @p true display the button(s).
+ */
+ void showButtonCancel( bool state );
+
+ /**
+ * Sets the page with @p index to be displayed.
+ *
+ * This method will only
+ * work when the dialog is using the predefined shape of TreeList,
+ * IconList or Tabbed.
+ *
+ * @param index Index of the page to be shown.
+ * @return @p true if the page is shown, @p false otherwise.
+ */
+ bool showPage( int index );
+
+ /**
+ * Returns the index of the active page.
+ *
+ * This method will only work when the dialog is using the
+ * predefined shape of Tabbed, TreeList or IconList.
+ *
+ * @return The page index or -1 if there is no active page.
+ */
+ int activePageIndex() const;
+
+
+ /**
+ * Returns the index of a page created with addPage(),
+ * addVBoxPage(), addHBoxPage() or addGridPage().
+ * You can can compare this index with the value returned from
+ * activePageIndex() if you need to do some page specific actions
+ * in your code.
+ *
+ * The returned index will never change so you can safely use this
+ * function once and save the value.
+ *
+ * @param widget The widget returned by addPage(), addVBoxPage(),
+ * addHBoxPage() or addGridPage().
+ *
+ * @return The index or -1 if the face is not Tabbed, TreeList or
+ * IconList
+ */
+ int pageIndex( QWidget *widget ) const;
+
+
+ /**
+ * Sets the main user definable widget.
+ *
+ * If the dialog is using the predefined Swallow mode, the widget will
+ * be reparented to the internal swallow control widget. If the dialog
+ * is being used in the standard mode then the @p widget must have the
+ * dialog as parent.
+ *
+ * @param widget The widget to be displayed as main widget. If it
+ * is 0, then the dialog will show an empty space of 100x100 pixels
+ * instead.
+ */
+ void setMainWidget( QWidget *widget );
+
+ /**
+ * Returns the main widget if any.
+ *
+ * @return The current main widget. Can be 0 if no widget has been defined.
+ */
+ QWidget *mainWidget();
+
+ /**
+ * Convenience method.
+ *
+ * Freezes the dialog size using the minimum size
+ * of the dialog. This method should only be called right before
+ * show() or exec().
+ */
+ void disableResize();
+
+ /**
+ * Convenience method. Sets the initial dialog size.
+ *
+ * This method should
+ * only be called right before show() or exec(). The initial
+ * size will be
+ * ignored if smaller than the dialog's minimum size.
+ *
+ * @param s Startup size.
+ * @param noResize If @p true the dialog cannot be resized.
+ */
+ void setInitialSize( const QSize &s, bool noResize=false );
+
+ /**
+ * Convenience method. Add a size to the default minimum size of a
+ * dialog.
+ *
+ * This method should only be called right before show() or
+ * exec().
+ *
+ * @param s Size added to minimum size.
+ * @param noResize If @p true the dialog cannot be resized.
+ */
+ void incInitialSize( const QSize &s, bool noResize=false );
+
+ /**
+ * read the dialogs size from the configuration according to the screen size.
+ * If no size is saved for one dimension of the screen, sizeHint() is returned.
+ *
+ * @param groupName Name of the group to read from. The old group
+ * of KGlobal::config is preserved.
+ */
+ QSize configDialogSize( const QString& groupName ) const;
+
+ /**
+ * read the dialogs size from the configuration according to the screen size.
+ * If no size is saved for one dimension of the screen, sizeHint() is returned.
+ *
+ * @param config The KConfig object to read from
+ * @param groupName Name of the group to read from. The old group
+ * of KGlobal::config is preserved.
+ * @since 3.2
+ */
+ QSize configDialogSize( KConfig& config, const QString& groupName ) const;
+
+ /**
+ * save the dialogs size dependant on the screen dimension either to the
+ * global or application config file.
+ *
+ * @param groupName The group to which the dialogs size is saved. See configDialogSize
+ * to read the size.
+ * @param global Set to true if the entry should go to the global config rather
+ * than to the applications config. Default is false.
+ */
+ void saveDialogSize( const QString& groupName, bool global=false );
+
+ /**
+ * save the dialogs size dependant on the screen dimension.
+ *
+ * @param config The KConfig object to write to.
+ * @param groupName The group to which the dialogs size is saved. See
+ * configDialogSize to read the size.
+ * @param global Set to true if the entry should go to the global config.
+ * Default is false.
+ * @since 3.2
+ */
+ void saveDialogSize( KConfig& config, const QString& groupName,
+ bool global=false ) const;
+
+ /**
+ * Sets the appearance of the OK button.
+ *
+ * If the default parameters are used
+ * (that is, if no KGuiItem is given) KStdGuiItem::ok() is used.
+ *
+ * @param item KGuiItem.
+ * @since 3.2
+ */
+ void setButtonOK( const KGuiItem &item = KStdGuiItem::ok() );
+
+ /**
+ * @deprecated. Use setButtonOk() instead.
+ *
+ * Sets the text of the OK button.
+ *
+ * If the default parameters are used
+ * (that is, if no parameters are given) the standard texts are set:
+ * The button shows "OK", the tooltip contains "Accept settings."
+ * (internationalized) and the quickhelp text explains the standard
+ * behavior of the OK button in settings dialogs.
+ *
+ * @param text Button text.
+ * @param tooltip Tooltip text.
+ * @param quickhelp Quick help text.
+ */
+ void setButtonOKText( const QString &text=QString::null,
+ const QString &tooltip=QString::null,
+ const QString &quickhelp=QString::null ) KDE_DEPRECATED;
+
+ /**
+ * Sets the appearance of the Apply button.
+ *
+ * If the default parameters are used
+ * (that is, if no KGuiItem is given) KStdGuiItem::apply() is used.
+ *
+ * @param item KGuiItem.
+ * @since 3.2
+ */
+ void setButtonApply( const KGuiItem &item = KStdGuiItem::apply() );
+
+ /**
+ * @deprecated. Use setButtonApply() instead.
+ *
+ * Sets the text of the Apply button.
+ *
+ * If the default parameters are
+ * used (that is, if no parameters are given) the standard texts are set:
+ * The button shows "Apply", the tooltip contains "Apply settings."
+ * (internationalized) and the quickhelp text explains the standard
+ * behavior of the apply button in settings dialogs.
+ *
+ * @param text Button text.
+ * @param tooltip Tooltip text.
+ * @param quickhelp Quick help text.
+ */
+ void setButtonApplyText( const QString &text=QString::null,
+ const QString &tooltip=QString::null,
+ const QString &quickhelp=QString::null ) KDE_DEPRECATED;
+
+ /**
+ * Sets the appearance of the Cancel button.
+ *
+ * If the default parameters are used
+ * (that is, if no KGuiItem is given) KStdGuiItem::cancel() is used.
+ *
+ * @param item KGuiItem.
+ * @since 3.2
+ */
+ void setButtonCancel( const KGuiItem &item = KStdGuiItem::cancel() );
+
+ /**
+ * @deprecated. Use setButtonCancel() instead.
+ *
+ * Sets the text of the Cancel button.
+ *
+ * If the default parameters are
+ * used (that is, if no parameters are given) the standard texts are set:
+ * The button shows "Cancel", everything else will not be set.
+ *
+ * @param text Button text.
+ * @param tooltip Tooltip text.
+ * @param quickhelp Quick help text.
+ */
+ void setButtonCancelText( const QString &text=QString::null,
+ const QString &tooltip=QString::null,
+ const QString &quickhelp=QString::null ) KDE_DEPRECATED;
+
+ /**
+ * Sets the text of any button.
+ *
+ * @param id The button identifier.
+ * @param text Button text.
+ */
+ void setButtonText( ButtonCode id, const QString &text );
+
+ /**
+ * Sets the tooltip text of any button.
+ *
+ * @param id The button identifier.
+ * @param text Button text.
+ */
+ void setButtonTip( ButtonCode id, const QString &text );
+
+ /**
+ * Sets the "What's this?" text of any button.
+ *
+ * @param id The button identifier.
+ * @param text Button text.
+ */
+ void setButtonWhatsThis( ButtonCode id, const QString &text );
+
+ /**
+ * Sets the KGuiItem directly for the button instead of using 3 methods to
+ * set the text, tooltip and whatsthis strings. This also allows to set an
+ * icon for the button which is otherwise not possible for the extra
+ * buttons beside Ok, Cancel and Apply.
+ *
+ * @param id The button identifier.
+ * @param item The KGuiItem for the button.
+ *
+ * @since 3.3
+ */
+ void setButtonGuiItem( ButtonCode id, const KGuiItem &item );
+
+ /**
+ * This function has only effect in TreeList mode.
+ *
+ * Defines how the tree list widget is resized when the dialog is
+ * resized horizontally. By default the tree list keeps its width
+ * when the dialog becomes wider.
+ *
+ * @param state The resize mode. If false (default) the tree list keeps
+ * its current width when the dialog becomes wider.
+ */
+ void setTreeListAutoResize( bool state );
+
+ /**
+ * This function has only effect in TreeList mode.
+ *
+ * This tells the widgets whether the icons given in the addPage,
+ * addVBoxPage, addHBoxPage, or addGridPage methods should
+ * be shown in the TreeList.
+ *
+ * Note: This method must be called before calling any of the methods
+ * which add icons to the page.
+ *
+ * @param state If true the icons are shown.
+ **/
+ void setShowIconsInTreeList(bool state);
+
+ /**
+ * This function has only effect in TreeList mode.
+ *
+ * This tells the widgets whether the root should be decorated.
+ * For details see QListView::setRootIsDecorated
+ *
+ * @param state Root will be decorated if true.
+ **/
+ void setRootIsDecorated( bool state );
+
+ /**
+ * This function has only effect in TreeList mode.
+ *
+ * This tells the TreeList to unfold the whole tree so that all entries
+ * are visible.
+ *
+ * If the list is empty when you call this method newly created entries
+ * will not automatically be opened. If the @p persist flag is set opened
+ * entries cannot be closed again, though.
+ *
+ * @param persist If true the tree always stays unfolded.
+ * @since 3.2
+ */
+ void unfoldTreeList( bool persist = false );
+
+ /**
+ * Add a widget at the bottom of the TreeList/IconList.
+ *
+ * @param widget The widget to be added. It will be reparented into the
+ * KJanusWidget, therefor it will be deleted with the
+ * KJanusWidget, too. To be on the save side just don't keep
+ * the pointer to this widget.
+ */
+ void addWidgetBelowList( QWidget * widget );
+
+ /**
+ * Add a button at the bottom of the TreeList/IconList.
+ *
+ * @param text The text on the PushButton.
+ * @param recv The object that is to receive the signal when the button
+ * is clicked.
+ * @param slot The slot to connect to the clicked signal of the button.
+ *
+ * @since 3.2
+ */
+ void addButtonBelowList( const QString & text, QObject * recv, const char * slot );
+
+ /**
+ * The same as the above function, but with a KGuiItem providing the text
+ * and icon for the button at the bottom of the TreeList/IconList.
+ *
+ * @param guiitem The text and icon on the PushButton.
+ * @param recv The object that is to receive the signal when the button
+ * is clicked.
+ * @param slot The slot to connect to the clicked signal of the button.
+ *
+ * @since 3.2
+ */
+ void addButtonBelowList( const KGuiItem & guiitem, QObject * recv, const char * slot );
+
+ /**
+ * This function has only effect in IconList mode.
+ *
+ * Defines how the icon list widget is displayed. By default it is
+ * the widgets in the dialog pages that decide the minimum height
+ * of the dialog. A vertical scrollbar can be used in the icon list
+ * area.
+ *
+ * @param state The visibility mode. If true, the minimum height is
+ * adjusted so that every icon in the list is visible at the
+ * same time. The vertical scrollbar will never be visible.
+ */
+ void setIconListAllVisible( bool state );
+
+ /**
+ * Check whether the background tile is set or not.
+ *
+ * @return @p true if there is defined a background tile.
+ */
+ static bool haveBackgroundTile();
+
+ /**
+ * Returns a pointer to the background tile if there is one.
+ *
+ * @return The tile pointer or 0 if no tile is defined.
+ *
+ **/
+ static const QPixmap *backgroundTile();
+ /**
+ * @deprecated
+ * Use backgroundTile() instead.
+ */
+ static const QPixmap *getBackgroundTile() KDE_DEPRECATED;
+
+ /**
+ * Sets the background tile.
+ *
+ * If it is Null (0), the background image is deleted.
+ *
+ * @param pix The background tile.
+ */
+ static void setBackgroundTile( const QPixmap *pix );
+
+ /**
+ * Enable hiding of the background tile (if any).
+ *
+ * @param state @p true will make the tile visible.
+ */
+ void showTile( bool state );
+
+ /**
+ * @deprecated
+ * Do not use this method. It is included for compatibility reasons.
+ *
+ * This method returns the border widths in all directions the dialog
+ * needs for itself. Respect this, or get bad looking results.
+ * The references are upper left x (@p ulx), upper left y (@p uly),
+ * lower right x (@p lrx), and lower left y (@p lly).
+ * The results are differences in pixels from the
+ * dialogs corners.
+ */
+ void getBorderWidths( int& ulx, int& uly, int& lrx, int& lry ) const KDE_DEPRECATED;
+
+ /**
+ * @deprecated
+ * Do not use this method. It is included for compatibility reasons.
+ *
+ * This method returns the contents rectangle of the work area. Place
+ * your widgets inside this rectangle, and use it to set up
+ * their geometry. Be careful: The rectangle is only valid after
+ * resizing the dialog, as it is a result of the resizing process.
+ * If you need the "overhead" the dialog needs for its elements,
+ * use getBorderWidths().
+ */
+ QRect getContentsRect() const KDE_DEPRECATED;
+
+ /**
+ * Calculate the size hint for the dialog.
+ *
+ * With this method it is easy to calculate a size hint for a
+ * dialog derived from KDialogBase if you know the width and height of
+ * the elements you add to the widget. The rectangle returned is
+ * calculated so that all elements exactly fit into it. Thus, you may
+ * set it as a minimum size for the resulting dialog.
+ *
+ * You should not need to use this method and never if you use one of
+ * the predefined shapes.
+ *
+ * @param w The width of you special widget.
+ * @param h The height of you special widget.
+ * @return The minimum width and height of the dialog using @p w and @p h
+ * as the size of the main widget.
+ */
+ QSize calculateSize( int w, int h ) const;
+
+ /**
+ * Returns the help link text.
+ *
+ * If no text has been defined,
+ * "Get help..." (internationalized) is returned.
+ *
+ * @return The help link text.
+ */
+ QString helpLinkText() const;
+
+ /**
+ * Returns the action button that corresponds to the @p id.
+ *
+ * Normally
+ * you should not use this function. @em Never delete the object returned
+ * by this function. See also enableButton(), showButton(),
+ * setButtonTip(), setButtonWhatsThis(), and setButtonText().
+ *
+ * @param id Integer identifier of the button.
+ * @return The action button or 0 if the button does not exists.
+ *
+ * FIXME KDE 4: Return the actual KPushButton instead of QPushButton (Martijn)
+ */
+ QPushButton *actionButton( ButtonCode id );
+
+ public slots:
+ /**
+ * Enable or disable (gray out) a general action button.
+ *
+ * @param id Button identifier.
+ * @param state @p true enables the button(s).
+ */
+ void enableButton( ButtonCode id, bool state );
+
+ /**
+ * Enable or disable (gray out) the OK button.
+ *
+ * @param state @p true enables the button.
+ */
+ void enableButtonOK( bool state );
+
+ /**
+ * Enable or disable (gray out) the Apply button.
+ *
+ * @param state true enables the button.
+ */
+ void enableButtonApply( bool state );
+
+ /**
+ * Enable or disable (gray out) the Cancel button.
+ *
+ * @param state true enables the button.
+ */
+ void enableButtonCancel( bool state );
+
+ /**
+ * Display or hide the help link area on the top of the dialog.
+ *
+ * @param state @p true will display the area.
+ */
+ void enableLinkedHelp( bool state );
+
+ /**
+ * Destruct the Dialog delayed.
+ *
+ * You can call this function from
+ * slots like closeClicked() and hidden().
+ * You should not use the dialog any more after
+ * calling this function.
+ * @since 3.1
+ */
+ void delayedDestruct();
+
+ /**
+ * Sets the text that is shown as the linked text.
+ *
+ * If text is empty,
+ * the text "Get help..." (internationalized) is used instead.
+ *
+ * @param text The link text.
+ */
+ void setHelpLinkText( const QString &text );
+
+ /**
+ * Sets the help path and topic.
+ *
+ * @param anchor Defined anchor in your docbook sources
+ * @param appname Defines the appname the help belongs to
+ * If empty it's the current one
+ *
+ * @note The help button works differently for the class
+ * KCMultiDialog, so it does not make sense to call this
+ * function for Dialogs of that type. See
+ * KCMultiDialog::slotHelp() for more information.
+ */
+ void setHelp( const QString &anchor,
+ const QString &appname = QString::null );
+
+ /**
+ * Connected to help link label.
+ */
+ void helpClickedSlot( const QString & );
+
+ /**
+ * Sets the status of the Details button.
+ */
+ void setDetails(bool showDetails);
+
+ /**
+ * Sets the widget that gets shown when "Details" is enabled.
+ *
+ * The dialog takes over ownership of the widget.
+ * Any previously set widget gets deleted.
+ */
+ void setDetailsWidget(QWidget *detailsWidget);
+
+ /**
+ * This method is called automatically whenever the background has
+ * changed. You do not need to use this method.
+ */
+ void updateBackground();
+
+ /**
+ * Force closing the dialog, setting its result code to the one Esc would set.
+ * You shouldn't use this, generally (let the user make his choice!)
+ * but it can be useful when you need to make a choice after a timeout
+ * has happened, or when the parent widget has to go somewhere else
+ * (e.g. html redirections).
+ * @since 3.1
+ */
+ void cancel();
+
+ signals:
+ /**
+ * The Help button was pressed. This signal is only emitted if
+ * slotHelp() is not replaced.
+ */
+ void helpClicked();
+
+ /**
+ * The Default button was pressed. This signal is only emitted if
+ * slotDefault() is not replaced.
+ */
+ void defaultClicked();
+
+
+ /**
+ * The User3 button was pressed. This signal is only emitted if
+ * slotUser3() is not replaced.
+ */
+ void user3Clicked();
+
+ /**
+ * The User2 button was pressed. This signal is only emitted if
+ * slotUser2() is not replaced.
+ */
+ void user2Clicked();
+
+ /**
+ * The User1 button was pressed. This signal is only emitted if
+ * slotUser1() is not replaced.
+ */
+ void user1Clicked();
+
+ /**
+ * The Apply button was pressed. This signal is only emitted if
+ * slotApply() is not replaced.
+ */
+ void applyClicked();
+
+ /**
+ * The Try button was pressed. This signal is only emitted if
+ * slotTry() is not replaced.
+ */
+ void tryClicked();
+
+ /**
+ * The OK button was pressed. This signal is only emitted if
+ * slotOk() is not replaced.
+ */
+ void okClicked();
+
+ /**
+ * The Yes button was pressed. This signal is only emitted if
+ * slotYes() is not replaced.
+ */
+ void yesClicked();
+
+ /**
+ * The No button was pressed. This signal is only emitted if
+ * slotNo() is not replaced.
+ */
+ void noClicked();
+
+ /**
+ * The Cancel button was pressed. This signal is only emitted if
+ * slotCancel() is not replaced.
+ */
+ void cancelClicked();
+
+ /**
+ * The Close button was pressed. This signal is only emitted if
+ * slotClose() is not replaced.
+ */
+ void closeClicked();
+
+ /**
+ * Do not use this signal. Is is kept for compatibility reasons.
+ * @deprecated Use applyClicked() instead.
+ */
+ void apply();
+
+ /**
+ * The background tile has changed.
+ */
+ void backgroundChanged();
+
+ /**
+ * The dialog is about to be hidden.
+ *
+ * A dialog is hidden after a user clicks a button that ends
+ * the dialog or when the user switches to another desktop or
+ * minimizes the dialog.
+ */
+ void hidden();
+
+ /**
+ * The dialog has finished.
+ *
+ * A dialog emits finished after a user clicks a button that ends
+ * the dialog.
+ *
+ * This signal is also emitted when you call hide()
+ *
+ * If you have stored a pointer to the
+ * dialog do @em not try to delete the pointer in the slot that is
+ * connected to this signal.
+ *
+ * You should use delayedDestruct() instead.
+ */
+ void finished();
+
+ /**
+ * The detailsWidget is about to get shown. This is your last chance
+ * to call setDetailsWidget if you haven't done so yet.
+ */
+ void aboutToShowDetails();
+
+ /**
+ * A page is about to be shown. This signal is only emitted for the TreeList
+ * and IconList faces.
+ */
+ void aboutToShowPage(QWidget *page);
+
+ protected:
+ /**
+ * Maps some keys to the actions buttons. F1 is mapped to the Help
+ * button if present and Escape to the Cancel or Close if present. The
+ * button action event is animated.
+ */
+ virtual void keyPressEvent( QKeyEvent *e );
+
+ /**
+ * Emits the #hidden signal. You can connect to that signal to
+ * detect when a dialog has been closed.
+ */
+ virtual void hideEvent( QHideEvent * );
+
+ /**
+ * Detects when a dialog is being closed from the window manager
+ * controls. If the Cancel or Close button is present then the button
+ * is activated. Otherwise standard QDialog behavior
+ * will take place.
+ */
+ virtual void closeEvent( QCloseEvent *e );
+
+ protected slots:
+ /**
+ * Activated when the Help button has been clicked. If a help
+ * text has been defined, the help system will be activated.
+ */
+ virtual void slotHelp();
+
+ /**
+ * Activated when the Default button has been clicked.
+ */
+ virtual void slotDefault();
+
+ /**
+ * Activated when the Details button has been clicked.
+ * @see detailsClicked(bool)
+ */
+ virtual void slotDetails();
+
+ /**
+ * Activated when the User3 button has been clicked.
+ */
+ virtual void slotUser3();
+
+ /**
+ * Activated when the User2 button has been clicked.
+ */
+ virtual void slotUser2();
+
+ /**
+ * Activated when the User1 button has been clicked.
+ */
+ virtual void slotUser1();
+
+ /**
+ * Activated when the Ok button has been clicked. The
+ * QDialog::accept() is activated.
+ */
+ virtual void slotOk();
+
+ /**
+ * Activated when the Apply button has been clicked.
+ */
+ virtual void slotApply();
+
+ /**
+ * Activated when the Try button has been clicked.
+ */
+ virtual void slotTry();
+
+ /**
+ * Activated when the Yes button has been clicked. The
+ * QDialog::done( Yes ) is activated.
+ */
+ virtual void slotYes();
+
+ /**
+ * Activated when the Yes button has been clicked. The
+ * QDialog::done( No ) is activated.
+ */
+ virtual void slotNo();
+
+ /**
+ * Activated when the Cancel button has been clicked. The
+ * QDialog::reject() is activated in regular mode and
+ * QDialog::done( Cancel ) when in message box mode.
+ */
+ virtual void slotCancel();
+
+ /**
+ * Activated when the Close button has been clicked. The
+ * QDialog::reject() is activated.
+ */
+ virtual void slotClose();
+
+ /**
+ * @deprecated
+ * Do not use this slot. Is is kept for compatibility reasons.
+ * Activated when the Apply button has been clicked
+ */
+ virtual void applyPressed();
+
+ /**
+ * Updates the margins and spacings.
+ */
+ void updateGeometry();
+
+ /**
+ * Deletes the dialog immediately. If you want to delete the dialog
+ * delayed use delayedDestruct() or QObject::deleteLater().
+ *
+ * Attention: Do no use connect this slot to signals from user
+ * actions!
+ */
+ void slotDelayedDestruct();
+
+ private:
+ /**
+ * Prepares the layout that manages the widgets of the dialog
+ */
+ void setupLayout();
+
+ /**
+ * Prepares a relay that is used to send signals between
+ * all KDialogBase instances of a program. Should only be used in the
+ * constructor.
+ */
+ void makeRelay();
+
+ /**
+ * Makes the button box and all the buttons in it. This method must
+ * only be ran once from the constructor.
+ *
+ * @param buttonMask Specifies what buttons will be made.
+ * @param defaultButton Specifies which button will be marked as
+ * the default. Use ButtonCode::NoDefault to indicate that no button
+ * should be marked as the default button.
+ * @param user1 User button1 item.
+ * @param user2 User button2 item.
+ * @param user2 User button3 item.
+ */
+ void makeButtonBox( int mask, ButtonCode defaultButton,
+ const KGuiItem &user1 = KGuiItem(),
+ const KGuiItem &user2 = KGuiItem(),
+ const KGuiItem &user3 = KGuiItem() );
+
+ /**
+ * Sets the action button that is marked as default and has focus.
+ *
+ * @param p The action button.
+ * @param isDefault If true, make the button default
+ * @param isFocus If true, give the button focus.
+ */
+ void setButtonFocus( QPushButton *p, bool isDefault, bool isFocus );
+
+ /**
+ * Prints an error message using qDebug if makeMainWidget ,
+ * makeVBoxMainWidget , makeHBoxMainWidget or
+ * makeGridMainWidget failed.
+ */
+ void printMakeMainWidgetError();
+
+ private slots:
+ /**
+ * Sets the action button order according to the 'style'.
+ *
+ * @param style The style index.
+ */
+ void setButtonStyle( int style );
+
+
+ private:
+ QBoxLayout *mTopLayout;
+ QWidget *mMainWidget;
+ KURLLabel *mUrlHelp;
+ KJanusWidget *mJanus;
+ KSeparator *mActionSep;
+
+ bool mIsActivated;
+
+ QString mAnchor;
+ QString mHelpApp;
+ QString mHelpLinkText;
+
+ static KDialogBaseTile *mTile;
+ bool mShowTile;
+
+ bool mMessageBoxMode;
+ int mButtonOrientation;
+ ButtonCode mEscapeButton;
+
+ protected:
+ virtual void virtual_hook( int id, void* data );
+ private:
+ class KDialogBasePrivate;
+ KDialogBasePrivate* const d;
+};
+
+#endif
diff --git a/kdeui/kdialogbase_priv.h b/kdeui/kdialogbase_priv.h
new file mode 100644
index 000000000..8bfc6596e
--- /dev/null
+++ b/kdeui/kdialogbase_priv.h
@@ -0,0 +1,71 @@
+/*
+ * This file is part of the KDE Libraries
+ * Copyright (C) 1999-2001 Mirko Boehm (mirko@kde.org) and
+ * Espen Sand (espen@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#ifndef _KDIALOG_BASE_PRIV_H_
+#define _KDIALOG_BASE_PRIV_H_
+
+#include <kpushbutton.h>
+
+/**
+ * Used internally by KDialogBase.
+ * @internal
+ */
+class KDEUI_EXPORT KDialogBaseButton : public KPushButton
+{
+ Q_OBJECT
+
+ public:
+ KDialogBaseButton( const KGuiItem &text, int key, QWidget *parent=0,
+ const char *name=0 );
+ inline int id();
+
+ private:
+ int mKey;
+};
+
+/**
+ * Used internally by KDialogBase.
+ * @internal
+ */
+class KDEUI_EXPORT KDialogBaseTile : public QObject
+{
+ Q_OBJECT
+
+ public:
+ KDialogBaseTile( QObject *parent=0, const char *name=0 );
+ ~KDialogBaseTile();
+
+ void set( const QPixmap *pix );
+ const QPixmap *get() const;
+
+ public slots:
+ void cleanup();
+
+ signals:
+ void pixmapChanged();
+
+ private:
+ QPixmap *mPixmap;
+ class KDialogBaseTilePrivate;
+ KDialogBaseTilePrivate *d;
+};
+
+#endif
diff --git a/kdeui/kdockwidget.cpp b/kdeui/kdockwidget.cpp
new file mode 100644
index 000000000..eded26c55
--- /dev/null
+++ b/kdeui/kdockwidget.cpp
@@ -0,0 +1,3331 @@
+
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Max Judin <novaprint@mtu-net.ru>
+ Copyright (C) 2002,2003 Joseph Wenninger <jowenn@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#include "kdockwidget.h"
+#include "kdockwidget_private.h"
+#include "kdockwidget_p.h"
+
+#include <qapplication.h>
+#include <qlayout.h>
+#include <qpainter.h>
+#include <qobjectlist.h>
+#include <qstrlist.h>
+#include <qcursor.h>
+#include <qwidgetlist.h>
+#include <qtabwidget.h>
+#include <qtooltip.h>
+#include <qstyle.h>
+
+#ifndef NO_KDE2
+#include <kconfig.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <ktoolbar.h>
+#include <kpopupmenu.h>
+#include <kwin.h>
+#include <kdebug.h>
+#include <kglobalsettings.h>
+
+#include "config.h"
+#ifdef Q_WS_X11
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#endif
+
+#else
+#include <qtoolbar.h>
+#include <qpopupmenu.h>
+#endif
+
+#include <stdlib.h>
+
+#undef BORDERLESS_WINDOWS
+
+#define DOCK_CONFIG_VERSION "0.0.5"
+
+static const char* const dockback_xpm[]={
+"6 6 2 1",
+"# c black",
+". c None",
+"......",
+".#....",
+"..#..#",
+"...#.#",
+"....##",
+"..####"};
+
+static const char* const todesktop_xpm[]={
+"5 5 2 1",
+"# c black",
+". c None",
+"####.",
+"##...",
+"#.#..",
+"#..#.",
+"....#"};
+
+static const char* const not_close_xpm[]={
+"5 5 2 1",
+"# c black",
+". c None",
+"#####",
+"#...#",
+"#...#",
+"#...#",
+"#####"};
+
+/**
+ * A special kind of KMainWindow that is able to have dockwidget child widgets.
+ *
+ * The main widget should be a dockwidget where other dockwidgets can be docked to
+ * the left, right, top, bottom or to the middle.
+ * Furthermore, the KDockMainWindow has got the KDocManager and some data about the dock states.
+ *
+ * @author Max Judin.
+*/
+KDockMainWindow::KDockMainWindow( QWidget* parent, const char *name, WFlags f)
+:KMainWindow( parent, name, f )
+{
+ QString new_name = QString(name) + QString("_DockManager");
+ dockManager = new KDockManager( this, new_name.latin1() );
+ mainDockWidget = 0L;
+}
+
+KDockMainWindow::~KDockMainWindow()
+{
+ delete dockManager;
+}
+
+void KDockMainWindow::setMainDockWidget( KDockWidget* mdw )
+{
+ if ( mainDockWidget == mdw ) return;
+ mainDockWidget = mdw;
+ dockManager->setMainDockWidget2(mdw);
+}
+
+void KDockMainWindow::setView( QWidget *view )
+{
+ if ( view->isA("KDockWidget") ){
+ if ( view->parent() != this ) ((KDockWidget*)view)->applyToWidget( this );
+ }
+
+#ifndef NO_KDE2
+ KMainWindow::setCentralWidget(view);
+#else
+ QMainWindow::setCentralWidget(view);
+#endif
+}
+
+KDockWidget* KDockMainWindow::createDockWidget( const QString& name, const QPixmap &pixmap, QWidget* parent, const QString& strCaption, const QString& strTabPageLabel)
+{
+ return new KDockWidget( dockManager, name.latin1(), pixmap, parent, strCaption, strTabPageLabel );
+}
+
+void KDockMainWindow::makeDockVisible( KDockWidget* dock )
+{
+ if ( dock )
+ dock->makeDockVisible();
+}
+
+void KDockMainWindow::makeDockInvisible( KDockWidget* dock )
+{
+ if ( dock )
+ dock->undock();
+}
+
+void KDockMainWindow::makeWidgetDockVisible( QWidget* widget )
+{
+ makeDockVisible( dockManager->findWidgetParentDock(widget) );
+}
+
+void KDockMainWindow::writeDockConfig(QDomElement &base)
+{
+ dockManager->writeConfig(base);
+}
+
+void KDockMainWindow::readDockConfig(QDomElement &base)
+{
+ dockManager->readConfig(base);
+}
+
+#ifndef NO_KDE2
+void KDockMainWindow::writeDockConfig( KConfig* c, QString group )
+{
+ dockManager->writeConfig( c, group );
+}
+
+void KDockMainWindow::readDockConfig( KConfig* c, QString group )
+{
+ dockManager->readConfig( c, group );
+}
+#endif
+
+void KDockMainWindow::slotDockWidgetUndocked()
+{
+ QObject* pSender = (QObject*) sender();
+ if (!pSender->inherits("KDockWidget")) return;
+ KDockWidget* pDW = (KDockWidget*) pSender;
+ emit dockWidgetHasUndocked( pDW);
+}
+
+/*************************************************************************/
+KDockWidgetAbstractHeaderDrag::KDockWidgetAbstractHeaderDrag( KDockWidgetAbstractHeader* parent, KDockWidget* dock, const char* name )
+:QFrame( parent, name )
+{
+ dw = dock;
+ installEventFilter( dock->dockManager() );
+}
+/*************************************************************************/
+KDockWidgetHeaderDrag::KDockWidgetHeaderDrag( KDockWidgetAbstractHeader* parent, KDockWidget* dock, const char* name )
+:KDockWidgetAbstractHeaderDrag( parent, dock, name )
+{
+}
+
+void KDockWidgetHeaderDrag::paintEvent( QPaintEvent* )
+{
+ QPainter paint;
+
+ paint.begin( this );
+
+ style().drawPrimitive (QStyle::PE_DockWindowHandle, &paint, QRect(0,0,width(), height()), colorGroup());
+
+ paint.end();
+}
+/*************************************************************************/
+KDockWidgetAbstractHeader::KDockWidgetAbstractHeader( KDockWidget* parent, const char* name )
+:QFrame( parent, name )
+{
+}
+/*************************************************************************/
+KDockWidgetHeader::KDockWidgetHeader( KDockWidget* parent, const char* name )
+:KDockWidgetAbstractHeader( parent, name )
+{
+#ifdef BORDERLESS_WINDOWS
+ setCursor(QCursor(ArrowCursor));
+#endif
+ d = new KDockWidgetHeaderPrivate( this );
+
+ layout = new QHBoxLayout( this );
+ layout->setResizeMode( QLayout::Minimum );
+
+ drag = new KDockWidgetHeaderDrag( this, parent );
+
+ closeButton = new KDockButton_Private( this, "DockCloseButton" );
+ QToolTip::add( closeButton, i18n("Close") );
+ closeButton->setPixmap( style().stylePixmap (QStyle::SP_TitleBarCloseButton , this));
+ closeButton->setFixedSize(closeButton->pixmap()->width(),closeButton->pixmap()->height());
+ connect( closeButton, SIGNAL(clicked()), parent, SIGNAL(headerCloseButtonClicked()));
+ connect( closeButton, SIGNAL(clicked()), parent, SLOT(undock()));
+
+ stayButton = new KDockButton_Private( this, "DockStayButton" );
+ QToolTip::add( stayButton, i18n("Freeze the window geometry", "Freeze") );
+ stayButton->setToggleButton( true );
+ stayButton->setPixmap( const_cast< const char** >(not_close_xpm) );
+ stayButton->setFixedSize(closeButton->pixmap()->width(),closeButton->pixmap()->height());
+ connect( stayButton, SIGNAL(clicked()), this, SLOT(slotStayClicked()));
+
+ dockbackButton = new KDockButton_Private( this, "DockbackButton" );
+ QToolTip::add( dockbackButton, i18n("Dock this window", "Dock") );
+ dockbackButton->setPixmap( const_cast< const char** >(dockback_xpm));
+ dockbackButton->setFixedSize(closeButton->pixmap()->width(),closeButton->pixmap()->height());
+ connect( dockbackButton, SIGNAL(clicked()), parent, SIGNAL(headerDockbackButtonClicked()));
+ connect( dockbackButton, SIGNAL(clicked()), parent, SLOT(dockBack()));
+
+ d->toDesktopButton = new KDockButton_Private( this, "ToDesktopButton" );
+ QToolTip::add( d->toDesktopButton, i18n("Detach") );
+ d->toDesktopButton->setPixmap( const_cast< const char** >(todesktop_xpm));
+ d->toDesktopButton->setFixedSize(closeButton->pixmap()->width(),closeButton->pixmap()->height());
+ connect( d->toDesktopButton, SIGNAL(clicked()), parent, SLOT(toDesktop()));
+ stayButton->hide();
+
+ d->dummy = new QWidget( this );
+ d->dummy->setFixedSize( 1,closeButton->pixmap()->height() );
+
+
+ layout->addWidget( drag );
+ layout->addWidget( dockbackButton );
+ layout->addWidget( d->toDesktopButton );
+ layout->addWidget( d->dummy);
+ layout->addWidget( stayButton );
+ layout->addWidget( closeButton );
+ layout->activate();
+ d->dummy->hide();
+ drag->setFixedHeight( layout->minimumSize().height() );
+}
+
+void KDockWidgetHeader::setTopLevel( bool isTopLevel )
+{
+ d->topLevel = isTopLevel;
+ if ( isTopLevel ){
+ KDockWidget* par = (KDockWidget*)parent();
+ if( par && par->isDockBackPossible() )
+ dockbackButton->show();
+ else
+ dockbackButton->hide();
+
+ stayButton->hide();
+ closeButton->hide();
+ d->toDesktopButton->hide();
+ drag->setEnabled( true );
+ } else {
+ dockbackButton->hide();
+ stayButton->hide();
+ if (!d->forceCloseButtonHidden) closeButton->show();
+ if( d->showToDesktopButton )
+ d->toDesktopButton->show();
+ }
+ layout->activate();
+
+ bool dontShowDummy=drag->isVisibleTo(this) || dockbackButton->isVisibleTo(this) ||
+ d->toDesktopButton->isVisibleTo(this) || stayButton->isVisibleTo(this) ||
+ closeButton->isVisibleTo(this);
+ for (QPtrListIterator<KDockButton_Private> it( d->btns );it.current();++it) {
+ dontShowDummy=dontShowDummy || (it.current()->isVisibleTo(this));
+ }
+ if (dontShowDummy) d->dummy->hide(); else d->dummy->show();
+
+ updateGeometry();
+}
+
+void KDockWidgetHeader::forceCloseButtonHidden(bool hidden) {
+ d->forceCloseButtonHidden=hidden;
+ if (hidden) closeButton->hide();
+ else closeButton->show();
+}
+
+KDockWidgetHeaderDrag *KDockWidgetHeader::dragPanel() {
+ return drag;
+}
+
+void KDockWidgetHeader::setDragPanel( KDockWidgetHeaderDrag* nd )
+{
+ if ( !nd ) return;
+
+ delete layout;
+ layout = new QHBoxLayout( this );
+ layout->setResizeMode( QLayout::Minimum );
+
+ delete drag;
+ drag = nd;
+ if (drag->parentWidget()!=this) {
+ drag->reparent(this,QPoint(0,0));
+ }
+
+
+ layout->addWidget( drag );
+ layout->addWidget( dockbackButton );
+ layout->addWidget( d->dummy );
+ layout->addWidget( d->toDesktopButton );
+ layout->addWidget( stayButton );
+ bool dontShowDummy=drag->isVisibleTo(this) || dockbackButton->isVisibleTo(this) ||
+ d->toDesktopButton->isVisibleTo(this) || stayButton->isVisibleTo(this) ||
+ closeButton->isVisibleTo(this);
+ for (QPtrListIterator<KDockButton_Private> it( d->btns );it.current();++it) {
+ layout->addWidget(it.current());
+ dontShowDummy=dontShowDummy || (it.current()->isVisibleTo(this));
+ }
+ if (dontShowDummy) d->dummy->hide(); else d->dummy->show();
+ layout->addWidget( closeButton );
+ layout->activate();
+ kdDebug(282)<<"KdockWidgetHeader::setDragPanel:minimum height="<<layout->minimumSize().height()<<endl;
+ //FIXME somebody left this here, but we don't know what the hell it's for.
+ drag->setFixedHeight( closeButton->height()); // /*layout->minimumS*/sizeHint().height() );
+}
+
+void KDockWidgetHeader::addButton(KDockButton_Private* btn) {
+ if (!btn) return;
+
+ if (btn->parentWidget()!=this) {
+ btn->reparent(this,QPoint(0,0));
+ }
+ btn->setFixedSize(closeButton->pixmap()->width(),closeButton->pixmap()->height());
+ if (!d->btns.containsRef(btn)) d->btns.append(btn);
+
+ btn->show();
+
+ delete layout;
+ layout = new QHBoxLayout( this );
+ layout->setResizeMode( QLayout::Minimum );
+
+ layout->addWidget( drag );
+ layout->addWidget( dockbackButton );
+ layout->addWidget( d->toDesktopButton );
+ layout->addWidget( d->dummy);
+ layout->addWidget( stayButton );
+ bool dontShowDummy=drag->isVisibleTo(this) || dockbackButton->isVisibleTo(this) ||
+ d->toDesktopButton->isVisibleTo(this) || stayButton->isVisibleTo(this) ||
+ closeButton->isVisibleTo(this);
+ for (QPtrListIterator<KDockButton_Private> it( d->btns );it.current();++it) {
+ layout->addWidget(it.current());
+ dontShowDummy=dontShowDummy || (it.current()->isVisibleTo(this));
+ }
+ if (dontShowDummy) d->dummy->hide(); else d->dummy->show();
+ layout->addWidget( closeButton );
+ layout->activate();
+ drag->setFixedHeight( layout->minimumSize().height() );
+}
+
+void KDockWidgetHeader::removeButton(KDockButton_Private* btn) {
+ if (btn->parentWidget()==this) {
+ if (d->btns.containsRef(btn)) d->btns.removeRef(btn);
+ delete btn;
+ }
+}
+
+
+void KDockWidgetHeader::slotStayClicked()
+{
+ setDragEnabled(!stayButton->isOn());
+}
+
+bool KDockWidgetHeader::dragEnabled() const
+{
+ return drag->isEnabled();
+}
+
+void KDockWidgetHeader::showUndockButton(bool show)
+{
+ kdDebug(282)<<"KDockWidgetHeader::showUndockButton("<<show<<")"<<endl;
+ if( d->showToDesktopButton == show )
+ return;
+
+ d->showToDesktopButton = show;
+ if( !show || d->topLevel )
+ d->toDesktopButton->hide( );
+ else
+ d->toDesktopButton->show( );
+}
+
+void KDockWidgetHeader::setDragEnabled(bool b)
+{
+ stayButton->setOn(!b);
+ closeButton->setEnabled(b);
+ drag->setEnabled(b);
+}
+
+#ifndef NO_KDE2
+void KDockWidgetHeader::saveConfig( KConfig* c )
+{
+ c->writeEntry( QString("%1%2").arg(parent()->name()).arg(":stayButton"), stayButton->isOn() );
+}
+
+void KDockWidgetHeader::loadConfig( KConfig* c )
+{
+ setDragEnabled( !c->readBoolEntry( QString("%1%2").arg(parent()->name()).arg(":stayButton"), false ) );
+}
+#endif
+
+/*************************************************************************/
+
+class KDockManager::KDockManagerPrivate
+{
+public:
+ /**
+ * This rectangle is used to highlight the current dockposition. It stores global screen coordinates.
+ */
+ QRect dragRect;
+
+ /**
+ * This rectangle is used to erase the previously highlighted dockposition. It stores global screen coordinates.
+ */
+ QRect oldDragRect;
+
+ /**
+ * This flag stores the information if dragging is ready to start. Used between mousePress and mouseMove event.
+ */
+ bool readyToDrag;
+
+ /**
+ * This variable stores the offset of the mouse cursor to the upper left edge of the current drag widget.
+ */
+ QPoint dragOffset;
+
+ /**
+ * These flags store information about the splitter behavior
+ */
+ bool splitterOpaqueResize;
+ bool splitterKeepSize;
+ bool splitterHighResolution;
+
+ QGuardedPtr<KDockWidget> mainDockWidget;
+
+ QObjectList containerDocks;
+
+ QGuardedPtr<KDockWidget> leftContainer;
+ QGuardedPtr<KDockWidget> topContainer;
+ QGuardedPtr<KDockWidget> rightContainer;
+ QGuardedPtr<KDockWidget> bottomContainer;
+ int m_readDockConfigMode;
+};
+
+
+/*************************************************************************/
+KDockWidget::KDockWidget( KDockManager* dockManager, const char* name, const QPixmap &pixmap, QWidget* parent, const QString& strCaption, const QString& strTabPageLabel, WFlags f)
+#ifdef BORDERLESS_WINDOWS
+: QWidget( parent, name, f )//| WType_Dialog | WStyle_Customize | WStyle_NoBorder )
+#else
+: QWidget( parent, name, f )
+#endif
+ ,formerBrotherDockWidget(0L)
+ ,currentDockPos(DockNone)
+ ,formerDockPos(DockNone)
+ ,widget(0L)
+ ,pix(new QPixmap(pixmap))
+ ,prevSideDockPosBeforeDrag(DockNone)
+ ,isGroup(false)
+{
+ d = new KDockWidgetPrivate(); // create private data
+
+ d->_parent = parent;
+
+ layout = new QVBoxLayout( this );
+ layout->setResizeMode( QLayout::Minimum );
+
+ manager = dockManager;
+ manager->childDock->append( this );
+ installEventFilter( manager );
+
+ eDocking = DockFullDocking;
+ sDocking = DockFullSite;
+
+ header = 0L;
+ setHeader( new KDockWidgetHeader( this, "AutoCreatedDockHeader" ) );
+
+ if( strCaption.isNull() )
+ setCaption( name );
+ else
+ setCaption( strCaption);
+
+ if( strTabPageLabel == " ")
+ setTabPageLabel( caption());
+ else
+ setTabPageLabel( strTabPageLabel);
+
+ isTabGroup = false;
+ d->isContainer =false;
+ setIcon( pixmap);
+ widget = 0L;
+
+ QObject::connect(this, SIGNAL(hasUndocked()), manager->main, SLOT(slotDockWidgetUndocked()) );
+ applyToWidget( parent, QPoint(0,0) );
+}
+
+void KDockWidget::setPixmap(const QPixmap& pixmap) {
+ delete pix;
+ pix=new QPixmap(pixmap);
+ setIcon(*pix);
+ KDockTabGroup *dtg=parentDockTabGroup();
+ if (dtg)
+ dtg->changeTab(this,pixmap,dtg->tabLabel(this));
+ QWidget *contWid=parentDockContainer();
+ if (contWid) {
+ KDockContainer *x = dynamic_cast<KDockContainer*>(contWid);
+ if (x) {
+ x->setPixmap(this,pixmap);
+ }
+ }
+}
+
+const QPixmap& KDockWidget::pixmap() const {
+ return *pix;
+}
+
+KDockWidget::~KDockWidget()
+{
+ d->pendingDtor = true;
+ if ( !manager->undockProcess ){
+ d->blockHasUndockedSignal = true;
+ undock();
+ d->blockHasUndockedSignal = false;
+ }
+
+ if (latestKDockContainer()) {
+ KDockContainer *x = dynamic_cast<KDockContainer*>(latestKDockContainer());
+ if (x) {
+ x->removeWidget(this);
+ }
+ }
+ emit iMBeingClosed();
+ if (manager->d) manager->d->containerDocks.remove(this);
+ manager->childDock->remove( this );
+ delete pix;
+ delete d; // destroy private data
+ d=0;
+}
+
+void KDockWidget::paintEvent(QPaintEvent* pe)
+{
+ QWidget::paintEvent(pe);
+ QPainter paint;
+ paint.begin( this );
+ style().drawPrimitive (QStyle::PE_Panel, &paint, QRect(0,0,width(), height()), colorGroup());
+ paint.end();
+}
+
+void KDockWidget::leaveEvent(QEvent *e)
+{
+ QWidget::leaveEvent(e);
+#ifdef BORDERLESS_WINDOWS
+ if (parent()) return;
+// setCursor(QCursor(ArrowCursor));
+#endif
+}
+
+void KDockWidget::mousePressEvent(QMouseEvent* mme)
+{
+#ifdef BORDERLESS_WINDOWS
+ if (!parent())
+ {
+ kdDebug(282)<<"KDockWidget::mousePressEvent"<<endl;
+
+ bool bbottom;
+ bool bleft;
+ bool bright;
+ bool btop;
+ int styleheight;
+ QPoint mp;
+ mp=mme->pos();
+ styleheight=2*style().pixelMetric(QStyle::PM_DefaultFrameWidth,this);
+ bbottom=mp.y()>=height()-styleheight;
+ btop=mp.y()<=styleheight;
+ bleft=mp.x()<=styleheight;
+ bright=mp.x()>=width()-styleheight;
+ kdDebug(282)<<"mousemovevent"<<endl;
+ d->resizing=true;
+ if (bright)
+ {
+ if (btop)
+ {
+ d->resizeMode=KDockWidgetPrivate::ResizeTopRight;
+ d->resizePos=QPoint(width(),0)-mme->pos();
+
+ }
+ else
+ {
+ d->resizePos=QPoint(width(),height())-mme->pos();
+ if (bbottom) d->resizeMode=KDockWidgetPrivate::ResizeBottomRight;
+ else d->resizeMode=KDockWidgetPrivate::ResizeRight;
+ }
+ }
+ else if (bleft)
+ {
+ if (btop) setCursor(QCursor(SizeFDiagCursor));
+ else
+ if (bbottom) setCursor(QCursor(SizeBDiagCursor));
+ else setCursor(QCursor(SizeHorCursor));
+ }
+ else
+ if (bbottom)
+ {
+ d->resizeMode=KDockWidgetPrivate::ResizeBottom;
+ d->resizePos=QPoint(0,height())-mme->pos();
+ }
+ else
+ if (btop) setCursor(QCursor(SizeVerCursor));
+ else d->resizing=false;
+
+ if (d->resizing) grabMouse(cursor());
+
+ }
+#endif
+ QWidget::mousePressEvent(mme);
+}
+
+void KDockWidget::mouseReleaseEvent(QMouseEvent* ev)
+{
+#ifdef BORDERLESS_WINDOWS
+ d->resizing=false;
+ releaseMouse();
+#endif
+ QWidget::mouseReleaseEvent(ev);
+}
+
+void KDockWidget::mouseMoveEvent(QMouseEvent* mme)
+{
+ QWidget::mouseMoveEvent(mme);
+#ifdef BORDERLESS_WINDOWS
+ if (parent()) return;
+
+ if (d->resizing)
+ {
+ switch (d->resizeMode)
+ {
+ case KDockWidgetPrivate::ResizeRight:
+ resize(mme->pos().x()+d->resizePos.x(),height());
+ break;
+ case KDockWidgetPrivate::ResizeBottomRight:
+ resize(mme->pos().x()+d->resizePos.x(),mme->pos().y()+d->resizePos.y());
+ break;
+ case KDockWidgetPrivate::ResizeBottom:
+ resize(width(),mme->pos().y()+d->resizePos.y());
+ break;
+ default:
+ break;
+ }
+ return;
+ }
+
+
+ bool bbottom;
+ bool bleft;
+ bool bright;
+ bool btop;
+ int styleheight;
+ QPoint mp;
+ mp=mme->pos();
+ styleheight=2*style().pixelMetric(QStyle::PM_DefaultFrameWidth,this);
+ bbottom=mp.y()>=height()-styleheight;
+ btop=mp.y()<=styleheight;
+ bleft=mp.x()<=styleheight;
+ bright=mp.x()>=width()-styleheight;
+ kdDebug(282)<<"mousemovevent"<<endl;
+ if (bright)
+ {
+ if (btop) setCursor(QCursor(SizeBDiagCursor));
+ else
+ if (bbottom) setCursor(QCursor(SizeFDiagCursor));
+ else setCursor(QCursor(SizeHorCursor));
+ }
+ else if (bleft)
+ {
+ if (btop) setCursor(QCursor(SizeFDiagCursor));
+ else
+ if (bbottom) setCursor(QCursor(SizeBDiagCursor));
+ else setCursor(QCursor(SizeHorCursor));
+ }
+ else
+ if (bbottom || btop) setCursor(QCursor(SizeVerCursor));
+ else setCursor(QCursor(ArrowCursor));
+#endif
+}
+
+void KDockWidget::setLatestKDockContainer(QWidget* container)
+{
+ if (container)
+ {
+ if (dynamic_cast<KDockContainer*>(container))
+ d->container=container;
+ else
+ d->container=0;
+ }
+}
+
+QWidget* KDockWidget::latestKDockContainer()
+{
+ if (!(d->container)) return 0;
+ if (dynamic_cast<KDockContainer*>(d->container.operator->())) return d->container;
+ return 0;
+}
+
+
+
+KDockWidgetAbstractHeader *KDockWidget::getHeader() {
+ return header;
+}
+
+void KDockWidget::setHeader( KDockWidgetAbstractHeader* h )
+{
+ if ( !h ) return;
+
+ if ( header ){
+ delete header;
+ delete layout;
+ header = h;
+ layout = new QVBoxLayout( this );
+ layout->setResizeMode( QLayout::Minimum );
+ layout->addWidget( header );
+ setWidget( widget );
+ } else {
+ header = h;
+ layout->addWidget( header );
+ }
+ kdDebug(282)<<caption()<<": KDockWidget::setHeader"<<endl;
+ setEnableDocking(eDocking);
+}
+
+void KDockWidget::setEnableDocking( int pos )
+{
+ eDocking = pos;
+ if( header ) {
+ if (header->inherits( "KDockWidgetHeader" ) )
+ ( ( KDockWidgetHeader* ) header )->showUndockButton( pos & DockDesktop );
+ updateHeader();
+ }
+}
+
+void KDockWidget::updateHeader()
+{
+ if ( parent() ){
+#ifdef BORDERLESS_WINDOWS
+ layout->setMargin(0);
+ setMouseTracking(false);
+ setCursor(QCursor(ArrowCursor));
+#endif
+
+ if ( (parent() == manager->main) || isGroup || (eDocking == KDockWidget::DockNone) ){
+ header->hide();
+ } else {
+ header->setTopLevel( false );
+ if (widget && dynamic_cast<KDockContainer*>(widget))
+ header->hide();
+ else
+ header->show();
+ }
+ } else {
+ header->setTopLevel( true );
+ header->show();
+#ifdef BORDERLESS_WINDOWS
+ layout->setMargin(2*style().pixelMetric(QStyle::PM_DefaultFrameWidth,this));
+ setMouseTracking(true);
+#endif
+ }
+}
+
+void KDockWidget::applyToWidget( QWidget* s, const QPoint& p )
+{
+ if ( parent() != s )
+ {
+ hide();
+ reparent(s, 0, QPoint(0,0), false);
+ }
+
+ if ( s && s->inherits("KDockMainWindow") ){
+ ((KDockMainWindow*)s)->setView( this );
+ }
+
+ if ( manager && s == manager->main ){
+ setGeometry( QRect(QPoint(0,0), manager->main->geometry().size()) );
+ }
+
+ if ( !s )
+ {
+ move(p);
+
+#ifndef NO_KDE2
+#ifdef Q_WS_X11
+ if (d->transient && d->_parent)
+ XSetTransientForHint( qt_xdisplay(), winId(), d->_parent->winId() );
+
+#ifdef BORDERLESS_WINDOWS
+ KWin::setType( winId(), NET::Override); //d->windowType );
+// setWFlags(WStyle_Customize | WStyle_NoBorder | WStyle_Tool);
+#else
+ KWin::setType( winId(), d->windowType );
+#endif // BORDERLESS_WINDOW
+#endif // Q_WS_X11
+#endif
+
+ }
+ updateHeader();
+
+ setIcon(*pix);
+}
+
+void KDockWidget::show()
+{
+ if ( parent() || manager->main->isVisible() )
+ if ( !parent() ){
+ emit manager->setDockDefaultPos( this );
+ emit setDockDefaultPos();
+ if ( parent() ){
+ makeDockVisible();
+ } else {
+ QWidget::show();
+ }
+ } else {
+ QWidget::show();
+ }
+}
+
+#ifndef NO_KDE2
+
+void KDockWidget::setDockWindowType (NET::WindowType windowType)
+{
+ d->windowType = windowType;
+ applyToWidget( parentWidget(), QPoint(0,0) );
+}
+
+#endif
+
+void KDockWidget::setDockWindowTransient (QWidget *parent, bool transientEnabled)
+{
+ d->_parent = parent;
+ d->transient = transientEnabled;
+ applyToWidget( parentWidget(), QPoint(0,0) );
+}
+
+QWidget *KDockWidget::transientTo() {
+ if (d->transient && d->_parent) return d->_parent; else return 0;
+}
+
+bool KDockWidget::event( QEvent *event )
+{
+ switch ( event->type() )
+ {
+ #undef FocusIn
+ case QEvent::FocusIn:
+ if (widget && !d->pendingFocusInEvent) {
+ d->pendingFocusInEvent = true;
+ widget->setFocus();
+ }
+ d->pendingFocusInEvent = false;
+ break;
+ case QEvent::ChildRemoved:
+ if ( widget == ((QChildEvent*)event)->child() ) widget = 0L;
+ break;
+ case QEvent::Show:
+ if ( widget ) widget->show();
+ emit manager->change();
+ break;
+ case QEvent::Hide:
+ if ( widget ) widget->hide();
+ emit manager->change();
+ break;
+ case QEvent::CaptionChange:
+ if ( parentWidget() ){
+ if ( parent()->inherits("KDockSplitter") ){
+ ((KDockSplitter*)(parent()))->updateName();
+ }
+ if ( parentDockTabGroup() ){
+ setDockTabName( parentDockTabGroup() );
+ parentDockTabGroup()->setTabLabel( this, tabPageLabel() );
+ }
+ }
+ break;
+ case QEvent::Close:
+ emit iMBeingClosed();
+ break;
+ default:
+ break;
+ }
+ return QWidget::event( event );
+}
+
+KDockWidget *KDockWidget::findNearestDockWidget(DockPosition pos)
+{
+ if (!parent()) return 0;
+ if (!parent()->inherits("KDockSplitter")) return 0;
+ Orientation orientation=((pos==DockLeft) || (pos==DockRight)) ? Vertical:Horizontal;
+ if (((KDockSplitter*)(parent()))->orientation()==orientation)
+ {
+ KDockWidget *neighbor=
+ ((pos==DockLeft)||(pos==DockTop))?
+ static_cast<KDockWidget*>(((KDockSplitter*)(parent()))->getFirst()):
+ static_cast<KDockWidget*>(((KDockSplitter*)(parent()))->getLast());
+
+ if (neighbor==this)
+ return (static_cast<KDockWidget*>(parent()->parent())->findNearestDockWidget(pos));
+ else
+ if (neighbor->getWidget() && (neighbor->getWidget()->qt_cast("KDockTabGroup")))
+ return (KDockWidget*)(((KDockTabGroup*)neighbor->getWidget())->page(0));
+ else
+ return neighbor;
+ }
+ else
+ return (static_cast<KDockWidget*>(parent()->parent())->findNearestDockWidget(pos));
+
+ return 0;
+}
+
+
+KDockWidget* KDockWidget::manualDock( KDockWidget* target, DockPosition dockPos, int spliPos, QPoint pos, bool check, int tabIndex )
+{
+ if (this == target)
+ return 0L; // docking to itself not possible
+
+// kdDebug(282)<<"manualDock called "<<endl;
+ bool success = true; // tested flag
+
+ // Check to make sure that we can dock in to the position wee
+ // were told to dock in to
+ if ( !(eDocking & (int)dockPos) ){
+ success = false;
+// kdDebug(282)<<"KDockWidget::manualDock(): success = false (1)"<<endl;
+ }
+
+ // fix for apps which use a value > 100%. The splitter position must be between 0..100
+ // The old behavior on high resolution was 0..10000. So likely the value is >100.
+ if (spliPos > 100) {
+ spliPos = spliPos / 100;
+ kdDebug(282) << "KDockWidget::manualDock(): fix splitter position: " << spliPos << endl;
+ }
+
+ KDockWidget *tmpTarget = 0;
+ switch (dockPos) {
+ case DockLeft:
+ tmpTarget=dockManager()->d->leftContainer;
+ break;
+ case DockRight:
+ tmpTarget=dockManager()->d->rightContainer;
+ break;
+ case DockBottom:
+ tmpTarget=dockManager()->d->bottomContainer;
+ break;
+ case DockTop:
+ tmpTarget=dockManager()->d->topContainer;
+ break;
+ default:
+ tmpTarget = 0;
+ }
+
+ //If we're not the target, and the target is our dock manager's main window
+ //dock into the temp target as chosen above
+ if ( tmpTarget && target && this != tmpTarget && target == dockManager()->d->mainDockWidget )
+ return manualDock(tmpTarget,DockCenter,spliPos,pos,check,tabIndex);
+
+ // check if the target allows us to oock into the requested position
+ if ( target && !(target->sDocking & (int)dockPos) ){
+ success = false;
+// kdDebug(282)<<"KDockWidget::manualDock(): success = false (2)"<<endl;
+ }
+
+ /* if we have a parent, and it's not a KDockSplitter, and we don't have a parent
+ * dock tab group, and our parent isn't a KDockContainer, and we have no explicit
+ * parent dock container...we can't do much yet */
+ if ( parent() && !parent()->inherits("KDockSplitter") && !parentDockTabGroup() &&
+ !(dynamic_cast<KDockContainer*>(parent())) && !parentDockContainer()){
+// kdDebug(282)<<"KDockWidget::manualDock(): success = false (3)"<<endl;
+// kdDebug(282)<<parent()->name()<<endl;
+ success = false;
+ }
+
+ /* If all of our attempts to dock back so far have failed and we have a target
+ * and we're not being called recursively (i guess that's what check is for)
+ * then attempt to dock back to ourselves. */
+ if ( !success ){
+ // try to make another manualDock
+ KDockWidget* dock_result = 0L;
+ if ( target && !check ){
+ KDockWidget::DockPosition another__dockPos = KDockWidget::DockNone;
+ switch ( dockPos ){
+ case KDockWidget::DockLeft : another__dockPos = KDockWidget::DockRight ; break;
+ case KDockWidget::DockRight : another__dockPos = KDockWidget::DockLeft ; break;
+ case KDockWidget::DockTop : another__dockPos = KDockWidget::DockBottom; break;
+ case KDockWidget::DockBottom: another__dockPos = KDockWidget::DockTop ; break;
+ default: break;
+ }
+ dock_result = target->manualDock( this, another__dockPos, spliPos, pos, true, tabIndex );
+ }
+ return dock_result;
+ }
+ // end check block
+
+ d->blockHasUndockedSignal = true;
+ undock();
+ d->blockHasUndockedSignal = false;
+
+ //we have no docking target, so we're undocking
+ if ( !target ){
+ move( pos );
+ show();
+ emit manager->change();
+ return this;
+ }
+
+// kdDebug(282)<<"Looking for KDockTabGroup"<<endl;
+ KDockTabGroup* parentTab = target->parentDockTabGroup();
+ if ( parentTab ){
+ // add to existing TabGroup
+ applyToWidget( parentTab );
+ parentTab->insertTab( this, icon() ? *icon() : QPixmap(),
+ tabPageLabel(), tabIndex );
+
+ QWidget *wantTransient=parentTab->transientTo();
+ target->setDockWindowTransient(wantTransient,wantTransient);
+
+ setDockTabName( parentTab );
+ if( !toolTipStr.isEmpty())
+ parentTab->setTabToolTip( this, toolTipStr);
+
+ currentDockPos = KDockWidget::DockCenter;
+ emit manager->change();
+ return (KDockWidget*)parentTab->parent();
+ }
+ else
+ {
+// kdDebug(282)<<"Looking for KDockContainer"<<endl;
+ QWidget *contWid=target->parentDockContainer();
+ if (!contWid) contWid=target->widget;
+ if (contWid)
+ {
+ KDockContainer *cont=dynamic_cast<KDockContainer*>(contWid);
+ if (cont)
+ {
+ if (latestKDockContainer() && (latestKDockContainer()!=contWid)) {
+ KDockContainer* dc = dynamic_cast<KDockContainer*>(latestKDockContainer());
+ if (dc) {
+ dc->removeWidget(this);
+ }
+ }
+// kdDebug(282)<<"KDockContainerFound"<<endl;
+ applyToWidget( contWid );
+ cont->insertWidget( this, icon() ? *icon() : QPixmap(),
+ tabPageLabel(), tabIndex );
+ setLatestKDockContainer(contWid);
+// setDockTabName( parentTab );
+ if( !toolTipStr.isEmpty())
+ cont->setToolTip( this, toolTipStr);
+
+ currentDockPos = KDockWidget::DockCenter;
+ emit manager->change();
+ return (KDockWidget*)(cont->parentDockWidget());
+
+ }
+ }
+ }
+
+ // create a new dockwidget that will contain the target and this
+ QWidget* parentDock = target->parentWidget();
+ KDockWidget* newDock = new KDockWidget( manager, "tempName", QPixmap(""), parentDock );
+ newDock->currentDockPos = target->currentDockPos;
+
+ if ( dockPos == KDockWidget::DockCenter ){
+ newDock->isTabGroup = true;
+ } else {
+ newDock->isGroup = true;
+ }
+ newDock->eDocking = (target->eDocking & eDocking) & (~(int)KDockWidget::DockCenter);
+
+ newDock->applyToWidget( parentDock );
+
+ if ( !parentDock ){
+ // dock to a toplevel dockwidget means newDock is toplevel now
+ newDock->move( target->frameGeometry().topLeft() );
+ newDock->resize( target->geometry().size() );
+ if ( target->isVisibleToTLW() ) newDock->show();
+ }
+
+ // redirect the dockback button to the new dockwidget
+ if( target->formerBrotherDockWidget ) {
+ newDock->setFormerBrotherDockWidget(target->formerBrotherDockWidget);
+ if( formerBrotherDockWidget )
+ target->loseFormerBrotherDockWidget();
+ }
+ newDock->formerDockPos = target->formerDockPos;
+
+
+ // HERE SOMETING CREATING CONTAINERS SHOULD BE ADDED !!!!!
+ if ( dockPos == KDockWidget::DockCenter )
+ {
+ KDockTabGroup* tab = new KDockTabGroup( newDock, "_dock_tab");
+ QObject::connect(tab, SIGNAL(currentChanged(QWidget*)), d, SLOT(slotFocusEmbeddedWidget(QWidget*)));
+ newDock->setWidget( tab );
+
+ target->applyToWidget( tab );
+ applyToWidget( tab );
+
+
+ tab->insertTab( target, target->icon() ? *(target->icon()) : QPixmap(),
+ target->tabPageLabel() );
+
+
+
+ if( !target->toolTipString().isEmpty())
+ tab->setTabToolTip( target, target->toolTipString());
+
+ tab->insertTab( this, icon() ? *icon() : QPixmap(),
+ tabPageLabel(), tabIndex );
+
+ QRect geom=newDock->geometry();
+ QWidget *wantTransient=tab->transientTo();
+ newDock->setDockWindowTransient(wantTransient,wantTransient);
+ newDock->setGeometry(geom);
+
+ if( !toolTipString().isEmpty())
+ tab->setTabToolTip( this, toolTipString());
+
+ setDockTabName( tab );
+ tab->show();
+
+ currentDockPos = DockCenter;
+ target->formerDockPos = target->currentDockPos;
+ target->currentDockPos = DockCenter;
+ }
+ else {
+ // if to dock not to the center of the target dockwidget,
+ // dock to newDock
+ KDockSplitter* panner = 0L;
+ if ( dockPos == KDockWidget::DockTop || dockPos == KDockWidget::DockBottom ) panner = new KDockSplitter( newDock, "_dock_split_", Horizontal, spliPos );
+ if ( dockPos == KDockWidget::DockLeft || dockPos == KDockWidget::DockRight ) panner = new KDockSplitter( newDock, "_dock_split_", Vertical , spliPos );
+ newDock->setWidget( panner );
+
+ panner->setOpaqueResize(manager->splitterOpaqueResize());
+ panner->setKeepSize(manager->splitterKeepSize());
+ panner->setFocusPolicy( NoFocus );
+ target->applyToWidget( panner );
+ applyToWidget( panner );
+ target->formerDockPos = target->currentDockPos;
+ if ( dockPos == KDockWidget::DockRight) {
+ panner->activate( target, this );
+ currentDockPos = KDockWidget::DockRight;
+ target->currentDockPos = KDockWidget::DockLeft;
+ }
+ else if( dockPos == KDockWidget::DockBottom) {
+ panner->activate( target, this );
+ currentDockPos = KDockWidget::DockBottom;
+ target->currentDockPos = KDockWidget::DockTop;
+ }
+ else if( dockPos == KDockWidget::DockTop) {
+ panner->activate( this, target );
+ currentDockPos = KDockWidget::DockTop;
+ target->currentDockPos = KDockWidget::DockBottom;
+ }
+ else if( dockPos == KDockWidget::DockLeft) {
+ panner->activate( this, target );
+ currentDockPos = KDockWidget::DockLeft;
+ target->currentDockPos = KDockWidget::DockRight;
+ }
+ target->show();
+ show();
+ panner->show();
+ }
+
+ if ( parentDock ){
+ if ( parentDock->inherits("KDockSplitter") ){
+ KDockSplitter* sp = (KDockSplitter*)parentDock;
+ sp->deactivate();
+ if ( sp->getFirst() == target )
+ sp->activate( newDock, 0L );
+ else
+ sp->activate( 0L, newDock );
+ }
+ }
+
+ newDock->show();
+ emit target->docking( this, dockPos );
+ emit manager->replaceDock( target, newDock );
+ emit manager->change();
+
+ return newDock;
+}
+
+KDockTabGroup* KDockWidget::parentDockTabGroup() const
+{
+ if ( !parent() ) return 0L;
+ QWidget* candidate = parentWidget()->parentWidget();
+ if ( candidate && candidate->inherits("KDockTabGroup") ) return (KDockTabGroup*)candidate;
+ return 0L;
+}
+
+QWidget *KDockWidget::parentDockContainer() const
+{
+ if (!parent()) return 0L;
+ QWidget* candidate = parentWidget()->parentWidget();
+ if (candidate && dynamic_cast<KDockContainer*>(candidate)) return candidate;
+ return 0L;
+}
+
+
+void KDockWidget::setForcedFixedWidth(int w)
+{
+ d->forcedWidth=w;
+ setFixedWidth(w);
+ if (!parent()) return;
+ if (parent()->inherits("KDockSplitter"))
+ static_cast<KDockSplitter*>(parent()->qt_cast("KDockSplitter"))->setForcedFixedWidth(this,w);
+}
+
+void KDockWidget::setForcedFixedHeight(int h)
+{
+ d->forcedHeight=h;
+ setFixedHeight(h);
+ if (!parent()) return;
+ if (parent()->inherits("KDockSplitter"))
+ static_cast<KDockSplitter*>(parent()->qt_cast("KDockSplitter"))->setForcedFixedHeight(this,h);
+}
+
+int KDockWidget::forcedFixedWidth()
+{
+ return d->forcedWidth;
+}
+
+int KDockWidget::forcedFixedHeight()
+{
+ return d->forcedHeight;
+}
+
+void KDockWidget::restoreFromForcedFixedSize()
+{
+ d->forcedWidth=-1;
+ d->forcedHeight=-1;
+ setMinimumWidth(0);
+ setMaximumWidth(32000);
+ setMinimumHeight(0);
+ setMaximumHeight(32000);
+ if (!parent()) return;
+ if (parent()->inherits("KDockSplitter"))
+ static_cast<KDockSplitter*>(parent()->qt_cast("KDockSplitter"))->restoreFromForcedFixedSize(this);
+}
+
+void KDockWidget::toDesktop()
+{
+ QPoint p = mapToGlobal( QPoint( -30, -30 ) );
+ if( p.x( ) < 0 )
+ p.setX( 0 );
+ if( p.y( ) < 0 )
+ p.setY( 0 );
+ manualDock( 0, DockDesktop, 50, p );
+}
+
+KDockWidget::DockPosition KDockWidget::currentDockPosition() const
+{
+ return currentDockPos;
+}
+
+void KDockWidget::undock()
+{
+// kdDebug(282)<<"KDockWidget::undock()"<<endl;
+
+ manager->d->dragRect = QRect ();
+ manager->drawDragRectangle ();
+
+ QWidget* parentW = parentWidget();
+ if ( !parentW ){
+ hide();
+ if (!d->blockHasUndockedSignal)
+ emit hasUndocked();
+ return;
+ }
+
+ formerDockPos = currentDockPos;
+ currentDockPos = KDockWidget::DockDesktop;
+
+ manager->blockSignals(true);
+ manager->undockProcess = true;
+
+ bool isV = parentW->isVisibleToTLW();
+
+ //UNDOCK HAS TO BE IMPLEMENTED CORRECTLY :)
+ KDockTabGroup* parentTab = parentDockTabGroup();
+ if ( parentTab ){
+ d->index = parentTab->indexOf( this); // memorize the page position in the tab widget
+ parentTab->removePage( this );
+/*
+ QWidget *wantTransient=parentTab->transientTo();
+ target->setDockWindowTransient(wantTransient,wantTransient);
+ */
+ setFormerBrotherDockWidget((KDockWidget*)parentTab->page(0));
+ applyToWidget( 0L );
+ if ( parentTab->count() == 1 ){
+
+ // last subdock widget in the tab control
+ KDockWidget* lastTab = (KDockWidget*)parentTab->page(0);
+ parentTab->removePage( lastTab );
+/* QWidget *wantTransient=parentTab->transientTo();
+ target->setDockWindowTransient(wantTransient,wantTransient);*/
+
+ lastTab->applyToWidget( 0L );
+ lastTab->move( parentTab->mapToGlobal(parentTab->frameGeometry().topLeft()) );
+
+ // KDockTabGroup always have a parent that is a KDockWidget
+ KDockWidget* parentOfTab = (KDockWidget*)parentTab->parent();
+ delete parentTab; // KDockTabGroup
+
+ QWidget* parentOfDockWidget = parentOfTab->parentWidget();
+ if ( !parentOfDockWidget ){
+ if ( isV ) lastTab->show();
+ } else {
+ if ( parentOfDockWidget->inherits("KDockSplitter") ){
+ KDockSplitter* split = (KDockSplitter*)parentOfDockWidget;
+ lastTab->applyToWidget( split );
+ split->deactivate();
+ if ( split->getFirst() == parentOfTab ){
+ split->activate( lastTab );
+ if ( ((KDockWidget*)split->parent())->splitterOrientation == Vertical )
+ emit ((KDockWidget*)split->getAnother(parentOfTab))->docking( parentOfTab, KDockWidget::DockLeft );
+ else
+ emit ((KDockWidget*)split->getAnother(parentOfTab))->docking( parentOfTab, KDockWidget::DockTop );
+ } else {
+ split->activate( 0L, lastTab );
+ if ( ((KDockWidget*)split->parent())->splitterOrientation == Vertical )
+ emit ((KDockWidget*)split->getAnother(parentOfTab))->docking( parentOfTab, KDockWidget::DockRight );
+ else
+ emit ((KDockWidget*)split->getAnother(parentOfTab))->docking( parentOfTab, KDockWidget::DockBottom );
+ }
+ split->show();
+ } else {
+ lastTab->applyToWidget( parentOfDockWidget );
+ }
+ lastTab->show();
+ }
+ manager->blockSignals(false);
+ emit manager->replaceDock( parentOfTab, lastTab );
+ lastTab->currentDockPos = parentOfTab->currentDockPos;
+ emit parentOfTab->iMBeingClosed();
+ manager->blockSignals(true);
+ delete parentOfTab;
+
+ } else {
+ setDockTabName( parentTab );
+ }
+ } else {
+ /*********************************************************************************************/
+ //QWidget* containerWidget = (QWidget*)parent();
+ bool undockedFromContainer=false;
+ if (d->container)
+ {
+// kdDebug(282)<<"undocked from dockcontainer"<<endl;
+ undockedFromContainer=true;
+ KDockContainer* dc = dynamic_cast<KDockContainer*>(d->container.operator->());
+ if (dc) {
+ dc->undockWidget(this);
+ setFormerBrotherDockWidget(dc->parentDockWidget());
+ }
+ applyToWidget( 0L );
+ }
+ if (!undockedFromContainer) {
+/*********************************************************************************************/
+ if ( parentW->inherits("KDockSplitter") ){
+ KDockSplitter* parentSplitterOfDockWidget = (KDockSplitter*)parentW;
+ d->splitPosInPercent = parentSplitterOfDockWidget->separatorPosInPercent();
+
+ KDockWidget* secondWidget = (KDockWidget*)parentSplitterOfDockWidget->getAnother( this );
+ KDockWidget* group = (KDockWidget*)parentSplitterOfDockWidget->parentWidget();
+ setFormerBrotherDockWidget(secondWidget);
+ applyToWidget( 0L );
+ group->hide();
+
+ if ( !group->parentWidget() ){
+ secondWidget->applyToWidget( 0L, group->frameGeometry().topLeft() );
+ secondWidget->resize( group->width(), group->height() );
+ } else {
+ QWidget* obj = group->parentWidget();
+ secondWidget->applyToWidget( obj );
+ if ( obj->inherits("KDockSplitter") ){
+ KDockSplitter* parentOfGroup = (KDockSplitter*)obj;
+ parentOfGroup->deactivate();
+
+ if ( parentOfGroup->getFirst() == group )
+ parentOfGroup->activate( secondWidget );
+ else
+ parentOfGroup->activate( 0L, secondWidget );
+ }
+ }
+ secondWidget->currentDockPos = group->currentDockPos;
+ secondWidget->formerDockPos = group->formerDockPos;
+ delete parentSplitterOfDockWidget;
+ manager->blockSignals(false);
+ emit manager->replaceDock( group, secondWidget );
+ emit group->iMBeingClosed();
+ manager->blockSignals(true);
+ delete group;
+
+ if ( isV ) secondWidget->show();
+ } else {
+ if (!d->pendingDtor) {
+ // don't reparent in the dtor of this
+ applyToWidget( 0L );
+ }
+ }
+/*********************************************************************************************/
+ }
+ }
+ manager->blockSignals(false);
+ if (!d->blockHasUndockedSignal)
+ emit manager->change();
+ manager->undockProcess = false;
+
+ if (!d->blockHasUndockedSignal)
+ emit hasUndocked();
+}
+
+void KDockWidget::setWidget( QWidget* mw )
+{
+ if ( !mw ) return;
+
+ if ( mw->parent() != this ){
+ mw->reparent(this, 0, QPoint(0,0), false);
+ }
+
+#ifdef BORDERLESS_WINDOWS
+ if (!mw->ownCursor()) mw->setCursor(QCursor(ArrowCursor));
+#endif
+ widget = mw;
+ delete layout;
+
+ layout = new QVBoxLayout( this );
+ layout->setResizeMode( QLayout::Minimum );
+
+ KDockContainer* dc = dynamic_cast<KDockContainer*>(widget);
+ if (dc)
+ {
+ d->isContainer=true;
+ manager->d->containerDocks.append(this);
+ }
+ else
+ {
+ d->isContainer=false;
+ }
+
+ {
+ header->show();
+ layout->addWidget( header );
+ layout->addWidget( widget,1 );
+ }
+ updateHeader();
+ emit widgetSet(mw);
+}
+
+void KDockWidget::setDockTabName( KDockTabGroup* tab )
+{
+ QString listOfName;
+ QString listOfCaption;
+ for ( int i = 0; i < tab->count(); ++i ) {
+ QWidget *w = tab->page( i );
+ listOfCaption.append( w->caption() ).append(",");
+ listOfName.append( w->name() ).append(",");
+ }
+ listOfCaption.remove( listOfCaption.length()-1, 1 );
+ listOfName.remove( listOfName.length()-1, 1 );
+
+ tab->parentWidget()->setName( listOfName.utf8() );
+ tab->parentWidget()->setCaption( listOfCaption );
+
+ tab->parentWidget()->repaint( false ); // KDockWidget->repaint
+ if ( tab->parentWidget()->parent() )
+ if ( tab->parentWidget()->parent()->inherits("KDockSplitter") )
+ ((KDockSplitter*)(tab->parentWidget()->parent()))->updateName();
+}
+
+bool KDockWidget::mayBeHide() const
+{
+ bool f = (parent() != manager->main);
+ return ( !isGroup && !isTabGroup && f && isVisible() && ( eDocking != (int)KDockWidget::DockNone ) );
+}
+
+bool KDockWidget::mayBeShow() const
+{
+ bool f = (parent() != manager->main);
+ return ( !isGroup && !isTabGroup && f && !isVisible() );
+}
+
+void KDockWidget::changeHideShowState()
+{
+ if ( mayBeHide() ){
+ undock();
+ return;
+ }
+
+ if ( mayBeShow() ){
+ if ( manager->main->inherits("KDockMainWindow") ){
+ ((KDockMainWindow*)manager->main)->makeDockVisible(this);
+ } else {
+ makeDockVisible();
+ }
+ }
+}
+
+void KDockWidget::makeDockVisible()
+{
+ if ( parentDockTabGroup() ){
+ parentDockTabGroup()->showPage( this );
+ }
+ if (parentDockContainer()) {
+ QWidget *contWid=parentDockContainer();
+ KDockContainer *x = dynamic_cast<KDockContainer*>(contWid);
+ if (x) {
+ x->showWidget(this);
+ }
+ }
+ if ( isVisible() ) return;
+
+ QWidget* p = parentWidget();
+ while ( p ){
+ if ( !p->isVisible() )
+ p->show();
+ p = p->parentWidget();
+ }
+ if( !parent() ) // is undocked
+ dockBack();
+ show();
+}
+
+void KDockWidget::setFormerBrotherDockWidget(KDockWidget *dockWidget)
+{
+ formerBrotherDockWidget = dockWidget;
+ if( formerBrotherDockWidget )
+ QObject::connect( formerBrotherDockWidget, SIGNAL(iMBeingClosed()),
+ this, SLOT(loseFormerBrotherDockWidget()) );
+}
+
+void KDockWidget::loseFormerBrotherDockWidget()
+{
+ if( formerBrotherDockWidget )
+ QObject::disconnect( formerBrotherDockWidget, SIGNAL(iMBeingClosed()),
+ this, SLOT(loseFormerBrotherDockWidget()) );
+ formerBrotherDockWidget = 0L;
+ repaint();
+}
+
+void KDockWidget::dockBack()
+{
+ if( formerBrotherDockWidget) {
+ // search all children if it tries to dock back to a child
+ bool found = false;
+ QObjectList* cl = queryList("KDockWidget");
+ QObjectListIt it( *cl );
+ QObject * obj;
+ while ( !found && (obj=it.current()) != 0 ) {
+ ++it;
+ QWidget* widg = (QWidget*)obj;
+ if( widg == formerBrotherDockWidget)
+ found = true;
+ }
+ delete cl;
+
+ if( !found) {
+ // can dock back to the former brother dockwidget
+ manualDock( formerBrotherDockWidget, formerDockPos, d->splitPosInPercent, QPoint(0,0), false, d->index);
+ formerBrotherDockWidget = 0L;
+ makeDockVisible();
+ return;
+ }
+ }
+
+ // else dockback to the dockmainwindow (default behavior)
+ manualDock( ((KDockMainWindow*)manager->main)->getMainDockWidget(), formerDockPos, d->splitPosInPercent, QPoint(0,0), false, d->index);
+ formerBrotherDockWidget = 0L;
+ if (parent())
+ makeDockVisible();
+}
+
+bool KDockWidget::isDockBackPossible() const
+{
+ if( !(formerBrotherDockWidget) || !(formerBrotherDockWidget->dockSite() & formerDockPos))
+ return false;
+ else
+ return true;
+}
+
+/**************************************************************************************/
+
+
+KDockManager::KDockManager( QWidget* mainWindow , const char* name )
+:QObject( mainWindow, name )
+ ,main(mainWindow)
+ ,currentDragWidget(0L)
+ ,currentMoveWidget(0L)
+ ,childDockWidgetList(0L)
+ ,autoCreateDock(0L)
+ ,storeW(0)
+ ,storeH(0)
+ ,dragging(false)
+ ,undockProcess(false)
+ ,dropCancel(true)
+{
+ d = new KDockManagerPrivate;
+
+ d->readyToDrag = false;
+ d->mainDockWidget=0;
+
+#ifndef NO_KDE2
+ d->splitterOpaqueResize = KGlobalSettings::opaqueResize();
+#else
+ d->splitterOpaqueResize = false;
+#endif
+
+ d->splitterKeepSize = false;
+ d->splitterHighResolution = false;
+ d->m_readDockConfigMode = WrapExistingWidgetsOnly; // default as before
+
+ main->installEventFilter( this );
+
+ undockProcess = false;
+
+ menuData = new QPtrList<MenuDockData>;
+ menuData->setAutoDelete( true );
+ menuData->setAutoDelete( true );
+
+#ifndef NO_KDE2
+ menu = new KPopupMenu();
+#else
+ menu = new QPopupMenu();
+#endif
+
+ connect( menu, SIGNAL(aboutToShow()), SLOT(slotMenuPopup()) );
+ connect( menu, SIGNAL(activated(int)), SLOT(slotMenuActivated(int)) );
+
+ childDock = new QObjectList();
+ childDock->setAutoDelete( false );
+}
+
+
+void KDockManager::setMainDockWidget2(KDockWidget *w)
+{
+ d->mainDockWidget=w;
+}
+
+KDockManager::~KDockManager()
+{
+ delete menuData;
+ delete menu;
+
+ QObjectListIt it( *childDock );
+ KDockWidget * obj;
+
+ while ( (obj=(KDockWidget*)it.current()) ) {
+ delete obj;
+ }
+ delete childDock;
+ delete d;
+ d=0;
+}
+
+void KDockManager::activate()
+{
+ QObjectListIt it( *childDock );
+ KDockWidget * obj;
+
+ while ( (obj=(KDockWidget*)it.current()) ) {
+ ++it;
+ if ( obj->widget ) obj->widget->show();
+ if ( !obj->parentDockTabGroup() ){
+ obj->show();
+ }
+ }
+ if ( !main->inherits("QDialog") ) main->show();
+}
+
+bool KDockManager::eventFilter( QObject *obj, QEvent *event )
+{
+
+ if ( obj->inherits("KDockWidgetAbstractHeaderDrag") ){
+ KDockWidget* pDockWdgAtCursor = 0L;
+ KDockWidget* curdw = ((KDockWidgetAbstractHeaderDrag*)obj)->dockWidget();
+ switch ( event->type() ){
+ case QEvent::MouseButtonDblClick:
+ if (curdw->currentDockPos == KDockWidget::DockDesktop) curdw->dockBack();
+ else
+ {
+ curdw->toDesktop();
+ // curdw->manualDock (0, KDockWidget::DockDesktop);
+ }
+ break;
+
+ case QEvent::MouseButtonPress:
+ if ( ((QMouseEvent*)event)->button() == LeftButton ){
+ if ( curdw->eDocking != (int)KDockWidget::DockNone ){
+ dropCancel = true;
+ curdw->setFocus();
+ qApp->processOneEvent();
+
+ currentDragWidget = curdw;
+ currentMoveWidget = 0L;
+ childDockWidgetList = new QWidgetList();
+ childDockWidgetList->append( curdw );
+ findChildDockWidget( curdw, childDockWidgetList );
+
+ //d->oldDragRect = QRect(); should fix rectangle not erased problem
+ d->dragRect = QRect(curdw->geometry());
+ QPoint p = curdw->mapToGlobal(QPoint(0,0));
+ d->dragRect.moveTopLeft(p);
+ drawDragRectangle();
+ d->readyToDrag = true;
+
+ d->dragOffset = QCursor::pos()-currentDragWidget->mapToGlobal(QPoint(0,0));
+ }
+
+ }
+ break;
+ case QEvent::MouseButtonRelease:
+ if ( ((QMouseEvent*)event)->button() == LeftButton ){
+ if ( dragging ){
+ if ( !dropCancel )
+ drop();
+ else
+ cancelDrop();
+ }
+ if (d->readyToDrag) {
+ d->readyToDrag = false;
+ //d->oldDragRect = QRect(); should fix rectangle not erased problem
+ d->dragRect = QRect(curdw->geometry());
+ QPoint p = curdw->mapToGlobal(QPoint(0,0));
+ d->dragRect.moveTopLeft(p);
+ drawDragRectangle();
+ currentDragWidget = 0L;
+ delete childDockWidgetList;
+ childDockWidgetList = 0L;
+ }
+ dragging = false;
+ dropCancel = true;
+ }
+ break;
+ case QEvent::MouseMove:
+ if ( dragging ) {
+
+#ifdef BORDERLESS_WINDOWS
+//BEGIN TEST
+ KDockWidget *oldMoveWidget;
+ if (!curdw->parent())
+ {
+ curdw->move(QCursor::pos()-d->dragOffset);
+ pDockWdgAtCursor = findDockWidgetAt( QCursor::pos()-QPoint(0,d->dragOffset.y()+3) );
+ oldMoveWidget = currentMoveWidget;
+ }
+ else
+ {
+ pDockWdgAtCursor = findDockWidgetAt( QCursor::pos() );
+ oldMoveWidget = currentMoveWidget;
+ }
+//END TEST
+#else
+ pDockWdgAtCursor = findDockWidgetAt( QCursor::pos() );
+ KDockWidget* oldMoveWidget = currentMoveWidget;
+#endif
+
+ if ( currentMoveWidget && pDockWdgAtCursor == currentMoveWidget ) { //move
+ dragMove( currentMoveWidget, currentMoveWidget->mapFromGlobal( QCursor::pos() ) );
+ break;
+ } else {
+ if (dropCancel && curdw) {
+ d->dragRect = QRect(curdw->geometry());
+ QPoint p = curdw->mapToGlobal(QPoint(0,0));
+ d->dragRect.moveTopLeft(p);
+ }else
+ d->dragRect = QRect();
+
+ drawDragRectangle();
+ }
+
+ if ( !pDockWdgAtCursor && !(curdw->eDocking & (int)KDockWidget::DockDesktop) ){
+ // just moving at the desktop
+ currentMoveWidget = pDockWdgAtCursor;
+ curPos = KDockWidget::DockDesktop;
+ } else {
+ if ( oldMoveWidget && pDockWdgAtCursor != currentMoveWidget ) { //leave
+ currentMoveWidget = pDockWdgAtCursor;
+ curPos = KDockWidget::DockDesktop;
+ }
+ }
+
+ if ( oldMoveWidget != pDockWdgAtCursor && pDockWdgAtCursor ) { //enter pDockWdgAtCursor
+ currentMoveWidget = pDockWdgAtCursor;
+ curPos = KDockWidget::DockDesktop;
+ }
+ } else {
+ if (d->readyToDrag) {
+ d->readyToDrag = false;
+ }
+ if ( (((QMouseEvent*)event)->state() == LeftButton) &&
+ (curdw->eDocking != (int)KDockWidget::DockNone) ) {
+ startDrag( curdw);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return QObject::eventFilter( obj, event );
+}
+
+KDockWidget* KDockManager::findDockWidgetAt( const QPoint& pos )
+{
+ dropCancel = true;
+
+ if (!currentDragWidget)
+ return 0L; // pointer access safety
+
+ if (currentDragWidget->eDocking == (int)KDockWidget::DockNone ) return 0L;
+
+ QWidget* p = QApplication::widgetAt( pos );
+ if ( !p ) {
+ dropCancel = false;
+ return 0L;
+ }
+#if defined(_OS_WIN32_) || defined(Q_OS_WIN32)
+ p = p->topLevelWidget();
+#endif
+ QWidget* w = 0L;
+ findChildDockWidget( w, p, p->mapFromGlobal(pos) );
+ if ( !w ){
+ if ( !p->inherits("KDockWidget") ) {
+ return 0L;
+ }
+ w = p;
+ }
+ if ( qt_find_obj_child( w, "KDockSplitter", "_dock_split_" ) ) return 0L;
+ if ( qt_find_obj_child( w, "KDockTabGroup", "_dock_tab" ) ) return 0L;
+ if (dynamic_cast<KDockContainer*>(w)) return 0L;
+
+ if (!childDockWidgetList) return 0L;
+ if ( childDockWidgetList->find(w) != -1 ) return 0L;
+ if ( currentDragWidget->isGroup && ((KDockWidget*)w)->parentDockTabGroup() ) return 0L;
+
+ KDockWidget* www = (KDockWidget*)w;
+ if ( www->sDocking == (int)KDockWidget::DockNone ) return 0L;
+ if( !www->widget )
+ return 0L;
+
+ KDockWidget::DockPosition curPos = KDockWidget::DockDesktop;
+ QPoint cpos = www->mapFromGlobal( pos );
+
+ int ww = www->widget->width() / 3;
+ int hh = www->widget->height() / 3;
+
+ if ( cpos.y() <= hh ){
+ curPos = KDockWidget::DockTop;
+ } else
+ if ( cpos.y() >= 2*hh ){
+ curPos = KDockWidget::DockBottom;
+ } else
+ if ( cpos.x() <= ww ){
+ curPos = KDockWidget::DockLeft;
+ } else
+ if ( cpos.x() >= 2*ww ){
+ curPos = KDockWidget::DockRight;
+ } else
+ curPos = KDockWidget::DockCenter;
+
+ if ( !(www->sDocking & (int)curPos) ) return 0L;
+ if ( !(currentDragWidget->eDocking & (int)curPos) ) return 0L;
+ if ( www->manager != this ) return 0L;
+
+ dropCancel = false;
+ return www;
+}
+
+void KDockManager::findChildDockWidget( QWidget*& ww, const QWidget* p, const QPoint& pos )
+{
+ if ( p->children() ) {
+ QWidget *w;
+ QObjectListIt it( *p->children() );
+ it.toLast();
+ while ( it.current() ) {
+ if ( it.current()->isWidgetType() ) {
+ w = (QWidget*)it.current();
+ if ( w->isVisible() && w->geometry().contains(pos) ) {
+ if ( w->inherits("KDockWidget") ) ww = w;
+ findChildDockWidget( ww, w, w->mapFromParent(pos) );
+ return;
+ }
+ }
+ --it;
+ }
+ }
+ return;
+}
+
+void KDockManager::findChildDockWidget( const QWidget* p, QWidgetList*& list )
+{
+ if ( p->children() ) {
+ QWidget *w;
+ QObjectListIt it( *p->children() );
+ it.toLast();
+ while ( it.current() ) {
+ if ( it.current()->isWidgetType() ) {
+ w = (QWidget*)it.current();
+ if ( w->isVisible() ) {
+ if ( w->inherits("KDockWidget") ) list->append( w );
+ findChildDockWidget( w, list );
+ }
+ }
+ --it;
+ }
+ }
+ return;
+}
+
+void KDockManager::startDrag( KDockWidget* w )
+{
+ if(( w->currentDockPos == KDockWidget::DockLeft) || ( w->currentDockPos == KDockWidget::DockRight)
+ || ( w->currentDockPos == KDockWidget::DockTop) || ( w->currentDockPos == KDockWidget::DockBottom)) {
+ w->prevSideDockPosBeforeDrag = w->currentDockPos;
+
+ if ( w->parentWidget()->inherits("KDockSplitter") ){
+ KDockSplitter* parentSplitterOfDockWidget = (KDockSplitter*)(w->parentWidget());
+ w->d->splitPosInPercent = parentSplitterOfDockWidget->separatorPosInPercent();
+ }
+ }
+
+ curPos = KDockWidget::DockDesktop;
+ dragging = true;
+
+ QApplication::setOverrideCursor(QCursor(sizeAllCursor));
+}
+
+void KDockManager::dragMove( KDockWidget* dw, QPoint pos )
+{
+ QPoint p = dw->mapToGlobal( dw->widget->pos() );
+ KDockWidget::DockPosition oldPos = curPos;
+
+ QSize r = dw->widget->size();
+ if ( dw->parentDockTabGroup() ){
+ curPos = KDockWidget::DockCenter;
+ if ( oldPos != curPos ) {
+ d->dragRect.setRect( p.x()+2, p.y()+2, r.width()-4, r.height()-4 );
+ }
+ return;
+ }
+
+ int w = r.width() / 3;
+ int h = r.height() / 3;
+
+ if ( pos.y() <= h ){
+ curPos = KDockWidget::DockTop;
+ w = r.width();
+ } else
+ if ( pos.y() >= 2*h ){
+ curPos = KDockWidget::DockBottom;
+ p.setY( p.y() + 2*h );
+ w = r.width();
+ } else
+ if ( pos.x() <= w ){
+ curPos = KDockWidget::DockLeft;
+ h = r.height();
+ } else
+ if ( pos.x() >= 2*w ){
+ curPos = KDockWidget::DockRight;
+ p.setX( p.x() + 2*w );
+ h = r.height();
+ } else
+ {
+ curPos = KDockWidget::DockCenter;
+ p.setX( p.x() + w );
+ p.setY( p.y() + h );
+ }
+
+ if ( oldPos != curPos ) {
+ d->dragRect.setRect( p.x(), p.y(), w, h );
+ drawDragRectangle();
+ }
+}
+
+
+void KDockManager::cancelDrop()
+{
+ QApplication::restoreOverrideCursor();
+
+ delete childDockWidgetList;
+ childDockWidgetList = 0L;
+
+ d->dragRect = QRect(); // cancel drawing
+ drawDragRectangle(); // only the old rect will be deleted
+}
+
+
+void KDockManager::drop()
+{
+ d->dragRect = QRect(); // cancel drawing
+ drawDragRectangle(); // only the old rect will be deleted
+
+ QApplication::restoreOverrideCursor();
+
+ delete childDockWidgetList;
+ childDockWidgetList = 0L;
+
+ if ( dropCancel ) return;
+ if ( !currentMoveWidget && (!(currentDragWidget->eDocking & (int)KDockWidget::DockDesktop)) ) {
+ d->dragRect = QRect(); // cancel drawing
+ drawDragRectangle(); // only the old rect will be deleted
+ return;
+ }
+ if ( !currentMoveWidget && !currentDragWidget->parent() ) {
+ currentDragWidget->move( QCursor::pos() - d->dragOffset );
+ }
+ else {
+ // curPos is the current target DockPosition.
+ // currentDragWidget->prevSideDockPosBeforeDrag is where the dockwidget comes from.
+ // currentDragWidget->formerDockPos is the position *before* the dockwidget was in
+ // position currentDragWidget->prevSideDockPosBeforeDrag.
+ int splitPos = currentDragWidget->d->splitPosInPercent;
+ KDockWidget::DockPosition previousPosition = currentDragWidget->prevSideDockPosBeforeDrag;
+
+// kdDebug() << splitPos << endl;
+// kdDebug() << "curPos: " << curPos << endl;
+// kdDebug() << "formerDockPos: " << currentDragWidget->formerDockPos<< endl;
+// kdDebug() << "prevSideDockPosBeforeDrag: " << currentDragWidget->prevSideDockPosBeforeDrag<< endl;
+
+ // Now we *need* to "invert" the procentual value, if the dockwidget moves from top/left
+ // to bottom/right or vice versa. This keeps the dockwidget's size on its new position.
+ // A special case is, when the dock position was DockNone, then we have to look for the
+ // formerDockPos to get things right.
+ if( (curPos != previousPosition)
+ && (curPos != KDockWidget::DockCenter) && (curPos != KDockWidget::DockDesktop)) {
+
+ if (previousPosition == KDockWidget::DockNone)
+ previousPosition = currentDragWidget->formerDockPos;
+
+ switch( previousPosition ) {
+ case KDockWidget::DockLeft:
+ if(curPos != KDockWidget::DockTop && curPos != KDockWidget::DockLeft)
+ splitPos = 100 - splitPos;
+ break;
+
+ case KDockWidget::DockRight:
+ if(curPos != KDockWidget::DockBottom && curPos != KDockWidget::DockRight)
+ splitPos = 100 - splitPos;
+ break;
+
+ case KDockWidget::DockTop:
+ if(curPos != KDockWidget::DockLeft && curPos != KDockWidget::DockTop )
+ splitPos = 100 - splitPos;
+ break;
+
+ case KDockWidget::DockBottom:
+ if(curPos != KDockWidget::DockRight && curPos != KDockWidget::DockBottom )
+ splitPos = 100 - splitPos;
+ break;
+
+ default: break;
+ }
+ }
+ // set new prevSideDockPosBeforeDrag
+ currentDragWidget->prevSideDockPosBeforeDrag = curPos;
+ currentDragWidget->manualDock( currentMoveWidget, curPos , splitPos, QCursor::pos() - d->dragOffset );
+ currentDragWidget->makeDockVisible();
+ }
+}
+
+
+static QDomElement createStringEntry(QDomDocument &doc, const QString &tagName, const QString &str)
+{
+ QDomElement el = doc.createElement(tagName);
+
+ el.appendChild(doc.createTextNode(str));
+ return el;
+}
+
+
+static QDomElement createBoolEntry(QDomDocument &doc, const QString &tagName, bool b)
+{
+ return createStringEntry(doc, tagName, QString::fromLatin1(b? "true" : "false"));
+}
+
+
+static QDomElement createNumberEntry(QDomDocument &doc, const QString &tagName, int n)
+{
+ return createStringEntry(doc, tagName, QString::number(n));
+}
+
+
+static QDomElement createRectEntry(QDomDocument &doc, const QString &tagName, const QRect &rect)
+{
+ QDomElement el = doc.createElement(tagName);
+
+ QDomElement xel = doc.createElement("x");
+ xel.appendChild(doc.createTextNode(QString::number(rect.x())));
+ el.appendChild(xel);
+ QDomElement yel = doc.createElement("y");
+ yel.appendChild(doc.createTextNode(QString::number(rect.y())));
+ el.appendChild(yel);
+ QDomElement wel = doc.createElement("width");
+ wel.appendChild(doc.createTextNode(QString::number(rect.width())));
+ el.appendChild(wel);
+ QDomElement hel = doc.createElement("height");
+ hel.appendChild(doc.createTextNode(QString::number(rect.height())));
+ el.appendChild(hel);
+
+ return el;
+}
+
+
+static QDomElement createListEntry(QDomDocument &doc, const QString &tagName,
+ const QString &subTagName, const QStrList &list)
+{
+ QDomElement el = doc.createElement(tagName);
+
+ QStrListIterator it(list);
+ for (; it.current(); ++it) {
+ QDomElement subel = doc.createElement(subTagName);
+ subel.appendChild(doc.createTextNode(QString::fromLatin1(it.current())));
+ el.appendChild(subel);
+ }
+
+ return el;
+}
+
+
+static QString stringEntry(QDomElement &base, const QString &tagName)
+{
+ return base.namedItem(tagName).firstChild().toText().data();
+}
+
+
+static bool boolEntry(QDomElement &base, const QString &tagName)
+{
+ return base.namedItem(tagName).firstChild().toText().data() == "true";
+}
+
+
+static int numberEntry(QDomElement &base, const QString &tagName)
+{
+ return stringEntry(base, tagName).toInt();
+}
+
+
+static QRect rectEntry(QDomElement &base, const QString &tagName)
+{
+ QDomElement el = base.namedItem(tagName).toElement();
+
+ int x = numberEntry(el, "x");
+ int y = numberEntry(el, "y");
+ int width = numberEntry(el, "width");
+ int height = numberEntry(el, "height");
+
+ return QRect(x, y, width, height);
+}
+
+
+static QStrList listEntry(QDomElement &base, const QString &tagName, const QString &subTagName)
+{
+ QStrList list;
+
+ for( QDomNode n = base.namedItem(tagName).firstChild(); !n.isNull(); n = n.nextSibling() )
+ {
+ QDomElement subel = n.toElement();
+ if (subel.tagName() == subTagName)
+ list.append(subel.firstChild().toText().data().latin1());
+ }
+
+ return list;
+}
+
+
+void KDockManager::writeConfig(QDomElement &base)
+{
+ // First of all, clear the tree under base
+ while (!base.firstChild().isNull())
+ base.removeChild(base.firstChild());
+ QDomDocument doc = base.ownerDocument();
+
+ QStrList nameList;
+ QString mainWidgetStr;
+
+ // collect widget names
+ QStringList nList;
+ QObjectListIt it(*childDock);
+ KDockWidget *obj1;
+ while ( (obj1=(KDockWidget*)it.current()) ) {
+ if ( obj1->parent() == main )
+ mainWidgetStr = QString::fromLatin1(obj1->name());
+ nList.append(obj1->name());
+ ++it;
+ }
+
+ for (QObjectListIt it(d->containerDocks);it.current();++it)
+ {
+ KDockContainer* dc = dynamic_cast<KDockContainer*>(((KDockWidget*)it.current())->widget);
+ if (dc) {
+ dc->prepareSave(nList);
+ }
+ }
+
+ QStringList::Iterator nListIt=nList.begin();
+ while ( nListIt!=nList.end() ) {
+ KDockWidget *obj = getDockWidgetFromName( *nListIt);
+ if ((obj->isGroup && (!obj->d->isContainer)) && (nameList.find( obj->firstName.latin1() ) == -1
+ || nameList.find(obj->lastName.latin1()) == -1)) {
+ // Skip until children are saved (why?)
+ ++nListIt;
+// nList.next();
+//falk? if ( !nList.current() ) nList.first();
+ continue;
+ }
+
+ QDomElement groupEl;
+ if (obj->d->isContainer) {
+ KDockContainer* x = dynamic_cast<KDockContainer*>(obj->widget);
+ if (x) {
+ groupEl=doc.createElement("dockContainer");
+ x->save(groupEl);
+ }
+ } else
+ if (obj->isGroup) {
+ //// Save a group
+ groupEl = doc.createElement("splitGroup");
+
+ groupEl.appendChild(createStringEntry(doc, "firstName", obj->firstName));
+ groupEl.appendChild(createStringEntry(doc, "secondName", obj->lastName));
+ groupEl.appendChild(createNumberEntry(doc, "orientation", (int)obj->splitterOrientation));
+ groupEl.appendChild(createNumberEntry(doc, "separatorPos", ((KDockSplitter*)obj->widget)->separatorPosInPercent()));
+ } else if (obj->isTabGroup) {
+ //// Save a tab group
+ groupEl = doc.createElement("tabGroup");
+
+ QStrList list;
+ for ( int i = 0; i < ((KDockTabGroup*)obj->widget)->count(); ++i )
+ list.append( ((KDockTabGroup*)obj->widget)->page( i )->name() );
+ groupEl.appendChild(createListEntry(doc, "tabs", "tab", list));
+ groupEl.appendChild(createNumberEntry(doc, "currentTab", ((KDockTabGroup*)obj->widget)->currentPageIndex()));
+ if (!obj->parent()) {
+ groupEl.appendChild(createStringEntry(doc, "dockBackTo", obj->formerBrotherDockWidget ? obj->formerBrotherDockWidget->name() : ""));
+ groupEl.appendChild(createNumberEntry(doc, "dockBackToPos", obj->formerDockPos));
+ }
+ } else {
+ //// Save an ordinary dock widget
+ groupEl = doc.createElement("dock");
+ groupEl.appendChild(createStringEntry(doc, "tabCaption", obj->tabPageLabel()));
+ groupEl.appendChild(createStringEntry(doc, "tabToolTip", obj->toolTipString()));
+ if (!obj->parent()) {
+ groupEl.appendChild(createStringEntry(doc, "dockBackTo", obj->formerBrotherDockWidget ? obj->formerBrotherDockWidget->name() : ""));
+ groupEl.appendChild(createNumberEntry(doc, "dockBackToPos", obj->formerDockPos));
+ }
+ }
+
+ groupEl.appendChild(createStringEntry(doc, "name", QString::fromLatin1(obj->name())));
+ groupEl.appendChild(createBoolEntry(doc, "hasParent", obj->parent()));
+ if ( !obj->parent() ) {
+ groupEl.appendChild(createRectEntry(doc, "geometry", QRect(main->frameGeometry().topLeft(), main->size())));
+ groupEl.appendChild(createBoolEntry(doc, "visible", obj->isVisible()));
+ }
+ if (obj->header && obj->header->inherits("KDockWidgetHeader")) {
+ KDockWidgetHeader *h = static_cast<KDockWidgetHeader*>(obj->header);
+ groupEl.appendChild(createBoolEntry(doc, "dragEnabled", h->dragEnabled()));
+ }
+
+ base.appendChild(groupEl);
+ nameList.append(obj->name());
+ nList.remove(nListIt);
+ nListIt=nList.begin();
+ }
+
+ if (main->inherits("KDockMainWindow")) {
+ KDockMainWindow *dmain = (KDockMainWindow*)main;
+ QString centralWidgetStr = QString(dmain->centralWidget()? dmain->centralWidget()->name() : "");
+ base.appendChild(createStringEntry(doc, "centralWidget", centralWidgetStr));
+ QString mainDockWidgetStr = QString(dmain->getMainDockWidget()? dmain->getMainDockWidget()->name() : "");
+ base.appendChild(createStringEntry(doc, "mainDockWidget", mainDockWidgetStr));
+ } else {
+ base.appendChild(createStringEntry(doc, "mainWidget", mainWidgetStr));
+ }
+
+ base.appendChild(createRectEntry(doc, "geometry", QRect(main->frameGeometry().topLeft(), main->size())));
+}
+
+
+void KDockManager::readConfig(QDomElement &base)
+{
+ if (base.namedItem("group").isNull()
+ && base.namedItem("tabgroup").isNull()
+ && base.namedItem("dock").isNull()
+ && base.namedItem("dockContainer").isNull()) {
+ activate();
+ return;
+ }
+
+ autoCreateDock = new QObjectList();
+ autoCreateDock->setAutoDelete( true );
+
+ bool isMainVisible = main->isVisible();
+ main->hide();
+
+ QObjectListIt it(*childDock);
+ KDockWidget *obj1;
+ while ( (obj1=(KDockWidget*)it.current()) ) {
+ if ( !obj1->isGroup && !obj1->isTabGroup ) {
+ if ( obj1->parent() )
+ obj1->undock();
+ else
+ obj1->hide();
+ }
+ ++it;
+ }
+
+ // firstly, recreate all common dockwidgets
+ for( QDomNode n = base.firstChild(); !n.isNull(); n = n.nextSibling() )
+ {
+ QDomElement childEl = n.toElement();
+ if (childEl.tagName() != "dock") continue;
+
+ // Read an ordinary dock widget
+ KDockWidget *obj = getDockWidgetFromName(stringEntry(childEl, "name"));
+ obj->setTabPageLabel(stringEntry(childEl, "tabCaption"));
+ obj->setToolTipString(stringEntry(childEl, "tabToolTip"));
+
+ if (!boolEntry(childEl, "hasParent")) {
+ QRect r = rectEntry(childEl, "geometry");
+ obj = getDockWidgetFromName(stringEntry(childEl, "name"));
+ obj->applyToWidget(0);
+ obj->setGeometry(r);
+ if (boolEntry(childEl, "visible"))
+ obj->QWidget::show();
+ }
+
+ if (obj && obj->header && obj->header->inherits("KDockWidgetHeader")) {
+ KDockWidgetHeader *h = static_cast<KDockWidgetHeader*>(obj->header);
+ h->setDragEnabled(boolEntry(childEl, "dragEnabled"));
+ }
+ }
+
+ // secondly, now iterate again and create the groups and tabwidgets, apply the dockwidgets to them
+ for( QDomNode n = base.firstChild(); !n.isNull(); n = n.nextSibling() )
+ {
+ QDomElement childEl = n.toElement();
+ if (childEl.isNull()) continue;
+
+ KDockWidget *obj = 0;
+
+ if (childEl.tagName() == "dockContainer") {
+
+ KDockWidget *cont=getDockWidgetFromName(stringEntry(childEl, "name"));
+ kdDebug(282)<<"dockContainer: "<<stringEntry(childEl,"name")<<endl;
+ if (!(cont->d->isContainer)) {
+ kdDebug(282)<<"restoration of dockContainer is only supported for already existing dock containers"<<endl;
+ } else {
+ KDockContainer *dc=dynamic_cast<KDockContainer*>(cont->getWidget());
+ if (!dc) kdDebug(282)<<"Error while trying to handle dockcontainer configuration restoration"<<endl;
+ else {
+ dc->load(childEl);
+ removeFromAutoCreateList(cont);
+ }
+
+ }
+ }
+ else
+ if (childEl.tagName() == "splitGroup") {
+ // Read a group
+ QString name = stringEntry(childEl, "name");
+ QString firstName = stringEntry(childEl, "firstName");
+ QString secondName = stringEntry(childEl, "secondName");
+ int orientation = numberEntry(childEl, "orientation");
+ int separatorPos = numberEntry(childEl, "separatorPos");
+
+ KDockWidget *first = getDockWidgetFromName(firstName);
+ KDockWidget *second = getDockWidgetFromName(secondName);
+ if (first && second) {
+ obj = first->manualDock(second,
+ (orientation == (int)Vertical)? KDockWidget::DockLeft : KDockWidget::DockTop,
+ separatorPos);
+ if (obj)
+ obj->setName(name.latin1());
+ }
+ } else if (childEl.tagName() == "tabGroup") {
+ // Read a tab group
+ QString name = stringEntry(childEl, "name");
+ QStrList list = listEntry(childEl, "tabs", "tab");
+
+ KDockWidget *d1 = getDockWidgetFromName( list.first() );
+ list.next();
+ KDockWidget *d2 = getDockWidgetFromName( list.current() );
+
+ KDockWidget *obj = d2->manualDock( d1, KDockWidget::DockCenter );
+ if (obj) {
+ KDockTabGroup *tab = (KDockTabGroup*)obj->widget;
+ list.next();
+ while (list.current() && obj) {
+ KDockWidget *tabDock = getDockWidgetFromName(list.current());
+ obj = tabDock->manualDock(d1, KDockWidget::DockCenter);
+ list.next();
+ }
+ if (obj) {
+ obj->setName(name.latin1());
+ tab->showPage(tab->page(numberEntry(childEl, "currentTab")));
+ }
+ }
+ } else {
+ continue;
+ }
+
+ if (!boolEntry(childEl, "hasParent")) {
+ QRect r = rectEntry(childEl, "geometry");
+ obj = getDockWidgetFromName(stringEntry(childEl, "name"));
+ obj->applyToWidget(0);
+ obj->setGeometry(r);
+ if (boolEntry(childEl, "visible"))
+ obj->QWidget::show();
+ }
+
+ if (obj && obj->header && obj->header->inherits("KDockWidgetHeader")) {
+ KDockWidgetHeader *h = static_cast<KDockWidgetHeader*>(obj->header);
+ h->setDragEnabled(boolEntry(childEl, "dragEnabled"));
+ }
+ }
+
+ // thirdly, now that all ordinary dockwidgets are created,
+ // iterate them again and link them with their corresponding dockwidget for the dockback action
+ for( QDomNode n = base.firstChild(); !n.isNull(); n = n.nextSibling() )
+ {
+ QDomElement childEl = n.toElement();
+
+ if (childEl.tagName() != "dock" && childEl.tagName() != "tabGroup")
+ continue;
+
+ KDockWidget *obj = 0;
+
+ if (!boolEntry(childEl, "hasParent")) {
+ // Read a common toplevel dock widget
+ obj = getDockWidgetFromName(stringEntry(childEl, "name"));
+ QString name = stringEntry(childEl, "dockBackTo");
+ if (!name.isEmpty()) {
+ obj->setFormerBrotherDockWidget(getDockWidgetFromName(name));
+ }
+ obj->formerDockPos = KDockWidget::DockPosition(numberEntry(childEl, "dockBackToPos"));
+ obj->updateHeader();
+ }
+ }
+
+ if (main->inherits("KDockMainWindow")) {
+ KDockMainWindow *dmain = (KDockMainWindow*)main;
+
+ QString mv = stringEntry(base, "centralWidget");
+ if (!mv.isEmpty() && getDockWidgetFromName(mv) ) {
+ KDockWidget *mvd = getDockWidgetFromName(mv);
+ mvd->applyToWidget(dmain);
+ mvd->show();
+ dmain->setCentralWidget(mvd);
+ }
+ QString md = stringEntry(base, "mainDockWidget");
+ if (!md.isEmpty() && getDockWidgetFromName(md)) {
+ KDockWidget *mvd = getDockWidgetFromName(md);
+ dmain->setMainDockWidget(mvd);
+ }
+ } else {
+ QString mv = stringEntry(base, "mainWidget");
+ if (!mv.isEmpty() && getDockWidgetFromName(mv)) {
+ KDockWidget *mvd = getDockWidgetFromName(mv);
+ mvd->applyToWidget(main);
+ mvd->show();
+ }
+
+ // only resize + move non-mainwindows
+ QRect mr = rectEntry(base, "geometry");
+ main->move(mr.topLeft());
+ main->resize(mr.size());
+ }
+
+ if (isMainVisible)
+ main->show();
+
+ if (d->m_readDockConfigMode == WrapExistingWidgetsOnly) {
+ finishReadDockConfig(); // remove empty dockwidgets
+ }
+}
+
+void KDockManager::removeFromAutoCreateList(KDockWidget* pDockWidget)
+{
+ if (!autoCreateDock) return;
+ autoCreateDock->setAutoDelete(false);
+ autoCreateDock->removeRef(pDockWidget);
+ autoCreateDock->setAutoDelete(true);
+}
+
+void KDockManager::finishReadDockConfig()
+{
+ delete autoCreateDock;
+ autoCreateDock = 0;
+}
+
+void KDockManager::setReadDockConfigMode(int mode)
+{
+ d->m_readDockConfigMode = mode;
+}
+
+#ifndef NO_KDE2
+void KDockManager::writeConfig( KConfig* c, QString group )
+{
+ //debug("BEGIN Write Config");
+ if ( !c ) c = KGlobal::config();
+ if ( group.isEmpty() ) group = "dock_setting_default";
+
+ c->setGroup( group );
+ c->writeEntry( "Version", DOCK_CONFIG_VERSION );
+
+ QStringList nameList;
+ QStringList findList;
+ QObjectListIt it( *childDock );
+ KDockWidget * obj;
+
+ // collect KDockWidget's name
+ QStringList nList;
+ while ( (obj=(KDockWidget*)it.current()) ) {
+ ++it;
+ //debug(" +Add subdock %s", obj->name());
+ nList.append( obj->name() );
+ if ( obj->parent() == main )
+ c->writeEntry( "Main:view", obj->name() );
+ }
+
+// kdDebug(282)<<QString("list size: %1").arg(nList.count())<<endl;
+ for (QObjectListIt it(d->containerDocks);it.current();++it)
+ {
+ KDockContainer* dc = dynamic_cast<KDockContainer*>(((KDockWidget*)it.current())->widget);
+ if (dc) {
+ dc->prepareSave(nList);
+ }
+ }
+// kdDebug(282)<<QString("new list size: %1").arg(nList.count())<<endl;
+
+ QStringList::Iterator nListIt=nList.begin();
+ while ( nListIt!=nList.end() ){
+ //debug(" -Try to save %s", nList.current());
+ obj = getDockWidgetFromName( *nListIt );
+ QString cname = obj->name();
+ if ( obj->header ){
+ obj->header->saveConfig( c );
+ }
+ if (obj->d->isContainer) {
+ KDockContainer* x = dynamic_cast<KDockContainer*>(obj->widget);
+ if (x) {
+ x->save(c,group);
+ }
+ }
+/*************************************************************************************************/
+ if ( obj->isGroup ){
+ if ( (findList.find( obj->firstName ) != findList.end()) && (findList.find( obj->lastName ) != findList.end() )){
+
+ c->writeEntry( cname+":type", "GROUP");
+ if ( !obj->parent() ){
+ c->writeEntry( cname+":parent", "___null___");
+ c->writeEntry( cname+":geometry", QRect(obj->frameGeometry().topLeft(), obj->size()) );
+ c->writeEntry( cname+":visible", obj->isVisible());
+ } else {
+ c->writeEntry( cname+":parent", "yes");
+ }
+ c->writeEntry( cname+":first_name", obj->firstName );
+ c->writeEntry( cname+":last_name", obj->lastName );
+ c->writeEntry( cname+":orientation", (int)obj->splitterOrientation );
+ c->writeEntry( cname+":sepPos", ((KDockSplitter*)obj->widget)->separatorPosInPercent() );
+
+ nameList.append( obj->name() );
+ findList.append( obj->name() );
+ //debug(" Save %s", nList.current());
+ nList.remove(nListIt);
+ nListIt=nList.begin(); //nList.first();
+ } else {
+/*************************************************************************************************/
+ //debug(" Skip %s", nList.current());
+ //if ( findList.find( obj->firstName ) == -1 )
+ // debug(" ? Not found %s", obj->firstName);
+ //if ( findList.find( obj->lastName ) == -1 )
+ // debug(" ? Not found %s", obj->lastName);
+ ++nListIt;
+ // if ( !nList.current() ) nList.first();
+ if (nListIt==nList.end()) nListIt=nList.begin();
+ }
+ } else {
+/*************************************************************************************************/
+ if ( obj->isTabGroup){
+ c->writeEntry( cname+":type", "TAB_GROUP");
+ if ( !obj->parent() ){
+ c->writeEntry( cname+":parent", "___null___");
+ c->writeEntry( cname+":geometry", QRect(obj->frameGeometry().topLeft(), obj->size()) );
+ c->writeEntry( cname+":visible", obj->isVisible());
+ c->writeEntry( cname+":dockBackTo", obj->formerBrotherDockWidget ? obj->formerBrotherDockWidget->name() : "");
+ c->writeEntry( cname+":dockBackToPos", obj->formerDockPos);
+ } else {
+ c->writeEntry( cname+":parent", "yes");
+ }
+ QStrList list;
+ for ( int i = 0; i < ((KDockTabGroup*)obj->widget)->count(); ++i )
+ list.append( ((KDockTabGroup*)obj->widget)->page( i )->name() );
+ c->writeEntry( cname+":tabNames", list );
+ c->writeEntry( cname+":curTab", ((KDockTabGroup*)obj->widget)->currentPageIndex() );
+
+ nameList.append( obj->name() );
+ findList.append( obj->name() ); // not really need !!!
+ //debug(" Save %s", nList.current());
+ nList.remove(nListIt);
+ nListIt=nList.begin();
+ } else {
+/*************************************************************************************************/
+ c->writeEntry( cname+":tabCaption", obj->tabPageLabel());
+ c->writeEntry( cname+":tabToolTip", obj->toolTipString());
+ if ( !obj->parent() ){
+ c->writeEntry( cname+":type", "NULL_DOCK");
+ c->writeEntry( cname+":geometry", QRect(obj->frameGeometry().topLeft(), obj->size()) );
+ c->writeEntry( cname+":visible", obj->isVisible());
+ c->writeEntry( cname+":dockBackTo", obj->formerBrotherDockWidget ? obj->formerBrotherDockWidget->name() : "");
+ c->writeEntry( cname+":dockBackToPos", obj->formerDockPos);
+ } else {
+ c->writeEntry( cname+":type", "DOCK");
+ }
+ nameList.append( cname.latin1() );
+ //debug(" Save %s", nList.current());
+ findList.append( obj->name() );
+ nList.remove(nListIt);
+ nListIt=nList.begin();
+ }
+ }
+ }
+ c->writeEntry( "NameList", nameList );
+
+ c->writeEntry( "Main:Geometry", QRect(main->frameGeometry().topLeft(), main->size()) );
+ c->writeEntry( "Main:visible", main->isVisible()); // curently nou use
+
+ if ( main->inherits("KDockMainWindow") ){
+ KDockMainWindow* dmain = (KDockMainWindow*)main;
+ // for KDockMainWindow->setView() in readConfig()
+ c->writeEntry( "Main:view", dmain->centralWidget() ? dmain->centralWidget()->name():"" );
+ c->writeEntry( "Main:dock", dmain->getMainDockWidget() ? dmain->getMainDockWidget()->name() :"" );
+ }
+
+ c->sync();
+ //debug("END Write Config");
+}
+#include <qmessagebox.h>
+void KDockManager::readConfig( KConfig* c, QString group )
+{
+ if ( !c ) c = KGlobal::config();
+ if ( group.isEmpty() ) group = "dock_setting_default";
+
+ c->setGroup( group );
+ QStrList nameList;
+ c->readListEntry( "NameList", nameList );
+ QString ver = c->readEntry( "Version", "0.0.1" );
+ nameList.first();
+ if ( !nameList.current() || ver != DOCK_CONFIG_VERSION ){
+ activate();
+ return;
+ }
+
+ autoCreateDock = new QObjectList();
+ autoCreateDock->setAutoDelete( true );
+
+ bool isMainVisible = main->isVisible();
+ // if (isMainVisible) // CCC
+ //QMessageBox::information(0,"","hallo");
+//COMMENTED4TESTING main->hide();
+
+ QObjectListIt it( *childDock );
+ KDockWidget * obj;
+
+ while ( (obj=(KDockWidget*)it.current()) ){
+ ++it;
+ if ( !obj->isGroup && !obj->isTabGroup )
+ {
+ if ( obj->parent() ) obj->undock(); else obj->hide();
+ }
+ }
+
+ // firstly, only the common dockwidgets,
+ // they must be restored before e.g. tabgroups are restored
+ nameList.first();
+ while ( nameList.current() ){
+ QString oname = nameList.current();
+ c->setGroup( group );
+ QString type = c->readEntry( oname + ":type" );
+ obj = 0L;
+
+ if ( type == "NULL_DOCK" || c->readEntry( oname + ":parent") == "___null___" ){
+ QRect r = c->readRectEntry( oname + ":geometry" );
+ obj = getDockWidgetFromName( oname );
+ obj->applyToWidget( 0L );
+ obj->setGeometry(r);
+
+ c->setGroup( group );
+ obj->setTabPageLabel(c->readEntry( oname + ":tabCaption" ));
+ obj->setToolTipString(c->readEntry( oname + ":tabToolTip" ));
+ if ( c->readBoolEntry( oname + ":visible" ) ){
+ obj->QWidget::show();
+ }
+ }
+
+ if ( type == "DOCK" ){
+ obj = getDockWidgetFromName( oname );
+ obj->setTabPageLabel(c->readEntry( oname + ":tabCaption" ));
+ obj->setToolTipString(c->readEntry( oname + ":tabToolTip" ));
+ }
+
+ if (obj && obj->d->isContainer) {
+ dynamic_cast<KDockContainer*>(obj->widget)->load(c,group);
+ removeFromAutoCreateList(obj);
+ }
+ if ( obj && obj->header){
+ obj->header->loadConfig( c );
+ }
+ nameList.next();
+ }
+
+ // secondly, after the common dockwidgets, restore the groups and tabgroups
+ nameList.first();
+ while ( nameList.current() ){
+ QString oname = nameList.current();
+ c->setGroup( group );
+ QString type = c->readEntry( oname + ":type" );
+ obj = 0L;
+
+ if ( type == "GROUP" ){
+ KDockWidget* first = getDockWidgetFromName( c->readEntry( oname + ":first_name" ) );
+ KDockWidget* last = getDockWidgetFromName( c->readEntry( oname + ":last_name" ) );
+ int sepPos = c->readNumEntry( oname + ":sepPos" );
+
+ Orientation p = (Orientation)c->readNumEntry( oname + ":orientation" );
+ if ( first && last ){
+ obj = first->manualDock( last, ( p == Vertical ) ? KDockWidget::DockLeft : KDockWidget::DockTop, sepPos );
+ if (obj){
+ obj->setName( oname.latin1() );
+ }
+ }
+ }
+
+ if ( type == "TAB_GROUP" ){
+ QStrList list;
+ KDockWidget* tabDockGroup = 0L;
+ c->readListEntry( oname+":tabNames", list );
+ KDockWidget* d1 = getDockWidgetFromName( list.first() );
+ list.next();
+ KDockWidget* d2 = getDockWidgetFromName( list.current() );
+ tabDockGroup = d2->manualDock( d1, KDockWidget::DockCenter );
+ if ( tabDockGroup ){
+ KDockTabGroup* tab = dynamic_cast<KDockTabGroup*>(tabDockGroup->widget);
+ list.next();
+ while ( list.current() && tabDockGroup ){
+ KDockWidget* tabDock = getDockWidgetFromName( list.current() );
+ tabDockGroup = tabDock->manualDock( d1, KDockWidget::DockCenter );
+ list.next();
+ }
+ if ( tabDockGroup ){
+ tabDockGroup->setName( oname.latin1() );
+ c->setGroup( group );
+ if (tab)
+ tab->showPage( tab->page( c->readNumEntry( oname+":curTab" ) ) );
+ }
+ }
+ obj = tabDockGroup;
+ }
+
+ if (obj && obj->d->isContainer) dynamic_cast<KDockContainer*>(obj->widget)->load(c,group);
+ if ( obj && obj->header){
+ obj->header->loadConfig( c );
+ }
+ nameList.next();
+ }
+
+ // thirdly, now that all ordinary dockwidgets are created,
+ // iterate them again and link the toplevel ones of them with their corresponding dockwidget for the dockback action
+ nameList.first();
+ while ( nameList.current() ){
+ QString oname = nameList.current();
+ c->setGroup( group );
+ QString type = c->readEntry( oname + ":type" );
+ obj = 0L;
+
+ if ( type == "NULL_DOCK" || c->readEntry( oname + ":parent") == "___null___" ){
+ obj = getDockWidgetFromName( oname );
+ c->setGroup( group );
+ QString name = c->readEntry( oname + ":dockBackTo" );
+ if (!name.isEmpty()) {
+ obj->setFormerBrotherDockWidget(getDockWidgetFromName( name ));
+ }
+ obj->formerDockPos = KDockWidget::DockPosition(c->readNumEntry( oname + ":dockBackToPos" ));
+ }
+
+ nameList.next();
+ }
+
+ if ( main->inherits("KDockMainWindow") ){
+ KDockMainWindow* dmain = (KDockMainWindow*)main;
+
+ c->setGroup( group );
+ QString mv = c->readEntry( "Main:view" );
+ if ( !mv.isEmpty() && getDockWidgetFromName( mv ) ){
+ KDockWidget* mvd = getDockWidgetFromName( mv );
+ mvd->applyToWidget( dmain );
+ mvd->show();
+ dmain->setView( mvd );
+ }
+ c->setGroup( group );
+ QString md = c->readEntry( "Main:dock" );
+ if ( !md.isEmpty() && getDockWidgetFromName( md ) ){
+ KDockWidget* mvd = getDockWidgetFromName( md );
+ dmain->setMainDockWidget( mvd );
+ }
+ } else {
+ c->setGroup( group );
+ QString mv = c->readEntry( "Main:view" );
+ if ( !mv.isEmpty() && getDockWidgetFromName( mv ) ){
+ KDockWidget* mvd = getDockWidgetFromName( mv );
+ mvd->applyToWidget( main );
+ mvd->show();
+ }
+
+ }
+
+ // delete all autocreate dock
+ if (d->m_readDockConfigMode == WrapExistingWidgetsOnly) {
+ finishReadDockConfig(); // remove empty dockwidgets
+ }
+
+ c->setGroup( group );
+
+ QRect mr = c->readRectEntry("Main:Geometry");
+
+ if (!main->inherits("KDockMainWindow"))
+ main->move(mr.topLeft());
+
+ main->resize(mr.size());
+
+ if ( isMainVisible ) main->show();
+}
+#endif
+
+
+void KDockManager::dumpDockWidgets() {
+ QObjectListIt it( *childDock );
+ KDockWidget * obj;
+ while ( (obj=(KDockWidget*)it.current()) ) {
+ ++it;
+ kdDebug(282)<<"KDockManager::dumpDockWidgets:"<<obj->name()<<endl;
+ }
+
+}
+
+KDockWidget* KDockManager::getDockWidgetFromName( const QString& dockName )
+{
+ QObjectListIt it( *childDock );
+ KDockWidget * obj;
+ while ( (obj=(KDockWidget*)it.current()) ) {
+ ++it;
+ if ( QString(obj->name()) == dockName ) return obj;
+ }
+
+ KDockWidget* autoCreate = 0L;
+ if ( autoCreateDock ){
+ kdDebug(282)<<"Autocreating dock: "<<dockName<<endl;
+ autoCreate = new KDockWidget( this, dockName.latin1(), QPixmap("") );
+ autoCreateDock->append( autoCreate );
+ }
+ return autoCreate;
+}
+void KDockManager::setSplitterOpaqueResize(bool b)
+{
+ d->splitterOpaqueResize = b;
+}
+
+bool KDockManager::splitterOpaqueResize() const
+{
+ return d->splitterOpaqueResize;
+}
+
+void KDockManager::setSplitterKeepSize(bool b)
+{
+ d->splitterKeepSize = b;
+}
+
+bool KDockManager::splitterKeepSize() const
+{
+ return d->splitterKeepSize;
+}
+
+void KDockManager::setSplitterHighResolution(bool b)
+{
+ d->splitterHighResolution = b;
+}
+
+bool KDockManager::splitterHighResolution() const
+{
+ return d->splitterHighResolution;
+}
+
+void KDockManager::slotMenuPopup()
+{
+ menu->clear();
+ menuData->clear();
+
+ QObjectListIt it( *childDock );
+ KDockWidget * obj;
+ int numerator = 0;
+ while ( (obj=(KDockWidget*)it.current()) ) {
+ ++it;
+ if ( obj->mayBeHide() )
+ {
+ menu->insertItem( obj->icon() ? *(obj->icon()) : QPixmap(), i18n("Hide %1").arg(obj->caption()), numerator++ );
+ menuData->append( new MenuDockData( obj, true ) );
+ }
+
+ if ( obj->mayBeShow() )
+ {
+ menu->insertItem( obj->icon() ? *(obj->icon()) : QPixmap(), i18n("Show %1").arg(obj->caption()), numerator++ );
+ menuData->append( new MenuDockData( obj, false ) );
+ }
+ }
+}
+
+void KDockManager::slotMenuActivated( int id )
+{
+ MenuDockData* data = menuData->at( id );
+ data->dock->changeHideShowState();
+}
+
+KDockWidget* KDockManager::findWidgetParentDock( QWidget* w ) const
+{
+ QObjectListIt it( *childDock );
+ KDockWidget * dock;
+ KDockWidget * found = 0L;
+
+ while ( (dock=(KDockWidget*)it.current()) ) {
+ ++it;
+ if ( dock->widget == w ){ found = dock; break; }
+ }
+ return found;
+}
+
+void KDockManager::drawDragRectangle()
+{
+#ifdef BORDERLESS_WINDOWS
+ return
+#endif
+ if (d->oldDragRect == d->dragRect)
+ return;
+
+ int i;
+ QRect oldAndNewDragRect[2];
+ oldAndNewDragRect[0] = d->oldDragRect;
+ oldAndNewDragRect[1] = d->dragRect;
+
+ // 2 calls, one for the old and one for the new drag rectangle
+ for (i = 0; i <= 1; i++) {
+ if (oldAndNewDragRect[i].isEmpty())
+ continue;
+
+ KDockWidget* pDockWdgAtRect = (KDockWidget*) QApplication::widgetAt( oldAndNewDragRect[i].topLeft(), true );
+ if (!pDockWdgAtRect)
+ continue;
+
+ bool isOverMainWdg = false;
+ bool unclipped;
+ KDockMainWindow* pMain = 0L;
+ KDockWidget* pTLDockWdg = 0L;
+ QWidget* topWdg;
+ if (pDockWdgAtRect->topLevelWidget() == main) {
+ isOverMainWdg = true;
+ topWdg = pMain = (KDockMainWindow*) main;
+ unclipped = pMain->testWFlags( WPaintUnclipped );
+ pMain->setWFlags( WPaintUnclipped );
+ }
+ else {
+ topWdg = pTLDockWdg = (KDockWidget*) pDockWdgAtRect->topLevelWidget();
+ unclipped = pTLDockWdg->testWFlags( WPaintUnclipped );
+ pTLDockWdg->setWFlags( WPaintUnclipped );
+ }
+
+ // draw the rectangle unclipped over the main dock window
+ QPainter p;
+ p.begin( topWdg );
+ if ( !unclipped ) {
+ if (isOverMainWdg)
+ pMain->clearWFlags(WPaintUnclipped);
+ else
+ pTLDockWdg->clearWFlags(WPaintUnclipped);
+ }
+ // draw the rectangle
+ p.setRasterOp(Qt::NotXorROP);
+ QRect r = oldAndNewDragRect[i];
+ r.moveTopLeft( r.topLeft() - topWdg->mapToGlobal(QPoint(0,0)) );
+ p.drawRect(r.x(), r.y(), r.width(), r.height());
+ p.end();
+ }
+
+ // memorize the current rectangle for later removing
+ d->oldDragRect = d->dragRect;
+}
+
+void KDockManager::setSpecialLeftDockContainer(KDockWidget* container) {
+ d->leftContainer=container;
+}
+
+void KDockManager::setSpecialTopDockContainer(KDockWidget* container) {
+ d->topContainer=container;
+}
+
+void KDockManager::setSpecialRightDockContainer(KDockWidget* container) {
+ d->rightContainer=container;
+
+}
+
+void KDockManager::setSpecialBottomDockContainer(KDockWidget* container) {
+ d->bottomContainer=container;
+}
+
+
+KDockArea::KDockArea( QWidget* parent, const char *name)
+:QWidget( parent, name)
+{
+ QString new_name = QString(name) + QString("_DockManager");
+ dockManager = new KDockManager( this, new_name.latin1() );
+ mainDockWidget = 0L;
+}
+
+KDockArea::~KDockArea()
+{
+ delete dockManager;
+}
+
+KDockWidget* KDockArea::createDockWidget( const QString& name, const QPixmap &pixmap, QWidget* parent, const QString& strCaption, const QString& strTabPageLabel)
+{
+ return new KDockWidget( dockManager, name.latin1(), pixmap, parent, strCaption, strTabPageLabel );
+}
+
+void KDockArea::makeDockVisible( KDockWidget* dock )
+{
+ if ( dock )
+ dock->makeDockVisible();
+}
+
+void KDockArea::makeDockInvisible( KDockWidget* dock )
+{
+ if ( dock )
+ dock->undock();
+}
+
+void KDockArea::makeWidgetDockVisible( QWidget* widget )
+{
+ makeDockVisible( dockManager->findWidgetParentDock(widget) );
+}
+
+void KDockArea::writeDockConfig(QDomElement &base)
+{
+ dockManager->writeConfig(base);
+}
+
+void KDockArea::readDockConfig(QDomElement &base)
+{
+ dockManager->readConfig(base);
+}
+
+void KDockArea::slotDockWidgetUndocked()
+{
+ QObject* pSender = (QObject*) sender();
+ if (!pSender->inherits("KDockWidget")) return;
+ KDockWidget* pDW = (KDockWidget*) pSender;
+ emit dockWidgetHasUndocked( pDW);
+}
+
+void KDockArea::resizeEvent(QResizeEvent *rsize)
+{
+ QWidget::resizeEvent(rsize);
+ if (children()){
+#ifndef NO_KDE2
+// kdDebug(282)<<"KDockArea::resize"<<endl;
+#endif
+ QObjectList *list=queryList("QWidget",0,false);
+
+ QObjectListIt it( *list ); // iterate over the buttons
+ QObject *obj;
+
+ while ( (obj = it.current()) != 0 ) {
+ // for each found object...
+ ((QWidget*)obj)->setGeometry(QRect(QPoint(0,0),size()));
+ break;
+ }
+ delete list;
+#if 0
+ KDockSplitter *split;
+// for (unsigned int i=0;i<children()->count();i++)
+ {
+// QPtrList<QObject> list(children());
+// QObject *obj=((QPtrList<QObject*>)children())->at(i);
+ QObject *obj=children()->getFirst();
+ if (split = dynamic_cast<KDockSplitter*>(obj))
+ {
+ split->setGeometry( QRect(QPoint(0,0), size() ));
+// break;
+ }
+ }
+#endif
+ }
+}
+
+#ifndef NO_KDE2
+void KDockArea::writeDockConfig( KConfig* c, QString group )
+{
+ dockManager->writeConfig( c, group );
+}
+
+void KDockArea::readDockConfig( KConfig* c, QString group )
+{
+ dockManager->readConfig( c, group );
+}
+
+void KDockArea::setMainDockWidget( KDockWidget* mdw )
+{
+ if ( mainDockWidget == mdw ) return;
+ mainDockWidget = mdw;
+ mdw->applyToWidget(this);
+}
+#endif
+
+
+
+// KDOCKCONTAINER - AN ABSTRACTION OF THE KDOCKTABWIDGET
+KDockContainer::KDockContainer(){m_overlapMode=false; m_childrenListBegin=0; m_childrenListEnd=0;}
+KDockContainer::~KDockContainer(){
+
+ if (m_childrenListBegin)
+ {
+ struct ListItem *tmp=m_childrenListBegin;
+ while (tmp)
+ {
+ struct ListItem *tmp2=tmp->next;
+ free(tmp->data);
+ delete tmp;
+ tmp=tmp2;
+ }
+ m_childrenListBegin=0;
+ m_childrenListEnd=0;
+ }
+
+}
+
+void KDockContainer::activateOverlapMode(int nonOverlapSize) {
+ m_nonOverlapSize=nonOverlapSize;
+ m_overlapMode=true;
+ if (parentDockWidget() && parentDockWidget()->parent()) {
+ kdDebug(282)<<"KDockContainer::activateOverlapMode: recalculating sizes"<<endl;
+ KDockSplitter *sp= static_cast<KDockSplitter*>(parentDockWidget()->
+ parent()->qt_cast("KDockSplitter"));
+ if (sp)
+ sp->resizeEvent(0);
+ }
+}
+
+void KDockContainer::deactivateOverlapMode() {
+ if (!m_overlapMode) return;
+ m_overlapMode=false;
+ if (parentDockWidget() && parentDockWidget()->parent()) {
+ kdDebug(282)<<"KDockContainer::deactivateOverlapMode: recalculating sizes"<<endl;
+ KDockSplitter *sp= static_cast<KDockSplitter*>(parentDockWidget()->
+ parent()->qt_cast("KDockSplitter"));
+ if (sp)
+ sp->resizeEvent(0);
+ }
+}
+
+bool KDockContainer::isOverlapMode() {
+ return m_overlapMode;
+}
+
+
+bool KDockContainer::dockDragEnter(KDockWidget*, QMouseEvent *) { return false;}
+bool KDockContainer::dockDragMove(KDockWidget*, QMouseEvent *) { return false;}
+bool KDockContainer::dockDragLeave(KDockWidget*, QMouseEvent *) { return false;}
+
+
+KDockWidget *KDockContainer::parentDockWidget(){return 0;}
+
+QStringList KDockContainer::containedWidgets() const {
+ QStringList tmp;
+ for (struct ListItem *it=m_childrenListBegin;it;it=it->next) {
+ tmp<<QString(it->data);
+ }
+
+ return tmp;
+}
+
+void KDockContainer::showWidget(KDockWidget *) {
+}
+
+void KDockContainer::insertWidget (KDockWidget *dw, QPixmap, const QString &, int &)
+ {
+ struct ListItem *it=new struct ListItem;
+ it->data=strdup(dw->name());
+ it->next=0;
+
+ if (m_childrenListEnd)
+ {
+ m_childrenListEnd->next=it;
+ it->prev=m_childrenListEnd;
+ m_childrenListEnd=it;
+ }
+ else
+ {
+ it->prev=0;
+ m_childrenListEnd=it;
+ m_childrenListBegin=it;
+ }
+ }
+void KDockContainer::removeWidget (KDockWidget *dw){
+ for (struct ListItem *tmp=m_childrenListBegin;tmp;tmp=tmp->next)
+ {
+ if (!strcmp(tmp->data,dw->name()))
+ {
+ free(tmp->data);
+ if (tmp->next) tmp->next->prev=tmp->prev;
+ if (tmp->prev) tmp->prev->next=tmp->next;
+ if (tmp==m_childrenListBegin) m_childrenListBegin=tmp->next;
+ if (tmp==m_childrenListEnd) m_childrenListEnd=tmp->prev;
+ delete tmp;
+ break;
+ }
+ }
+}
+
+//m_children.remove(dw->name());}
+void KDockContainer::undockWidget (KDockWidget *){;}
+void KDockContainer::setToolTip(KDockWidget *, QString &){;}
+void KDockContainer::setPixmap(KDockWidget*,const QPixmap&){;}
+void KDockContainer::load (KConfig*, const QString&){;}
+void KDockContainer::save (KConfig*, const QString&){;}
+void KDockContainer::load (QDomElement&){;}
+void KDockContainer::save (QDomElement&){;}
+void KDockContainer::prepareSave(QStringList &names)
+{
+
+ for (struct ListItem *tmp=m_childrenListBegin;tmp; tmp=tmp->next)
+ names.remove(tmp->data);
+// for (uint i=0;i<m_children.count();i++)
+// {
+// names.remove(m_children.at(i));
+// }
+}
+
+
+QWidget *KDockTabGroup::transientTo() {
+ QWidget *tT=0;
+ for (int i=0;i<count();i++) {
+ KDockWidget *dw=static_cast<KDockWidget*>(page(i)->qt_cast("KDockWidget"));
+ QWidget *tmp;
+ if ((tmp=dw->transientTo())) {
+ if (!tT) tT=tmp;
+ else {
+ if (tT!=tmp) {
+ kdDebug(282)<<"KDockTabGroup::transientTo: widget mismatch"<<endl;
+ return 0;
+ }
+ }
+ }
+ }
+
+ kdDebug(282)<<"KDockTabGroup::transientTo: "<<(tT?"YES":"NO")<<endl;
+
+ return tT;
+}
+
+void KDockWidgetAbstractHeader::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void KDockWidgetAbstractHeaderDrag::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void KDockWidgetHeaderDrag::virtual_hook( int id, void* data )
+{ KDockWidgetAbstractHeaderDrag::virtual_hook( id, data ); }
+
+void KDockWidgetHeader::virtual_hook( int id, void* data )
+{ KDockWidgetAbstractHeader::virtual_hook( id, data ); }
+
+void KDockTabGroup::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void KDockWidget::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void KDockManager::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void KDockMainWindow::virtual_hook( int id, void* data )
+{ KMainWindow::virtual_hook( id, data ); }
+
+void KDockArea::virtual_hook( int, void* )
+{ /*KMainWindow::virtual_hook( id, data );*/ }
+
+
+#ifndef NO_INCLUDE_MOCFILES // for Qt-only projects, because tmake doesn't take this name
+#include "kdockwidget.moc"
+#endif
diff --git a/kdeui/kdockwidget.h b/kdeui/kdockwidget.h
new file mode 100644
index 000000000..b43d9b88a
--- /dev/null
+++ b/kdeui/kdockwidget.h
@@ -0,0 +1,1539 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Max Judin <novaprint@mtu-net.ru>
+ Copyright (C) 2000 Falk Brettschneider <falk@kdevelop.org>
+ Copyright (C) 2002,2003 Joseph Wenninger <jowenn@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+/*
+ activities:
+ -----------
+ 05/2001 - : useful patches, bugfixes by Christoph Cullmann <crossfire@babylon2k.de>,
+ Joseph Wenninger <jowenn@bigfoot.com> and Falk Brettschneider
+ 03/2001 - 05/2001 : maintained and enhanced by Falk Brettschneider <falk@kdevelop.org>
+ 03/2000 : class documentation added by Falk Brettschneider <gigafalk@yahoo.com>
+ 10/1999 - 03/2000 : programmed by Max Judin <novaprint@mtu-net.ru>
+
+ C++ classes in this file:
+ -------------------------
+ - KDockWidgetAbstractHeader - minor helper class
+ - KDockWidgetAbstractHeaderDrag - minor helper class
+ - KDockWidgetHeaderDrag - drag panel in a dockwidget title bar
+ - KDockWidgetHeader - dockwidget title bar containing the drag panel
+ - KDockTabGroup - minor helper class
+ - KDockWidget - IMPORTANT CLASS: the one and only dockwidget class
+ - KDockManager - helper class
+ - KDockMainWindow - IMPORTANT CLASS: a special KMainWindow that can have dockwidgets
+ - KDockArea - like KDockMainWindow but inherits just QWidget
+
+ IMPORTANT Note: This file compiles also in Qt-only mode by using the NO_KDE2 precompiler definition!
+*/
+
+
+#ifndef KDOCKWIDGET_H
+#define KDOCKWIDGET_H
+
+#define _KDOCKWIDGET_2_2_
+
+#include <qpoint.h>
+#include <qptrlist.h>
+#include <qframe.h>
+#include <qdom.h>
+#include <qtabwidget.h>
+
+#ifndef NO_KDE2
+#include <kmainwindow.h>
+#include <netwm_def.h>
+#else
+
+#include <qmainwindow.h>
+#include "exportdockclass.h"
+#include "dummykmainwindow.h"
+#endif
+
+class KDockSplitter;
+class KDockManager;
+class KDockMoveManager;
+class KDockWidget;
+class KDockButton_Private;
+class KDockWidgetPrivate;
+class KDockWidgetHeaderPrivate;
+class KDockArea;
+
+class QObjectList;
+class QPopupMenu;
+class QVBoxLayout;
+class QHBoxLayout;
+class QPixmap;
+
+#ifndef NO_KDE2
+class KToolBar;
+class KConfig;
+#else
+class QToolBar;
+#endif
+
+class KDockContainer;
+
+namespace KMDI
+{
+ class MainWindow;
+}
+
+/**
+ * An abstract base clase for all dockwidget headers (and member of the dockwidget class set).
+ * See the class description of KDockWidgetHeader!
+ * More or less a minor helper class for the dockwidget class set.
+ *
+ * @author Max Judin (documentation: Falk Brettschneider).
+ */
+class KDEUI_EXPORT KDockWidgetAbstractHeader : public QFrame
+{
+ Q_OBJECT
+public:
+
+ /**
+ * Constructs this.
+ *
+ * @param parent the parent widget (usually a dockwidget)
+ * @param name the object instance name
+ */
+ KDockWidgetAbstractHeader( KDockWidget* parent, const char* name = 0L );
+
+ /**
+ * Destructs this.
+ */
+ virtual ~KDockWidgetAbstractHeader(){}
+
+ /**
+ * Provides things concerning to switching to toplevel mode. Must be overridden by an inheriting class.
+ */
+ virtual void setTopLevel( bool ){}
+
+#ifndef NO_KDE2
+ /**
+ * Provides saving the current configuration. Must be overridden by an inheriting class.
+ */
+ virtual void saveConfig( KConfig* ){}
+
+ /**
+ * Provides loading the current configuration. Must be overridden by an inheriting class
+ */
+ virtual void loadConfig( KConfig* ){}
+#endif
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KDockWidgetAbstractHeaderPrivate;
+ KDockWidgetAbstractHeaderPrivate *d;
+};
+
+/**
+ * An abstract class for all dockwidget drag-panels of a dockwidgets (and member of the dockwidget class set).
+ * See the class description of KDockWidgetHeaderDrag!
+ * More or less a minor helper class for the dockwidget class set.
+ *
+ * @author Max Judin (documentation: Falk Brettschneider).
+ */
+class KDEUI_EXPORT KDockWidgetAbstractHeaderDrag : public QFrame
+{
+ Q_OBJECT
+public:
+
+ /**
+ * Constructs this.
+ *
+ * @param parent the parent widget (usually a dockwidget header)
+ * @param dock the dockwidget where it belongs to
+ * @param name the object instance name
+ */
+ KDockWidgetAbstractHeaderDrag( KDockWidgetAbstractHeader* parent,
+ KDockWidget* dock, const char* name = 0L );
+
+ /**
+ * Destructs this.
+ */
+ virtual ~KDockWidgetAbstractHeaderDrag(){}
+
+ /**
+ * @return the dockwidget where this belongs to
+ */
+ KDockWidget* dockWidget() const { return dw; }
+
+private:
+ /**
+ * the dockwidget where this belongs to
+ */
+ KDockWidget* dw;
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KDockWidgetAbstractHeaderDragPrivate;
+ KDockWidgetAbstractHeaderDragPrivate *d;
+};
+
+/**
+ * This special widget is the panel one can grip with the mouses (and member of the dockwidget class set).
+ * The widget for dragging, so to speak.
+ * Usually it is located in the KDockWidgetHeader.
+ * More or less a minor helper class for the dockwidget class set.
+ *
+ * @author Max Judin (documentation: Falk Brettschneider).
+ */
+class KDEUI_EXPORT KDockWidgetHeaderDrag : public KDockWidgetAbstractHeaderDrag
+{
+ Q_OBJECT
+public:
+
+ /**
+ * Constructs this.
+ *
+ * @param parent the parent widget (usually a dockwidget header)
+ * @param dock the dockwidget where it belongs to
+ * @param name the object instance name
+ */
+ KDockWidgetHeaderDrag( KDockWidgetAbstractHeader* parent, KDockWidget* dock,
+ const char* name = 0L );
+
+ /**
+ * Destructs this.
+ */
+ virtual ~KDockWidgetHeaderDrag(){}
+
+protected:
+
+ /**
+ * Draws the drag panel (a double line)
+ */
+ virtual void paintEvent( QPaintEvent* );
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KDockWidgetHeaderDragPrivate;
+ KDockWidgetHeaderDragPrivate *d;
+};
+
+/**
+ * The header (additional bar) for a KDockWidget s (and member of the dockwidget class set).
+ * It have got the buttons located there. And it is for recording and reading the button states.
+ * More or less a minor helper class for the dockwidget class set.
+ *
+ * @author Max Judin (documentation: Falk Brettschneider).
+ */
+class KDEUI_EXPORT KDockWidgetHeader : public KDockWidgetAbstractHeader
+{
+ Q_OBJECT
+public:
+
+ /**
+ * Constructs this.
+ *
+ * @param parent the parent widget (usually a dockwidget)
+ * @param name the object instance name
+ */
+ KDockWidgetHeader( KDockWidget* parent, const char* name = 0L );
+
+ /**
+ * Destructs this.
+ */
+ virtual ~KDockWidgetHeader(){}
+
+ /**
+ * Hides the close button and stay button when switching to toplevel or vice versa shows them.
+ *
+ * @param t toplevel or not
+ */
+ virtual void setTopLevel( bool t);
+
+ /**
+ * Sets the drag panel of this header.
+ *
+ * @param nd A pointer to the new drag panel
+ */
+ void setDragPanel( KDockWidgetHeaderDrag* nd );
+
+ /**
+ * Get the drag panel of this header.
+ *
+ * @since 3.4
+ */
+ KDockWidgetHeaderDrag *dragPanel();
+
+ bool dragEnabled() const;
+ void setDragEnabled(bool b);
+ /// @since 3.1
+ void showUndockButton(bool show);
+
+ /// @since 3.2
+ void forceCloseButtonHidden(bool enable=true);
+#ifndef NO_KDE2
+ /**
+ * Saves the current button state to a KDE config container object.
+ *
+ * @param c the configuration safe
+ */
+ virtual void saveConfig( KConfig* c);
+
+ /**
+ * Loads the current button state from a KDE config container object.
+ *
+ * @param c the configuration safe
+ */
+ virtual void loadConfig( KConfig* c);
+#endif
+
+ /*@since 3.2
+ * add an arbitrary button to the dockwidget header
+ * NOT PART OF THE PUBLIC API (you don't have access the class defintion anyways, without special
+ * header file copying. (don't do it))
+ */
+ void addButton(KDockButton_Private*);
+
+ /*@since 3.2
+ * remove an arbtrary button from the dockwidget header
+ * NOT PART OF THE PUBLIC API (you don't have access the class defintion anyways, without special
+ * header file copying. (don't do it))
+ */
+ void removeButton(KDockButton_Private*);
+
+
+
+protected slots:
+ /**
+ * Sets dragging the dockwidget off when the stay button is pressed down and vice versa.
+ */
+ void slotStayClicked();
+
+protected:
+
+ /**
+ * A layout manager for placing the embedded buttons (close and stay)
+ */
+ QHBoxLayout* layout;
+
+ /**
+ * a little button for closing (undocking and hiding) the dockwidget
+ */
+ KDockButton_Private* closeButton;
+
+ /**
+ * a little button for enabling/disabling dragging the dockwidget with the mouse
+ */
+ KDockButton_Private* stayButton;
+
+ /**
+ * a little button for dock back the dockwidget to it's previous dockwidget
+ */
+ KDockButton_Private* dockbackButton;
+
+ /**
+ * the drag panel (double line)
+ */
+ KDockWidgetHeaderDrag* drag;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KDockWidgetHeaderPrivate *d;
+};
+
+/**
+ * It just hides the special implementation of a dockwidget tab groups (and is member of the dockwidget class set).
+ * An abstraction what it is currently.
+ * In general it is like QTabWidget but is more useful for the dockwidget class set.
+ * More or less a minor helper class for the dockwidget class set.
+ *
+ * @author Max Judin (documentation: Falk Brettschneider).
+ */
+class KDEUI_EXPORT KDockTabGroup : public QTabWidget
+{
+ Q_OBJECT
+public:
+ /**
+ * Constructs this. It just calls the method of the base class.
+ */
+ KDockTabGroup( QWidget *parent = 0, const char *name = 0 )
+ :QTabWidget( parent, name ){}
+
+ /**
+ * Destructs a KDockTabGroup.
+ */
+ virtual ~KDockTabGroup(){}
+
+ QWidget *transientTo();
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KDockTabGroupPrivate;
+ KDockTabGroupPrivate *d;
+};
+
+
+/**
+ * Floatable widget that can be dragged around with the mouse and
+ * encapsulate the actual widgets (and member of the dockwidget class
+ * set).
+ *
+ * You just grip the double-lined panel, tear it off its parent
+ * widget, drag it somewhere and let it loose. Depending on the
+ * position where you leave it, the dockwidget becomes a toplevel
+ * window on the desktop (floating mode) or docks to a new widget
+ * (dock mode). Note: A KDockWidget can only be docked to a
+ * KDockWidget.
+ *
+ * If you want to use this kind of widget, your main application
+ * window has to be a KDockMainWindow. That is because it has
+ * got several additional dock management features, for instance a
+ * KDockManager that has an overview over all dockwidgets and and
+ * a dockmovemanager (internal class) that handles the dock process.
+ *
+ * Usually you create an KDockWidget that covers the actual widget in this way:
+ * \code
+ * ...
+ * KDockMainWindow* mainWidget;
+ * ...
+ * KDockWidget* dock = 0L;
+ * dock = mainWidget->createDockWidget( "Any window caption", nicePixmap, 0L, i18n("window caption")); // 0L==no parent
+ * QWidget* actualWidget = new QWidget( dock);
+ * dock->setWidget( actualWidget); // embed it
+ * dock->setToolTipString(i18n("That's me")); // available when appearing as tab page
+ * ...
+ * \endcode
+ *
+ * See KDockMainWindow how a dockwidget is docked in.
+ *
+ *
+ * @author Max Judin (documentation: Falk Brettschneider).
+ */
+class KDEUI_EXPORT KDockWidget: public QWidget
+{
+ Q_OBJECT
+friend class KDockManager;
+friend class KDockSplitter;
+friend class KDockMainWindow;
+friend class KDockArea;
+
+public:
+ /**
+ * Construct a dockwidget.
+ *
+ * Initially, docking to another and docking to this is allowed for
+ * every @p DockPosition. It is supposed to be no (tab) group. It will
+ * taken under control of its dockmanager.
+ *
+ * @param dockManager The responsible manager (dock helper)
+ * @param name Object instance name
+ * @param pixmap An icon (for instance shown when docked centered)
+ * @param parent Parent widget
+ * @param strCaption Title of the dockwidget window (shown when toplevel)
+ * @param strTabPageLabel The title of the tab page (shown when in tab page mode), if it is "", only the icon will be shown, if it is 0L, the label is set to strCaption
+ * @param f Qt::WidgetFlags widget flags
+ */
+ KDockWidget( KDockManager* dockManager, const char* name,
+ const QPixmap &pixmap, QWidget* parent = 0L, const QString& strCaption = QString::null,
+ const QString& strTabPageLabel = QString::fromLatin1( " " ), WFlags f = 0);
+
+ /**
+ * Destructs a dockwidget.
+ */
+ virtual ~KDockWidget();
+
+ /**
+ * The possible positions where a dockwidget can dock to another dockwidget
+ */
+ enum DockPosition
+ {
+ DockNone = 0,
+ DockTop = 0x0001,
+ DockLeft = 0x0002,
+ DockRight = 0x0004,
+ DockBottom = 0x0008,
+ DockCenter = 0x0010,
+ DockDesktop= 0x0020,
+ DockToSpecialSites=0x0040, ///< @since 3.1
+ DockCorner = DockTop | DockLeft | DockRight | DockBottom,
+ DockFullSite = DockCorner | DockCenter,
+ DockFullDocking = DockFullSite | DockDesktop
+ };
+
+ /**
+ * This is a key method of this class! Use it to dock dockwidgets to
+ * another dockwidget at the right position within its
+ * KDockMainWindow or a toplevel dockwidget.
+ *
+ *
+ * If the target is null, it will become a toplevel dockwidget at position pos;
+ * Note: Docking to another dockwidget means exactly:
+ * A new parent dockwidget will be created, that replaces the target dockwidget and contains another single helper widget (tab widget or panner)
+ * which contains both dockwidgets, this and the target dockwidget. So consider parent<->child relationships change completely during such actions.
+ *
+ * @param target The dockwidget to dock to
+ * @param dockPos One of the DockPositions this is going to dock to
+ * @param spliPos The split relation (in percent, or percent*100 in high resolution) between both dockwidgets, target and this
+ * @param pos The dock position, mainly of interest for docking to the desktop (as toplevel dockwidget)
+ * @param check Only for internal use;
+ * @param tabIndex The position index of the tab widget (when in tab page mode), -1 (default) means append
+ * @return result The group dockwidget that replaces the target dockwidget and will be grandparent of target and @p this.
+ *
+ * @note Since KDE 3.5 the splitter position @p spliPos is always a value between [0..100]. If
+ * the value is > 100, it will be treated like the old code and normalized to a value between
+ * 0 and 100. Example: If the value was 4000, it will be fixed to 40. In short: The old and
+ * the new behavior both work, so it is compatible with older KDE-versions.
+ */
+ KDockWidget* manualDock( KDockWidget* target, DockPosition dockPos, int spliPos = 50, QPoint pos = QPoint(0,0), bool check = false, int tabIndex = -1);
+
+ /**
+ * Specify where it is either possible or impossible for this to dock to another dockwidget.
+ *
+ * @param pos An OR'ed set of @p DockPositions
+ */
+ void setEnableDocking( int pos );
+
+ /**
+ * @return Where it is either possible or impossible for this to dock to another dockwidget (an OR'ed set of DockPositions).
+ */
+ int enableDocking() const { return eDocking; }
+
+ /**
+ * Specify where it is either possible or impossible for another dockwidget to dock to this.
+ *
+ * @param pos An OR'ed set of @p DockPositions
+ */
+ void setDockSite( int pos ){ sDocking = pos;}
+
+ /**
+ * @return There it is either possible or impossible for another dockwidget to dock to this (an OR'ed set of @p DockPositions).
+ */
+ int dockSite() const { return sDocking; }
+
+ /**
+ * Sets the embedded widget.
+ *
+ * A QLayout takes care about proper resizing, automatically.
+ *
+ * @param w The pointer to the dockwidget's child widget.
+ */
+ void setWidget( QWidget* w);
+
+ /**
+ * Get the embedded widget.
+ *
+ * @return The pointer to the dockwidget's child widget, 0L if there's no such child.
+ */
+ QWidget* getWidget() const { return widget; }
+
+ /**
+ * Sets the header of this dockwidget.
+ *
+ * A QLayout takes care about proper resizing, automatically.
+ * The header contains the drag panel, the close button and the stay button.
+ *
+ * @param ah A base class pointer to the dockwidget header
+ */
+ void setHeader( KDockWidgetAbstractHeader* ah);
+
+ /**@since 3.2
+ * get the pointer to the header widget
+ */
+ KDockWidgetAbstractHeader *getHeader();
+
+ /**
+ * Normally it simply shows the dockwidget.
+ *
+ * But additionally, if it is docked to a tab widget (@p DockCenter), it is set as the active (visible) tab page.
+ */
+ void makeDockVisible();
+
+ /**
+ * @return If it may be possible to hide this.
+ *
+ * There are reasons that it's impossible:
+ * @li It is a (tab) group.
+ * @li It is already invisible ;-)
+ * @li The parent of this is the KDockMainWindow.
+ * @li It isn't able to dock to another widget.
+ */
+ bool mayBeHide() const;
+
+ /**
+ * @return If it may be possible to show this.
+ * There are reasons that it's impossible:
+ * @li It is a (tab) group.
+ * @li It is already visible ;-)
+ * @li The parent of this is the @p KDockMainWindow.
+ */
+ bool mayBeShow() const;
+
+ /**
+ * @return The dockmanager that is responsible for this.
+ */
+ KDockManager* dockManager() const { return manager; }
+
+ /**
+ * Stores a string for a tooltip.
+ *
+ * That tooltip string has only a meaning when this dockwidget is shown as tab page.
+ * In this case the tooltip is shown when one holds the mouse cursor on the tab page header.
+ * Such tooltip will for instance be useful, if you use only icons there.
+ * Note: Setting an empty string switches the tooltip off.
+ *
+ * @param ttStr A string for the tooltip on the tab.
+ */
+ void setToolTipString(const QString& ttStr) { toolTipStr = ttStr; }
+
+ /**
+ * @return The tooltip string being shown on the appropriate tab page header when in dock-centered mode.
+ */
+ const QString& toolTipString() const { return toolTipStr; }
+
+ /**
+ * @return result @p true, if a dockback is possible, otherwise @p false.
+ */
+ bool isDockBackPossible() const;
+
+ /**
+ * Sets a string that is used for the label of the tab page when in tab page mode
+ * @param label The new tab page label.
+ */
+ void setTabPageLabel( const QString& label) { tabPageTitle = label; }
+
+ /**
+ * @return A string that is used for the label of the tab page when in tab page mode.
+ */
+ const QString& tabPageLabel() const { return tabPageTitle; }
+
+ /**
+ * Catches and processes some QWidget events that are interesting for dockwidgets.
+ */
+ virtual bool event( QEvent * );
+
+ /**
+ * Add dockwidget management actions to QWidget::show.
+ */
+ virtual void show();
+ /**
+ * @return the parent widget of this if it inherits class KDockTabGroup
+ */
+ KDockTabGroup* parentDockTabGroup() const;
+
+ /// @since 3.1
+ QWidget *parentDockContainer() const;
+
+#ifndef NO_KDE2
+
+ /**
+ * Sets the type of the dock window
+ *
+ * @param windowType is type of dock window
+ */
+ void setDockWindowType (NET::WindowType windowType);
+
+#endif
+
+ void setDockWindowTransient (QWidget *parent, bool transientEnabled);
+
+ /**
+ * Returns the widget this dockwidget is set transient to, otherwise 0
+ * @since 3.2
+ */
+ QWidget *transientTo();
+
+ /**
+ * Lookup the nearest dockwidget docked left/right/top/bottom to this one or return 0
+ *
+ * @param pos is the position the wanted widget is docked to this one
+ * @since 3.1
+ */
+ KDockWidget *findNearestDockWidget(DockPosition pos);
+
+ /**
+ * Allows changing the pixmap which is used for the caption or dock tabs
+ *
+ * @param pixmap is the pixmap to set
+ * @since 3.2
+ */
+ void setPixmap(const QPixmap& pixmap=QPixmap());
+
+ /**
+ * Returns the dockwidget's associated caption/dock tab pixmap
+ *
+ * @since 3.2
+ */
+ const QPixmap& pixmap() const;
+
+ /**
+ * @return the current dock position.
+ * @since 3.3
+ */
+ KDockWidget::DockPosition currentDockPosition() const;
+
+public slots:
+ /**
+ * subject to changes. It doesn't completely work yet without small hacks from within the calling application (Perhaps
+ * KDE 3.1.x oder 3.2
+ * width is in pixel. It only affects a widget, which is placed directly into a horizontal KDockSplitter
+ * @since 3.1
+ **/
+ void setForcedFixedWidth(int);
+ /**
+ * subject to changes. It doesn't completely work yet without small hacks from within the calling application (Perhaps
+ * KDE 3.1.x oder 3.2
+ * height is in pixel. It only affects a widget, which is placed directly into a vertical KDockSplitter
+ * @since 3.1
+ **/
+ void setForcedFixedHeight(int);
+ /// @since 3.1
+ void restoreFromForcedFixedSize();
+
+ /// @since 3.1
+ int forcedFixedWidth();
+ /// @since 3.1
+ int forcedFixedHeight();
+
+ /**
+ * Docks a dockwidget back to the dockwidget that was the neighbor
+ widget before the current dock position.
+ */
+ void dockBack();
+
+ /**
+ * Toggles the visibility state of the dockwidget if it is able to be shown or to be hidden.
+ */
+ void changeHideShowState();
+
+ /**
+ * Undocks this. It means it becomes a toplevel widget framed by the system window manager.
+ * A small panel at the top of this undocked widget gives the possibility to drag it into
+ * another dockwidget by mouse (docking).
+ */
+ void undock();
+
+ /**
+ * Docks the widget to the desktop (as a toplevel widget)
+ * @since 3.1
+ */
+ void toDesktop( );
+
+protected:
+ friend class KMdiMainFrm;
+ friend class KMDI::MainWindow;
+ /**
+ * Checks some conditions and shows or hides the dockwidget header (drag panel).
+ * The header is hidden if:
+ * @li the parent widget is the KDockMainWindow
+ * @li this is a (tab) group dockwidget
+ * @li it is not able to dock to another dockwidget
+ */
+ void updateHeader();
+
+ /// @since 3.1
+ void setLatestKDockContainer(QWidget *);
+ /// @since 3.1
+ QWidget *latestKDockContainer();
+
+ /// @since 3.2
+ void setFormerBrotherDockWidget(KDockWidget *);
+
+signals:
+ /**
+ *@since 3.2
+ *is emitted after the setWidget method has finished
+ */
+ void widgetSet(QWidget*);
+
+ /**
+ * Emitted when another dock widget is docking to this.
+ *
+ * @param dw the dockwidget that is docking to this
+ * @param dp the DockPosition where it wants to dock to
+ */
+ void docking( KDockWidget* dw, KDockWidget::DockPosition dp);
+
+ /**
+ * Signals that the dock default position is set.
+ */
+ void setDockDefaultPos();
+
+ /**
+ * Emitted when the close button of the panel ( KDockWidgetHeader) has been clicked.
+ */
+ void headerCloseButtonClicked();
+
+ /**
+ * Emitted when the dockback button of the panel ( KDockWidgetHeader) has been clicked.
+ */
+ void headerDockbackButtonClicked();
+
+ /**
+ * Emitted when the widget processes a close event.
+ */
+ void iMBeingClosed();
+ /**
+ * Emitted when the widget has undocked.
+ */
+ void hasUndocked();
+
+protected slots:
+
+ /** Does several things here when it has noticed that the former brother widget (closest neighbor) gets lost.
+ * The former brother widget is needed for a possible dockback action, to speak with the Beatles:
+ * "To get back to where you once belonged" ;-)
+ */
+ void loseFormerBrotherDockWidget();
+
+ virtual void paintEvent(QPaintEvent*);
+
+ virtual void mousePressEvent(QMouseEvent*);
+ virtual void mouseReleaseEvent(QMouseEvent*);
+ virtual void mouseMoveEvent(QMouseEvent*);
+ virtual void leaveEvent(QEvent*);
+protected:
+ friend class KDockWidgetHeader;
+ /**
+ * earlier closest neighbor widget, so it's possible to dock back to it.
+ */
+ KDockWidget* formerBrotherDockWidget;
+ /**
+ * the current dock position.
+ */
+ DockPosition currentDockPos;
+ /**
+ * the former dock position when it really was at another position before.
+ */
+ DockPosition formerDockPos;
+ /**
+ * a string used as tooltip for the tab page header when in dock-centered mode.
+ */
+ QString toolTipStr;
+ /**
+ * a string used as title of the tab page when in tab page mode
+ */
+ QString tabPageTitle;
+
+private:
+ /**
+ * Sets the caption (window title) of the given tab widget.
+ *
+ * @param g the group (tab) widget
+ */
+ void setDockTabName( KDockTabGroup* g);
+
+ /**
+ * Reparent to s or set this to the KDockMainWindow's view if s is that dockmainwindow.
+ * If s is O, simply move the widget.
+ *
+ * @param s the target widget to reparent to
+ * @param p the point to move to (if it doesn't reparent)
+ */
+ void applyToWidget( QWidget* s, const QPoint& p = QPoint(0,0) );
+
+ /**
+ * A base class pointer to the header of this dockwidget
+ */
+ KDockWidgetAbstractHeader* header;
+
+ /**
+ * the embedded widget
+ */
+ QWidget* widget;
+
+ /**
+ * the layout manager that takes care about proper resizing and moving the embedded widget and the header
+ */
+ QVBoxLayout* layout;
+
+ /**
+ * the responsible dockmanager
+ */
+ KDockManager* manager;
+
+ /**
+ * an icon for the tab widget header
+ */
+ QPixmap* pix;
+
+ /**
+ * Information about the ability for docking to another dockwidget.
+ */
+ int eDocking;
+
+ /**
+ * Information which site of this dockwidget is free for docking of other dockwidgets.
+ */
+ int sDocking;
+
+ /**
+ * Previous side (left,right,top,bottom) where this dockwidget was before a dragging action, none if it wasn't dragged before.
+ */
+ KDockWidget::DockPosition prevSideDockPosBeforeDrag;
+
+ // GROUP data
+ QString firstName;
+ QString lastName;
+ Orientation splitterOrientation;
+ bool isGroup;
+ bool isTabGroup;
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KDockWidgetPrivate *d;
+};
+
+/**
+ * The manager that knows all dockwidgets and handles the dock process (and member of the dockwidget class set).
+ * More or less a helper class for the KDockWidget class set but of interest for some functionality
+ * that can be called within a KDockMainWindow or a KDockWidget .
+ *
+ * An important feature is the ability to read or save the current state of all things concerning to
+ * dockwidgets to KConfig .
+ *
+ * The dockmanager is also often used when a certain dockwidget or a child of such dockwidget must be found.
+ *
+ * @author Max Judin (documentation: Falk Brettschneider).
+ */
+class KDEUI_EXPORT KDockManager: public QObject
+{
+ Q_OBJECT
+friend class KDockWidget;
+friend class KDockMainWindow;
+
+public:
+ enum EnReadDockConfigMode {
+ Unknown,
+ WrapExistingWidgetsOnly,
+ RestoreAllDockwidgets
+ };
+
+public:
+ /**
+ * Constructs a dockmanager. Some initialization happen:
+ * @li It installs an event filter for the main window,
+ * @li a control list for dock objects
+ * @li a control list for menu items concerning to menus provided by the dockmanager
+ * @li Some state variables are set
+ *
+ * @param mainWindow the main window controlled by this
+ * @param name the internal QOject name
+ */
+ KDockManager( QWidget* mainWindow, const char* name = 0L );
+
+ /**
+ * Destructs a dockmanager.
+ */
+ virtual ~KDockManager();
+
+ void dumpDockWidgets();
+
+#ifndef NO_KDE2
+ /**
+ * Saves the current state of the dockmanager and of all controlled widgets.
+ * State means here to save the geometry, visibility, parents, internal object names, orientation,
+ * separator positions, dockwidget-group information, tab widget states (if it is a tab group) and
+ * last but not least some necessary things for recovering the dockmainwindow state.
+ *
+ * @param c the KDE configuration saver
+ * @param group the name of the section in KConfig
+ */
+ void writeConfig( KConfig* c = 0L, QString group = QString::null );
+
+ /**
+ * Like writeConfig but reads the whole stuff in.
+ *
+ * In order to restore a window configuration
+ * from a config file, it looks up widgets by name
+ * (QObject::name) in the childDock variable of
+ * KDockManager. This list in turn contains all
+ * KDockWidgets (according to the KDockWidget constructor).
+ * So in principle, in order to restore a window layout,
+ * one must first construct all widgets, put each of them in a
+ * KDockWidget and then call readConfig(). And for all that
+ * to work, each widget must have a unique name.
+ *
+ * @param c the KDE configuration saver
+ * @param group the name of the section in KConfig
+ */
+ void readConfig ( KConfig* c = 0L, QString group = QString::null );
+#endif
+
+ /// @since 3.1
+ void setMainDockWidget2(KDockWidget *);
+
+ /**
+ * Saves the current dock window layout into a DOM tree below the given element.
+ */
+ void writeConfig(QDomElement &base);
+ /**
+ * Reads the current dock window layout from a DOM tree below the given element.
+ */
+ void readConfig(QDomElement &base);
+
+ /**
+ * Shows all encapsulated widgets of all controlled dockwidgets and shows all dockwidgets which are
+ * parent of a dockwidget tab group.
+ */
+ void activate();
+
+ /**
+ * It's more or less a method that catches several events which are interesting for the dockmanager.
+ * Mainly mouse events during the drag process of a dockwidgets are of interest here.
+ *
+ * @param object the object that sends the event
+ * @param event the event
+ * @return the return value of the method call of the base class method
+ */
+ virtual bool eventFilter( QObject * object, QEvent * event );
+
+ /**
+ * This method finds out what a widgets' dockwidget is. That means the dockmanager has a look at all
+ * dockwidgets it knows and tells you when one of those dockwidgets covers the given widget.
+ *
+ * @param w any widget that is supposed to be encapsulated by one of the controlled dockwidgets
+ * @return the dockwidget that encapsulates that widget, otherwise 0
+ */
+ KDockWidget* findWidgetParentDock( QWidget* w) const;
+
+ /**
+ * Works like makeDockVisible() but can be called for widgets that covered by a dockwidget.
+ *
+ * @param w the widget that is encapsulated by a dockwidget that turns to visible.
+ */
+ void makeWidgetDockVisible( QWidget* w ){ findWidgetParentDock(w)->makeDockVisible(); }
+
+ /**
+ * @return the popupmenu for showing/hiding dockwidgets
+ */
+ QPopupMenu* dockHideShowMenu() const { return menu; }
+
+ /**
+ * @param dockName an internal QObject name
+ * @return the dockwidget that has got that internal QObject name
+ */
+ KDockWidget* getDockWidgetFromName( const QString& dockName );
+
+ /**
+ * Enables opaque resizing. Opaque resizing defaults to KGlobalSettings::opaqueResize().
+ * Call this method before you create any dock widgets!
+ */
+ void setSplitterOpaqueResize(bool b=true);
+
+ /**
+ * Returns true if opaque resizing is enabled, false otherwise.
+ */
+ bool splitterOpaqueResize() const;
+
+ /**
+ * Try to preserve the widget's size. Works like KeepSize resize mode
+ * of QSplitter. Off by default.
+ * Call this method before you create any dock widgets!
+ */
+ void setSplitterKeepSize(bool b=true);
+
+ /**
+ * Returns true if the KeepSize is enabled, false otherwise.
+ */
+ bool splitterKeepSize() const;
+
+ /**
+ * Operate the splitter with a higher resolution. Off by default.
+ * Call this method before you create any dock widgets!
+ * If high resolution is used all splitter position parameters
+ * are percent*100 instead of percent.
+ * @note Since KDE 3.5 this is ignored. Internally the splitter always
+ * calcualtes in high resolution values. For KDE 4, this will be removed.
+ */
+ void setSplitterHighResolution(bool b=true);
+
+ /**
+ * Returns true if the splitter uses the high resolution, false otherwise.
+ */
+ bool splitterHighResolution() const;
+
+ /**
+ * @since 3.2
+ */
+ void setSpecialLeftDockContainer(KDockWidget* container);
+ void setSpecialTopDockContainer(KDockWidget* container);
+ void setSpecialRightDockContainer(KDockWidget* container);
+ void setSpecialBottomDockContainer(KDockWidget* container);
+
+ void removeFromAutoCreateList(KDockWidget* pDockWidget);
+ void finishReadDockConfig();
+ void setReadDockConfigMode(int mode);
+
+signals:
+
+ /**
+ * Signals changes of the docking state of a dockwidget. Usually the dock-toolbar will be updated then.
+ */
+ void change();
+
+ /**
+ * Signals a dockwidget is replaced with another one.
+ */
+ void replaceDock( KDockWidget* oldDock, KDockWidget* newDock );
+
+ /**
+ * Signals a dockwidget without parent (toplevel) is shown.
+ */
+ void setDockDefaultPos( KDockWidget* );
+
+private slots:
+
+ /**
+ * Clears the popupmenu for showing/hiding dockwidgets and fills it with the current states of all controlled dockwidgets.
+ */
+ void slotMenuPopup();
+
+ /**
+ * This method assumes a menuitem of the popupmenu for showing/hiding dockwidgets is selected and toggles that state.
+ *
+ * @param id the popupmenu id of the selected menuitem
+ */
+ void slotMenuActivated( int id);
+
+ /* clears the old drawn drag rectangle (oldDragRect) from screen and
+ * draws the new current drag rectangle (dragRect) depending on the current mouse position.
+ * This highlights the dockwidget which is the currently chosen target during a dock action.
+ */
+ void drawDragRectangle();
+
+private:
+
+ /**
+ * A data structure containing data about every dockwidget that is under control.
+ */
+ struct MenuDockData
+ {
+ MenuDockData( KDockWidget* _dock, bool _hide )
+ {
+ dock = _dock;
+ hide = _hide;
+ }
+ ~MenuDockData(){}
+
+ KDockWidget* dock;
+ bool hide;
+ };
+
+ /**
+ * Finds the KDockWidget at the position given as parameter
+ *
+ * @param pos global (desktop) position of the wanted dockwidget
+ * @return the dockwidget at that position
+ */
+ KDockWidget* findDockWidgetAt( const QPoint& pos );
+
+ /**
+ * Finds the QWidget recursively at the position given as parameter
+ *
+ * @param w a variable where the method puts the QWidget at that position (instead of a return value)
+ * @param p the parent widget where the recursive search should start from
+ * @param pos global (desktop) position of the wanted dockwidget
+ */
+ void findChildDockWidget( QWidget*& w, const QWidget* p, const QPoint& pos );
+
+ /**
+ * Finds all dockwidgets which are child, grandchild and so on of p.
+ *
+ * @param p the parent widget where the recursive search starts from
+ * @param l the widget list that contains the search result after the return of this method
+ */
+ void findChildDockWidget( const QWidget* p, QWidgetList*& l);
+
+ /**
+ * Sets a dockwidget in drag mode.
+ */
+ void startDrag( KDockWidget* );
+
+ /**
+ * Moves a dockwidget that is in drag mode.
+ *
+ * @param d the dockwidget which is dragged
+ * @param pos the new position of the dragged dockwidget
+ */
+ void dragMove( KDockWidget* d, QPoint pos );
+
+ /**
+ * Aborts the drag mode. Restores the cursor and hides the drag indicator.
+ */
+ void cancelDrop();
+
+ /**
+ * Finishes the drag mode. If the user let it drop on an other dockwidget, it will possibly be docked (if allowed),
+ * if the user drops it outside of the application window it becomes toplevel.
+ */
+ void drop();
+
+// class members
+
+ /**
+ * Usually the KDockMainWindow but not necessarily.
+ */
+ QWidget* main;
+
+ /**
+ * The dockwidget that is being dragged at the moment
+ */
+ KDockWidget* currentDragWidget;
+
+ /**
+ * The target dockwidget where the currentDragWidget is dropped
+ */
+ KDockWidget* currentMoveWidget; // widget where mouse moving
+
+ /**
+ * It is of interest during the dock process. Then it contains all child dockwidgets.
+ */
+ QWidgetList* childDockWidgetList;
+
+ /**
+ * The dockposition where the dockwidget would be docked to, if we dropped it here.
+ */
+ KDockWidget::DockPosition curPos;
+
+ /**
+ * A QList of all objects that are important for docking.
+ * Some serve as group widgets of dockwidgets, others encapsulate normal widgets.
+ */
+ QObjectList* childDock;
+
+ /**
+ * Contains dockwidgets that are created automatically by the dockmanager. For internal use.
+ */
+ QObjectList* autoCreateDock;
+
+ /**
+ * For storing the width during the dragging of a dockwidget.
+ */
+ int storeW;
+
+ /**
+ * For storing the height during the dragging of a dockwidget.
+ */
+ int storeH;
+
+ /**
+ * State variable if there is a drag process active.
+ */
+ bool dragging;
+
+ /**
+ * State variable if there is an undock process active
+ */
+ bool undockProcess;
+
+ /**
+ * The dockmanager sets it to true if the user cancels the drag by moving the cursor
+ * on a invalid drop place
+ */
+ bool dropCancel;
+
+ /**
+ * A popup menu that contains one menuitem for each dockwidget that shows the current visibility state and
+ * to show or hide the appropriate dockwidget.
+ */
+ QPopupMenu* menu;
+
+ /**
+ * An internal list containing data for the menuitems for the visibility popup menu.
+ */
+ QPtrList<MenuDockData> *menuData;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KDockManagerPrivate;
+ KDockManagerPrivate *d;
+};
+
+/**
+ * A special kind of KMainWindow that is able to have dockwidget child widgets (and member of the dockwidget class set).
+ *
+ * The main widget should be a KDockWidget where other KDockWidget can be docked to
+ * the left, right, top, bottom or to the middle.
+ * Note: dock to the middle means to drop on a dockwidget and to unite them to a new widget, a tab control.
+ *
+ * Furthermore, the KDockMainWindow has got the KDockManager and some data about the dock states.
+ *
+ * If you've got some dockwidgets, you can dock them to the dockmainwindow to initialize a start scene:
+ * Here an example:
+ * \code
+ * DockApplication::DockApplication( const char* name) : KDockMainWindow( name)
+ * {
+ * ...
+ * KDockWidget* mainDock;
+ * mainDock = createDockWidget( "Falk's MainDockWidget", mainPixmap, 0L, "main_dock_widget");
+ * AnyContentsWidget* cw = new AnyContentsWidget( mainDock);
+ * mainDock->setWidget( cw);
+ * // allow others to dock to the 4 sides
+ * mainDock->setDockSite(KDockWidget::DockCorner);
+ * // forbit docking abilities of mainDock itself
+ * mainDock->setEnableDocking(KDockWidget::DockNone);
+ * setView( mainDock); // central widget in a KDE mainwindow
+ * setMainDockWidget( mainDock); // master dockwidget
+ * ...
+ * KDockWidget* dockLeft;
+ * dockLeft = createDockWidget( "Intially left one", anyOtherPixmap, 0L, i18n("The left dockwidget"));
+ * AnotherWidget* aw = new AnotherWidget( dockLeft);
+ * dockLeft->setWidget( aw);
+ * dockLeft->manualDock( mainDock, // dock target
+ * KDockWidget::DockLeft, // dock site
+ * 20 ); // relation target/this (in percent)
+ * ...
+ * \endcode
+ *
+ * Docking is fully dynamic at runtime. That means you can always move dockwidgets via drag and drop.
+ *
+ * And last but not least you can use the popupmenu for showing or hiding any controlled dockwidget
+ * of this class and insert it to your main menu bar or anywhere else.
+ *
+ * @author Max Judin (documentation: Falk Brettschneider).
+ */
+class KDEUI_EXPORT KDockMainWindow : public KMainWindow
+{
+ Q_OBJECT
+
+friend class KDockManager;
+
+public:
+
+ /**
+ * Constructs a dockmainwindow. It calls its base class constructor and does additional things concerning
+ * to the dock stuff:
+ * @li information about the dock state of this' children gets initialized
+ * @li a dockmanager is created...
+ * @li ...and gets initialized
+ * @li the main dockwidget is set to 0
+ *
+ * @param parent Parent widget for the dock main widget
+ * @param name internal object name
+ * @param f Qt::WidgetFlags widget flags
+ */
+ KDockMainWindow( QWidget* parent = 0L, const char *name = 0L, WFlags f = WType_TopLevel | WDestructiveClose );
+
+ /**
+ * Destructs a dockmainwindow.
+ */
+ virtual ~KDockMainWindow();
+
+ /**
+ * Returns the dockmanager of this. (see KDockManager)
+ * @return pointer to the wanted dockmanager
+ */
+ KDockManager* manager() const { return dockManager; }
+
+ /**
+ * Sets a new main dockwidget.
+ * Additionally, the toolbar is re-initialized.
+ *
+ * @param dockwidget dockwidget that become the new main dockwidget
+ */
+ void setMainDockWidget( KDockWidget* dockwidget);
+
+ /**
+ * Returns the main dockwidget.
+ *
+ * @return pointer to the main dockwidget
+ */
+ KDockWidget* getMainDockWidget() const { return mainDockWidget; }
+
+ /**
+ * This is one of the most important methods!
+ * The KDockMainWindow creates a new dockwidget object here that usually should encapsulate the user's widget.
+ * The new dockwidget is automatically taken under control by the dockmanager of the dockmainwindow.
+ *
+ * @param name QObject name (default dockwidget caption)
+ * @param pixmap window icon (for instance shown when docked as tabwidget entry)
+ * @param parent parent widget for the new dockwidget
+ * @param strCaption window title (shown when toplevel)
+ * @param strTabPageLabel title of the tab page (visible when in tab page mode), if it is "", only the icon will be shown; if it is 0L, the label is set to strCaption
+ * @return a pointer to the new created dockwidget
+ */
+ KDockWidget* createDockWidget( const QString& name, const QPixmap &pixmap, QWidget* parent = 0L,
+ const QString& strCaption = QString::null, const QString& strTabPageLabel = QString::fromLatin1( " " ) );
+
+ /**
+ * Saves the current dock window layout into a DOM tree below the given element.
+ */
+ void writeDockConfig(QDomElement &base);
+ /**
+ * Reads the current dock window layout from a DOM tree below the given element.
+ */
+ void readDockConfig(QDomElement &base);
+
+#ifndef NO_KDE2
+ /**
+ * It writes the current dock state in the given section of KConfig.
+ *
+ * @param c KDE class for saving configurations
+ * @param group name of section to write to
+ */
+ void writeDockConfig( KConfig* c = 0L, QString group = QString::null );
+
+ /**
+ * It reads the current dock state from the given section of KConfig.
+ *
+ * @param c KDE class for saving configurations
+ * @param group name of section to read from
+ */
+ void readDockConfig ( KConfig* c = 0L, QString group = QString::null );
+#endif
+
+ /**
+ * It runs through all dockwidgets which are under control of the dockmanager and calls show() for every
+ * encapsulated widget and show() for the dockwidget itself if it is not in tab mode.
+ * Additionally, if the main dockwidget is not a QDialog, it will be shown.
+ */
+ void activateDock(){ dockManager->activate(); }
+
+ /**
+ * Returns a popup menu that contains entries for all controlled dockwidgets making hiding and showing
+ * them possible.
+ *
+ * @return the wanted popup menu
+ */
+ QPopupMenu* dockHideShowMenu() const { return dockManager->dockHideShowMenu(); }
+
+ /**
+ * This method shows the given dockwidget.
+ * The clue is that it also considers the dockwidget could be a tab page
+ * and must set to be the activate one.
+ *
+ * @param dock the dockwidget that is to be shown
+ */
+ void makeDockVisible( KDockWidget* dock );
+
+ /**
+ * This method hides the given dockwidget.
+ *
+ * @param dock the dockwidget that is to be shown
+ */
+ void makeDockInvisible( KDockWidget* dock );
+
+ /**
+ * This is an overloaded member function, provided for convenience.
+ * It differs from the above function only in what argument(s) it accepts.
+ */
+ void makeWidgetDockVisible( QWidget* widget );
+
+ /**
+ * This method calls the base class method.
+ * If the given widget inherits KDockWidget, applyToWidget(this) is called.
+ *
+ * @param widget any widget that should become the main view
+ */
+ void setView( QWidget * widget );
+
+signals:
+ /**
+ * Signals a certain dockwidget is undocked now.
+ */
+ void dockWidgetHasUndocked(KDockWidget*);
+
+protected:
+
+ /**
+ * A pointer to the main dockwidget (where one can manualDock() to
+ */
+ KDockWidget* mainDockWidget;
+
+ /**
+ * A pointer to the manager for the dock process
+ */
+ KDockManager* dockManager;
+
+protected slots:
+ /**
+ * Called whenever one of the dockwidgets of this has been undocked.
+ */
+ void slotDockWidgetUndocked();
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KDockMainWindowPrivate;
+ KDockMainWindowPrivate *d;
+};
+
+class KDEUI_EXPORT KDockArea : public QWidget
+{
+ Q_OBJECT
+
+friend class KDockManager;
+
+public:
+
+
+ KDockArea( QWidget* parent = 0L, const char *name = 0L);
+
+ virtual ~KDockArea();
+
+ KDockManager* manager(){ return dockManager; }
+
+
+ void setMainDockWidget( KDockWidget* );
+ KDockWidget* getMainDockWidget(){ return mainDockWidget; }
+
+ KDockWidget* createDockWidget( const QString& name, const QPixmap &pixmap, QWidget* parent = 0L,
+ const QString& strCaption = QString::null, const QString& strTabPageLabel = QString::fromLatin1( " " ) );
+
+ void writeDockConfig(QDomElement &base);
+ void readDockConfig(QDomElement &base);
+
+#ifndef NO_KDE2
+ void writeDockConfig( KConfig* c = 0L, QString group = QString::null );
+ void readDockConfig ( KConfig* c = 0L, QString group = QString::null );
+#endif
+
+
+
+ void activateDock(){ dockManager->activate(); }
+ QPopupMenu* dockHideShowMenu(){ return dockManager->dockHideShowMenu(); }
+ void makeDockVisible( KDockWidget* dock );
+ void makeDockInvisible( KDockWidget* dock );
+ void makeWidgetDockVisible( QWidget* widget );
+ //void setView( QWidget* );
+
+signals:
+ /**
+ * Signals a certain dockwidget is undocked now.
+ */
+ void dockWidgetHasUndocked(KDockWidget*);
+
+protected:
+
+ KDockWidget* mainDockWidget;
+ KDockManager* dockManager;
+
+protected slots:
+ void slotDockWidgetUndocked();
+
+public:
+ virtual void resizeEvent(QResizeEvent *);
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KDockMainWindowPrivate;
+ KDockMainWindowPrivate *d;
+};
+
+
+#endif
+
+
diff --git a/kdeui/kdockwidget_p.h b/kdeui/kdockwidget_p.h
new file mode 100644
index 000000000..7c14394eb
--- /dev/null
+++ b/kdeui/kdockwidget_p.h
@@ -0,0 +1,89 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2002,2003 Joseph Wenninger <jowenn@kde.org
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+/***********************************************************************
+************************************************************************
+ IMPORTANT - IMPORTANT - IMPORTANT - IMPORTANT - IMPORTANT - IMPORTANT
+************************************************************************
+************************************************************************
+
+THIS IS ___NOT___ PART OF THE PUBLIC API YET. DON'T USE IT IN YOUR
+APPLICATIONS,SINCE IT'S MOST PROBABLY ___NOT___ GOING TO STAY BINARY
+COMPATIBLE. THIS HEADER IS ONLY INSTALLED, BECAUSE IT IS NEEDED IN
+ KDE 3.1'S KATE APPLICATON
+
+************************************************************************
+************************************************************************
+ IMPORTANT - IMPORTANT - IMPORTANT - IMPORTANT - IMPORTANT - IMPORTANT
+************************************************************************
+***********************************************************************/
+
+#ifndef KDOCKWIDGET_P_H
+#define KDOCKWIDGET_P_H
+
+#include <kdockwidget.h>
+#include <qstringlist.h>
+// Add some describing comment !!
+
+class KDEUI_EXPORT KDockContainer
+{
+public:
+ KDockContainer();
+ virtual ~KDockContainer();
+ virtual KDockWidget *parentDockWidget();
+ virtual void insertWidget (KDockWidget *, QPixmap, const QString &, int &);
+ virtual void showWidget(KDockWidget *);
+ virtual void removeWidget(KDockWidget*);
+ virtual void undockWidget(KDockWidget*);
+ virtual void save(KConfig *cfg,const QString& group_or_prefix);
+ virtual void save(QDomElement& dockElement);
+ virtual void load(KConfig *cfg,const QString& group_or_prefix);
+ virtual void load(QDomElement& dockElement);
+ virtual void setToolTip (KDockWidget *, QString &);
+ virtual void setPixmap(KDockWidget*,const QPixmap&);
+ QStringList containedWidgets() const;
+ virtual bool dockDragEnter(KDockWidget* dockWidget, QMouseEvent *event);
+ virtual bool dockDragMove(KDockWidget* dockWidget, QMouseEvent *event);
+ virtual bool dockDragLeave(KDockWidget* dockWidget, QMouseEvent *event);
+protected:
+ friend class KDockManager;
+ friend class KDockSplitter;
+ void prepareSave(QStringList &names);
+ void activateOverlapMode(int nonOverlapSize);
+ void deactivateOverlapMode();
+ bool isOverlapMode();
+private:
+
+ struct ListItem {
+ struct ListItem *prev;
+ struct ListItem *next;
+ char *data;
+ };
+
+
+
+ struct ListItem *m_childrenListBegin;
+ struct ListItem *m_childrenListEnd;
+
+ class KDockContainerPrivate;
+ KDockContainerPrivate *d;
+ bool m_overlapMode;
+ int m_nonOverlapSize;
+};
+
+#endif
diff --git a/kdeui/kdockwidget_private.cpp b/kdeui/kdockwidget_private.cpp
new file mode 100644
index 000000000..58bc954bc
--- /dev/null
+++ b/kdeui/kdockwidget_private.cpp
@@ -0,0 +1,712 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Max Judin <novaprint@mtu-net.ru>
+ Copyright (C) 2002,2003 Joseph Wenninger <jowenn@kde.org>
+ Copyright (C) 2005 Dominik Haumann <dhdev@gmx.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#include "kdockwidget.h"
+#include "kdockwidget_p.h"
+#include "kdockwidget_private.h"
+
+#include <qpainter.h>
+#include <qcursor.h>
+#include <kdebug.h>
+#include <qtimer.h>
+#include <qapplication.h>
+
+#include <math.h> // need ceil
+
+KDockSplitter::KDockSplitter(QWidget *parent, const char *name, Orientation orient, int pos)
+: QWidget(parent, name)
+{
+ m_dontRecalc=false;
+ divider = 0L;
+ child0 = 0L;
+ child1 = 0L;
+ fixedWidth0=-1;
+ fixedWidth1=-1;
+ fixedHeight0=-1;
+ fixedHeight1=-1;
+
+ m_orientation = orient;
+ mOpaqueResize = false;
+ mKeepSize = false;
+ setSeparatorPosInPercent( pos );
+ initialised = false;
+}
+
+void KDockSplitter::activate(QWidget *c0, QWidget *c1)
+{
+ if ( c0 ) child0 = c0;
+ if ( c1 ) child1 = c1;
+
+ setupMinMaxSize();
+
+ if (divider) delete divider;
+ divider = new QFrame(this, "pannerdivider");
+ divider->setFrameStyle(QFrame::Panel | QFrame::Raised);
+ divider->setLineWidth(1);
+ divider->raise();
+
+ if (m_orientation == Horizontal)
+ divider->setCursor(QCursor(sizeVerCursor));
+ else
+ divider->setCursor(QCursor(sizeHorCursor));
+ divider->installEventFilter(this);
+
+ initialised= true;
+
+ updateName();
+ divider->show();
+
+ // without this resize event, things will not work. why exactly? :(
+ resizeEvent(0);
+
+
+ KDockWidget* dw0 = (KDockWidget*) child0;
+ KDockWidget* dw1 = (KDockWidget*) child1;
+
+ // if fixed size is set, restore first, to restore xpos correctly
+ if( fixedWidth0 != -1 || fixedHeight0 != -1 ) restoreFromForcedFixedSize( dw0 );
+ if( fixedWidth1 != -1 || fixedHeight1 != -1 ) restoreFromForcedFixedSize( dw1 );
+
+
+ // now force fixed sizes, if they are set.
+ if( dw0->forcedFixedWidth() != -1 ) {
+ setForcedFixedWidth( dw0, dw0->forcedFixedWidth() );
+ }
+ else if( dw1->forcedFixedWidth() != -1 ) {
+ setForcedFixedWidth( dw1, dw1->forcedFixedWidth() );
+ }
+
+ if( dw0->forcedFixedHeight() != -1 ) {
+ setForcedFixedHeight (dw0, dw0->forcedFixedHeight() );
+ }
+ else if( dw1->forcedFixedHeight() != -1 ) {
+ setForcedFixedHeight( dw1, dw1->forcedFixedHeight() );
+ }
+}
+
+/*
+void KDockSplitter::delayedResize()
+{
+ kdDebug(282)<<"*********************** DELAYED RESIZE !!!!!!!!!!!!!!!"<<endl;
+ resizeEvent(0);
+}*/
+
+void KDockSplitter::setForcedFixedWidth(KDockWidget *dw,int w)
+{
+ if (dw==child0)
+ {
+ if (fixedWidth0==-1) savedXPos=xpos;
+ if (w==fixedWidth0) return;
+ fixedWidth0=w;
+ setSeparatorPos(w*factor/width(),true);
+// kdDebug(282)<<"Set forced fixed width for widget 0 :"<<w<<endl;
+ }
+ else
+ {
+ if (fixedWidth1==-1) savedXPos=xpos;
+ if (w==fixedWidth1) return;
+ fixedWidth1=w;
+ setSeparatorPos((width()-w)*factor/width(),true);
+// kdDebug(282)<<"Set forced fixed width for widget 1 :"<<w<<endl;
+ }
+ setupMinMaxSize();
+ if (divider) divider->hide();
+}
+
+void KDockSplitter::setForcedFixedHeight(KDockWidget *dw,int h)
+{
+ if (dw==child0)
+ {
+ if (fixedHeight0==-1) savedXPos=xpos;
+ if (h==fixedHeight0) return;
+ fixedHeight0=h;
+ setSeparatorPos(h*factor/height(),true);
+// // kdDebug(282)<<"Set forced fixed width for widget 0 :"<<h<<endl;
+ }
+ else
+ {
+ if (fixedHeight1==-1) savedXPos=xpos;
+ if (h==fixedHeight1) return;
+ fixedHeight1=h;
+ setSeparatorPos((height()-h)*factor/height(),true);
+// kdDebug(282)<<"Set forced fixed height for widget 1 :"<<h<<endl;
+ }
+ setupMinMaxSize();
+ if (divider) divider->hide();
+}
+
+void KDockSplitter::restoreFromForcedFixedSize(KDockWidget *dw)
+{
+ if (divider) divider->show();
+ if (dw==child0)
+ {
+ fixedWidth0=-1;
+ fixedHeight0=-1;
+ setSeparatorPos(savedXPos,true);
+ }
+ else
+ {
+ fixedWidth1=-1;
+ fixedHeight1=-1;
+ setSeparatorPos(savedXPos,true);
+ }
+}
+
+
+void KDockSplitter::setupMinMaxSize()
+{
+ // Set the minimum and maximum sizes for the KDockSplitter (this)
+ int minx, maxx, miny, maxy;
+ if (m_orientation == Horizontal) {
+ miny = child0->minimumHeight() + child1->minimumHeight() + 4;
+ maxy = child0->maximumHeight() + child1->maximumHeight() + 4;
+ minx = (child0->minimumWidth() > child1->minimumWidth()) ? child0->minimumWidth() : child1->minimumWidth();
+ maxx = (child0->maximumWidth() > child1->maximumWidth()) ? child0->maximumWidth() : child1->maximumWidth();
+
+ if (miny < 4) miny = 4;
+ if (maxy > 32000) maxy = 32000;
+ if (minx < 2) minx = 2;
+ if (maxx > 32000) maxx = 32000;
+ }
+ else
+ {
+ minx = child0->minimumWidth() + child1->minimumWidth() + 4;
+ maxx = child0->maximumWidth() + child1->maximumWidth() + 4;
+ miny = (child0->minimumHeight() > child1->minimumHeight()) ? child0->minimumHeight() : child1->minimumHeight();
+ maxy = (child0->maximumHeight() > child1->maximumHeight()) ? child0->maximumHeight() : child1->maximumHeight();
+
+ if (miny < 2) miny = 2;
+ if (maxy > 32000) maxy = 32000;
+ if (minx < 4) minx = 4;
+ if (maxx > 32000) maxx = 32000;
+ }
+
+ setMinimumSize(minx, miny);
+ setMaximumSize(maxx, maxy);
+}
+
+void KDockSplitter::deactivate()
+{
+ if (divider) delete divider;
+ divider = 0L;
+ initialised= false;
+}
+
+int KDockSplitter::separatorPosInPercent()
+{
+ return xpos / (factor/100);
+}
+
+void KDockSplitter::setSeparatorPosInPercent(int percent)
+{
+ xpos = percent * (factor/100);
+}
+
+void KDockSplitter::setSeparatorPos(int pos, bool do_resize)
+{
+ xpos = pos;
+ if (do_resize)
+ resizeEvent(0);
+}
+
+void KDockSplitter::setSeparatorPosX(int pos, bool do_resize)
+{
+ savedXPos = pos;
+ setSeparatorPos( pos, do_resize );
+}
+
+int KDockSplitter::separatorPos() const
+{
+ return xpos;
+}
+
+void KDockSplitter::resizeEvent(QResizeEvent *ev)
+{
+ //
+ // As already stated in the .h file we always have to differentiate
+ // between 6 modes.
+ // If we can cast child0->getWidget() or child1.getWidget() to
+ // KDockContainer* we *do* have a dockwidget around. For dockwidgets
+ // we have to take special care in the resizing routines, for example
+ // if mKeepSize is true and the dockcontainer is on the bottom or right,
+ // we always have to move the xpos splitter position. If there are no
+ // dockcontainers around, resizing is handeled like if child0 would
+ // be a dockcontainer.
+ //
+
+// kdDebug(282)<<"ResizeEvent :"<< ((initialised) ? "initialised":"not initialised")<<", "<< ((ev) ? "real event":"")<<", "<<(isVisible() ?"visible":"")<<endl;
+
+ if (initialised) {
+ KDockContainer *dc = 0L;
+ KDockWidget *c0 = (KDockWidget*)child0;
+ KDockWidget *c1 = (KDockWidget*)child1;
+ bool stdHandling=false; // true: if closed or nonoverlap mode. false: overlap mode
+
+ //
+ // Check whether this is a real resize event or a pseudo resize event
+ // Real resize events occure if the width() or height() changes. ev != 0L.
+ // Pseudo resize events occure if the dockwidget mode changes (overlaped,
+ // sticky or closed). ev == 0L.
+ //
+ if (ev && isVisible() && divider->isVisible()) {
+ // real resize event.
+// kdDebug(282)<<"mKeepSize : "<< ((m_orientation == Horizontal) ? "Horizontal":"Vertical") <<endl;
+
+ if (mKeepSize) {
+ // keep the splitter on a fixed position. This may be a bit inaccurate, because
+ // xpos saves a proportional value, which means there might occur rounding errors.
+ // However, this works surprising well!
+ if (m_orientation == Horizontal) {
+ if (ev->oldSize().height() != ev->size().height()) {
+ if( (c1->getWidget()) && (dc=dynamic_cast<KDockContainer*>(c1->getWidget()))) {
+ // dockwidget is on the bottom. move xpos so that the size from child1 stays
+ xpos = (int)ceil(((double)factor) * checkValue(height() - child1->height() - 4) / height());
+ } else {
+ // xpos should not change, the docking is on the top
+ // checkValue is *fuzzy* here, it leads to ugly rounding bugs
+ // In truth, it is not needed, because it is called when calculating the "position".
+ xpos = qRound(((double)xpos) * ev->oldSize().height() / height());
+ }
+ }
+ } else {
+ if (ev->oldSize().width() != width()) {
+ if( (c1->getWidget()) && (dc=dynamic_cast<KDockContainer*>(c1->getWidget()))) {
+ xpos = (int)ceil(((double)factor) * checkValue(width() - child1->width() - 4) / width());
+ } else {
+ // xpos should not change
+ // checkValue is *fuzzy* here, it leads to ugly rounding bugs
+ xpos = qRound(((double)xpos) * ev->oldSize().width() / width());
+ }
+ }
+ }
+ } else {
+ // dockwidget size proportional!
+ // Which means, xpos is always right (ratio value). Do nothing! :)
+ }
+ }
+ else
+ {
+ //
+ // Maybe a multitabbartab was clicked, so force an update of the fixed
+ // values.
+ //
+ if ( isVisible()) {
+ if (m_orientation == Horizontal) {
+ if (fixedHeight0!=-1)
+ xpos = checkValue(fixedHeight0) * factor / height();
+ else if (fixedHeight1!=-1)
+ xpos = checkValue(height()-fixedHeight1) * factor / height();
+ }
+ else
+ {
+ if (fixedWidth0!=-1)
+ xpos = checkValue(fixedWidth0) * factor / width();
+ else if (fixedWidth1!=-1)
+ xpos = checkValue(width()-fixedWidth1) * factor / width();
+ }
+ }
+// else kdDebug(282)<<"Something else happened"<<endl;
+ }
+
+/*
+ // --- debugging information ---
+ kdDebug(282) << "isVisible() is : " << isVisible() << endl;
+ kdDebug(282) << "Orientation : " << (m_orientation==Horizontal?"Horizontal":"Vertical")
+ << endl;
+ kdDebug(282) << "Splitter visibility : " << divider->isVisible() << endl;;
+ kdDebug(282) << "Splitter procentual pos: " << xpos << endl;
+ if (c0->getWidget()) {
+ dc=dynamic_cast<KDockContainer*>(c0->getWidget());
+ kdDebug(282) << "Child 0 KDockContainer?: " << dc << endl;
+ }
+ if (c1->getWidget()) {
+ dc=dynamic_cast<KDockContainer*>(c1->getWidget());
+ kdDebug(282) << "Child 1 KDockContainer?: " << dc << endl;
+ }
+ kdDebug(282) << "Child0 : " << child0 << endl;
+ kdDebug(282) << "child1 : " << child1 << endl;
+*/
+
+ //
+ // handle overlapped widgets only.
+ //
+ if( ( (m_orientation==Vertical) &&((fixedWidth0==-1) && (fixedWidth1==-1)) ) ||
+ ( (m_orientation==Horizontal) &&((fixedHeight0==-1) && (fixedHeight1==-1)) ) ) {
+ if ((c0->getWidget()) && (dc=dynamic_cast<KDockContainer*>(c0->getWidget()))
+ && (dc->isOverlapMode())) {
+ // child0 ist a KDockContainer
+ int position;
+ child0->show();
+ child0->raise();
+ divider->raise();
+ if (m_orientation == Horizontal) {
+ position = checkValueOverlapped( height() * xpos / factor, child0 );
+ child0->setGeometry(0, 0, width(), position);
+ child1->setGeometry(0, dc->m_nonOverlapSize, width(), height()-dc->m_nonOverlapSize);
+ divider->setGeometry(0, position, width(), 4);
+ } else {
+ position = checkValueOverlapped( width() * xpos / factor, child0 );
+ child0->setGeometry(0, 0, position, height());
+ child1->setGeometry(dc->m_nonOverlapSize, 0, width()-dc->m_nonOverlapSize, height());
+ divider->setGeometry(position, 0, 4, height());
+ }
+ } else {
+ if ((c1->getWidget()) && (dc=dynamic_cast<KDockContainer*>(c1->getWidget()))
+ && (dc->isOverlapMode())) {
+ // child1 ist a KDockContainer
+ int position;
+ child1->show();
+ child1->raise();
+ divider->raise();
+ if (m_orientation == Horizontal) {
+ position = checkValueOverlapped( height() * xpos / factor, child1 );
+ child0->setGeometry(0, 0, width(), height()-dc->m_nonOverlapSize);
+ child1->setGeometry(0, position+4, width(), height()-position-4);
+ divider->setGeometry(0, position, width(), 4);
+ } else {
+ position = checkValueOverlapped( width() * xpos / factor, child1 );
+ child0->setGeometry(0, 0, width()-dc->m_nonOverlapSize, height());
+ child1->setGeometry(position+4, 0, width()-position-4, height());
+ divider->setGeometry(position, 0, 4, height());
+ }
+ }
+ else // no KDockContainer available, this means the mode cannot be overlapped
+ stdHandling=true;
+ }
+ }
+ else // no KDockContainer available
+ stdHandling=true;
+
+ //
+ // stdHandling == true means either sticky mode (=nonoverlap mode) or
+ // closed mode. In both modes the widgets do *not* overlap, so we know
+ // the child0 and child1 adjoin.
+ //
+ if (stdHandling) {
+ int position = checkValue( (m_orientation == Vertical ? width() : height()) * xpos / factor );
+ int diff = 0;
+
+ if (m_orientation == Horizontal) {
+ if ((c1->getWidget()) && (dc=dynamic_cast<KDockContainer*>(c1->getWidget()))) {
+ // bottom is dockcontainer
+ if( divider->isVisible() ) {
+ child0->setGeometry(0, 0, width(), position);
+ child1->setGeometry(0, position+4, width(), height()-position-4);
+ } else {
+ child0->setGeometry(0, 0, width(), height()-dc->m_nonOverlapSize);
+ child1->setGeometry(0, height()-dc->m_nonOverlapSize, width(), height());
+ }
+ } else {
+ if( divider->isVisible() ) diff = 4;
+ child0->setGeometry(0, 0, width(), position);
+ child1->setGeometry(0, position+diff, width(), height()-position-diff);
+ }
+ divider->setGeometry(0, position, width(), 4);
+ } else {
+ if ((c1->getWidget()) && (dc=dynamic_cast<KDockContainer*>(c1->getWidget()))) {
+ // right is dockcontainer
+ if( divider->isVisible() ) {
+ child0->setGeometry(0, 0, position, height());
+ child1->setGeometry(position+4, 0, width()-position-4, height());
+ } else {
+ child0->setGeometry(0, 0, width()-dc->m_nonOverlapSize, height());
+ child1->setGeometry(width()-dc->m_nonOverlapSize, 0, width(), height());
+ }
+ } else {
+ if( divider->isVisible() ) diff = 4;
+ child0->setGeometry(0, 0, position, height());
+ child1->setGeometry(position+diff, 0, width()-position-diff, height());
+ }
+ divider->setGeometry(position, 0, 4, height());
+ }
+ }
+ }
+}
+
+int KDockSplitter::checkValueOverlapped(int position, QWidget *overlappingWidget) const
+{
+ if (initialised) {
+ if (m_orientation == Vertical) {
+ if (child0==overlappingWidget) {
+ if (position < child0->minimumWidth() || position > width())
+ position = child0->minimumWidth();
+ } else {
+ if (position > (width()-child1->minimumWidth()-4) || position < 0)
+ position = width()-child1->minimumWidth()-4;
+ }
+ } else {// orientation == Horizontal
+ if (child0==overlappingWidget) {
+ if (position < (child0->minimumHeight()) || position > height())
+ position = child0->minimumHeight();
+ } else {
+ if (position>(height()-child1->minimumHeight()-4) || position < 0)
+ position = height()-child1->minimumHeight()-4;
+ }
+ }
+ }
+ return position;
+}
+
+int KDockSplitter::checkValue( int position ) const
+{
+ if (initialised) {
+ if (m_orientation == Vertical) {
+ if (position < child0->minimumWidth())
+ position = child0->minimumWidth();
+ if ((width()-4-position) < (child1->minimumWidth()))
+ position = width() - (child1->minimumWidth()) - 4;
+ } else {
+ if (position < (child0->minimumHeight()))
+ position = child0->minimumHeight();
+ if ((height()-4-position) < child1->minimumHeight())
+ position = height() - (child1->minimumHeight()) - 4;
+ }
+ }
+
+ if (position < 0) position = 0;
+
+ if ((m_orientation == Vertical) && (position > width()))
+ position = width();
+ if ((m_orientation == Horizontal) && (position > height()))
+ position = height();
+
+ return position;
+}
+
+bool KDockSplitter::eventFilter(QObject *o, QEvent *e)
+{
+ QMouseEvent *mev;
+ bool handled = false;
+
+ switch (e->type()) {
+ case QEvent::MouseMove:
+ mev= (QMouseEvent*)e;
+ child0->setUpdatesEnabled(mOpaqueResize);
+ child1->setUpdatesEnabled(mOpaqueResize);
+ if (m_orientation == Horizontal) {
+ if ((fixedHeight0!=-1) || (fixedHeight1!=-1))
+ {
+ handled=true; break;
+ }
+
+ if (!mOpaqueResize) {
+ int position = checkValue( mapFromGlobal(mev->globalPos()).y() );
+ divider->move( 0, position );
+ } else {
+ int tmp_xpos = factor * checkValue( mapFromGlobal(mev->globalPos()).y() ) / height();
+ if (tmp_xpos != xpos) {
+ xpos = tmp_xpos;
+ resizeEvent(0);
+ divider->repaint(true);
+ }
+ }
+ } else {
+ if ((fixedWidth0!=-1) || (fixedWidth1!=-1))
+ {
+ handled=true; break;
+ }
+ if (!mOpaqueResize) {
+ int position = checkValue( mapFromGlobal(QCursor::pos()).x() );
+ divider->move( position, 0 );
+ } else {
+ int tmp_xpos = factor * checkValue( mapFromGlobal( mev->globalPos()).x() ) / width();
+ if (tmp_xpos != xpos) {
+ xpos = tmp_xpos;
+ resizeEvent(0);
+ divider->repaint(true);
+ }
+ }
+ }
+ handled= true;
+ break;
+ case QEvent::MouseButtonRelease:
+ child0->setUpdatesEnabled(true);
+ child1->setUpdatesEnabled(true);
+ mev= (QMouseEvent*)e;
+ if (m_orientation == Horizontal){
+ if ((fixedHeight0!=-1) || (fixedHeight1!=-1))
+ {
+ handled=true; break;
+ }
+ xpos = factor* checkValue( mapFromGlobal(mev->globalPos()).y() ) / height();
+ resizeEvent(0);
+ divider->repaint(true);
+ } else {
+ if ((fixedWidth0!=-1) || (fixedWidth1!=-1))
+ {
+ handled=true; break;
+ }
+ xpos = factor* checkValue( mapFromGlobal(mev->globalPos()).x() ) / width();
+ resizeEvent(0);
+ divider->repaint(true);
+ }
+ handled= true;
+ break;
+ default:
+ break;
+ }
+ return (handled) ? true : QWidget::eventFilter( o, e );
+}
+
+bool KDockSplitter::event( QEvent* e )
+{
+ if ( e->type() == QEvent::LayoutHint ){
+ // change children min/max size. This is needed, otherwise
+ // it is possible the divider get's out of bounds.
+ setupMinMaxSize();
+ resizeEvent(0);
+ }
+ return QWidget::event(e);
+}
+
+QWidget* KDockSplitter::getAnother( QWidget* w ) const
+{
+ return ( w == child0 ) ? child1 : child0;
+}
+
+void KDockSplitter::updateName()
+{
+ if ( !initialised ) return;
+
+ QString new_name = QString( child0->name() ) + "," + child1->name();
+ parentWidget()->setName( new_name.latin1() );
+ parentWidget()->setCaption( child0->caption() + "," + child1->caption() );
+ parentWidget()->repaint( false );
+
+ ((KDockWidget*)parentWidget())->firstName = child0->name();
+ ((KDockWidget*)parentWidget())->lastName = child1->name();
+ ((KDockWidget*)parentWidget())->splitterOrientation = m_orientation;
+
+ QWidget* p = parentWidget()->parentWidget();
+ if ( p && p->inherits("KDockSplitter" ) )
+ ((KDockSplitter*)p)->updateName();
+}
+
+void KDockSplitter::setOpaqueResize(bool b)
+{
+ mOpaqueResize = b;
+}
+
+bool KDockSplitter::opaqueResize() const
+{
+ return mOpaqueResize;
+}
+
+void KDockSplitter::setKeepSize(bool b)
+{
+ mKeepSize = b;
+}
+
+bool KDockSplitter::keepSize() const
+{
+ return mKeepSize;
+}
+
+
+
+/*************************************************************************/
+KDockButton_Private::KDockButton_Private( QWidget *parent, const char * name )
+:QPushButton( parent, name )
+{
+ moveMouse = false;
+ setFocusPolicy( NoFocus );
+}
+
+KDockButton_Private::~KDockButton_Private()
+{
+}
+
+void KDockButton_Private::drawButton( QPainter* p )
+{
+ p->fillRect( 0,0, width(), height(), QBrush(colorGroup().brush(QColorGroup::Background)) );
+ p->drawPixmap( (width() - pixmap()->width()) / 2, (height() - pixmap()->height()) / 2, *pixmap() );
+ if ( moveMouse && !isDown() ){
+ p->setPen( white );
+ p->moveTo( 0, height() - 1 );
+ p->lineTo( 0, 0 );
+ p->lineTo( width() - 1, 0 );
+
+ p->setPen( colorGroup().dark() );
+ p->lineTo( width() - 1, height() - 1 );
+ p->lineTo( 0, height() - 1 );
+ }
+ if ( isOn() || isDown() ){
+ p->setPen( colorGroup().dark() );
+ p->moveTo( 0, height() - 1 );
+ p->lineTo( 0, 0 );
+ p->lineTo( width() - 1, 0 );
+
+ p->setPen( white );
+ p->lineTo( width() - 1, height() - 1 );
+ p->lineTo( 0, height() - 1 );
+ }
+}
+
+void KDockButton_Private::enterEvent( QEvent * )
+{
+ moveMouse = true;
+ repaint();
+}
+
+void KDockButton_Private::leaveEvent( QEvent * )
+{
+ moveMouse = false;
+ repaint();
+}
+
+/*************************************************************************/
+KDockWidgetPrivate::KDockWidgetPrivate()
+ : QObject()
+ ,index(-1)
+ ,splitPosInPercent(50)
+ ,pendingFocusInEvent(false)
+ ,blockHasUndockedSignal(false)
+ ,pendingDtor(false)
+ ,forcedWidth(-1)
+ ,forcedHeight(-1)
+ ,isContainer(false)
+ ,container(0)
+ ,resizePos(0,0)
+ ,resizing(false)
+{
+#ifndef NO_KDE2
+ windowType = NET::Normal;
+#endif
+
+ _parent = 0L;
+ transient = false;
+}
+
+KDockWidgetPrivate::~KDockWidgetPrivate()
+{
+}
+
+void KDockWidgetPrivate::slotFocusEmbeddedWidget(QWidget* w)
+{
+ if (w) {
+ QWidget* embeddedWdg = ((KDockWidget*)w)->getWidget();
+ if (embeddedWdg && ((embeddedWdg->focusPolicy() == QWidget::ClickFocus) || (embeddedWdg->focusPolicy() == QWidget::StrongFocus))) {
+ embeddedWdg->setFocus();
+ }
+ }
+}
+
+#ifndef NO_INCLUDE_MOCFILES // for Qt-only projects, because tmake doesn't take this name
+#include "kdockwidget_private.moc"
+#endif
diff --git a/kdeui/kdockwidget_private.h b/kdeui/kdockwidget_private.h
new file mode 100644
index 000000000..2c6ae8896
--- /dev/null
+++ b/kdeui/kdockwidget_private.h
@@ -0,0 +1,335 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Max Judin <novaprint@mtu-net.ru>
+ Copyright (C) 2005 Dominik Haumann <dhdev@gmx.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+/*
+ IMPORTANT Note: This file compiles also in Qt-only mode by using the NO_KDE2 precompiler definition
+*/
+
+#ifndef KDOCKWIDGET_PRIVATE_H
+#define KDOCKWIDGET_PRIVATE_H
+
+#include <qwidget.h>
+#include <qpushbutton.h>
+
+#ifndef NO_KDE2
+#include <netwm_def.h>
+#endif
+
+class QFrame;
+class KDockContainer;
+
+
+/**
+ * Like QSplitter but specially designed for dockwidgets stuff.
+ * @internal
+ *
+ * @author Max Judin.
+ */
+class KDEUI_EXPORT KDockSplitter : public QWidget
+{
+ // NOTE: in theory the KDEUI_EXPORT above shouldn't be there, but it's needed for kexi,
+ // which copies the whole definition of the class to be able to access separatorPosInPercent etc.
+ // This needs real fixing in KDE4.
+
+ Q_OBJECT
+public:
+ /**
+ * Constructor.
+ * @param parent parent widget
+ * @param name name
+ * @param orient orientation. Either @p Vertical or @p Horizontal
+ * @param pos procentual position of the splitter. Must be int [0...100].
+ */
+ KDockSplitter(QWidget *parent= 0, const char *name= 0, Orientation orient= Vertical, int pos= 50);
+ virtual ~KDockSplitter(){}
+
+ /**
+ * Initialize the splitter. If @p c0 or @p c1 is 0L the child will not
+ * be replaced. So if you want to change @p c1 and not change c0, you'd
+ * call @p activate(0L,new_widget);
+ *
+ * @param c0 the widget on top/left
+ * @param c1 the widget on borrom/right
+ */
+ void activate(QWidget *c0, QWidget *c1 = 0L);
+ /**
+ * Disables the splitter.
+ */
+ void deactivate();
+
+ /**
+ * Return the separator position in percent (%), so the range is [0..100]
+ * @return separator position in percent
+ */
+ int separatorPosInPercent();
+ /**
+ * Set the separator position in percent (%), so the range must be [0..100]
+ * @param percent separator position in percent
+ */
+ void setSeparatorPosInPercent(int percent);
+
+ /**
+ * Return the separator position in the range [0..100000]
+ * To get the separator position in procent (%), call
+ * @p separatorPositionInPercent()!
+ *
+ * @return high resolution separator position in range [0..100000],
+ * where 100000 is 100%.
+ */
+ int separatorPos() const;
+ /**
+ * set separator position.
+ * @param pos the separator position in range [0..100000]. 100000 is 100%.
+ * @param do_resize if this is true, then a resize event is generated.
+ * This may cause the size to change.
+ */
+ void setSeparatorPos(int pos, bool do_resize = true);
+ /**
+ * For usage from outside.
+ * If the splitter is in fixed position when called,
+ * the value of @p pos will be saved and used when the splitter
+ * is restored.
+ * If @p do_resize is true, the size will be changed unless the splitter
+ * is in fixed mode.
+ */
+ // ### please come up with a nicer name
+ void setSeparatorPosX(int pos, bool do_resize=false);
+
+ /**
+ * The eventfilter installed on the @p divider processes
+ * all splitter resizing events.
+ */
+ virtual bool eventFilter(QObject *, QEvent *);
+ virtual bool event( QEvent * );
+
+ /**
+ * @return the top/left child widget.
+ */
+ QWidget* getFirst() const { return child0; }
+ /**
+ * @return the bottom/right child widget.
+ */
+ QWidget* getLast() const { return child1; }
+ /**
+ * If @p w is child0, return child1, otherwise child0.
+ * @return the other child widget
+ */
+ QWidget* getAnother( QWidget* w ) const;
+ void updateName();
+
+ /**
+ * Set opaque flag.
+ * @param b if true, both child widgets are resized immediately,
+ * if false, the widgets only resize on MouseUpEvent.
+ */
+ void setOpaqueResize(bool b=true);
+ bool opaqueResize() const;
+
+ /**
+ * If @p b is true, the splitter will keep its size on resize events.
+ * If no @p KDockContainer is around, always the left child0 will be fixed size.
+ */
+ void setKeepSize(bool b=true);
+ bool keepSize() const;
+
+
+ void setForcedFixedWidth(KDockWidget *dw,int w);
+ void setForcedFixedHeight(KDockWidget *dw,int h);
+ void restoreFromForcedFixedSize(KDockWidget *dw);
+
+ /**
+ * The orientation is either @p Horizontal or @p Vertical.
+ */
+ Orientation orientation(){return m_orientation;}
+
+protected:
+ friend class KDockContainer;
+ /**
+ * Make sure the splitter position is not out of bounds.
+ * @param position the current position
+ * @return a (new) valid splitter position.
+ */
+ int checkValue(int position) const;
+ /**
+ * Make sure the splitter position is not out of bounds. It has
+ * to honor all child widgets' mimimumSize.
+ * @param position current divider position
+ * @param child the overlapping child
+ * @return the (new) splitter position.
+ */
+ int checkValueOverlapped(int position, QWidget* child) const;
+
+ /**
+ * The resize event resizes @p child0, @p child1 and the @p divider.
+ * The new sizes are dependant of
+ * - whether @p child0 or @p child1 is a KDockContainer
+ * - the current mode which may be
+ * - Closed
+ * - Overlapped (opened)
+ * - Nonoverlap (opened)
+ * .
+ * .
+ * So there are 3*2=6 different modes we have to face.
+ * @param ev the resize Event. If @p ev=0L the user changed
+ * the mode (for example from overlap to nonoverlap mode).
+ */
+ virtual void resizeEvent(QResizeEvent *ev);
+
+/*
+protected slots:
+ void delayedResize();*/
+
+private:
+ /**
+ * updates the minimum and maximun sizes for the KDockSplitter.
+ * The sizes depend on the minimum and maximum sizes of the two child
+ * widgets.
+ */
+ void setupMinMaxSize();
+ /**
+ * child0 and child1 contain the embeded widgets. They are always valid
+ * so no need to make pointer checks.
+ * child[01]->getWidget() may be KDockContainer.
+ */
+ QWidget *child0, *child1;
+ Orientation m_orientation;
+ /**
+ * If initialised is true, the divider!=0L. If false, the divider==0L!
+ */
+ bool initialised;
+ /**
+ * The splitter controller which is between child0 and child1.
+ * Its size is 4 pixel.
+ */
+ QFrame* divider;
+ /**
+ * @p xpos and @p savedXPos represent the current divider position.
+ * If the orientation is Horizontal @p xpos actually is "ypos". So
+ * do not get confused only because of the 'x'.
+ *
+ * xpos and savedXPos are internally high resolution. So *not* 0..100%
+ * but 0..100000=100%. This fixes rounding bugs. In fact, this should
+ * be a double, but due to binary compatibility we can not change this
+ * as we would have to change it in all kdockwidgets.
+ */
+ int xpos, savedXPos;
+ bool mOpaqueResize, mKeepSize;
+ int fixedWidth0,fixedWidth1;
+ int fixedHeight0,fixedHeight1;
+ bool m_dontRecalc;
+ /**
+ * resolution factor, 0 = 0%, 100000=100%
+ */
+ static const int factor = 100000;
+};
+
+/**
+ * A mini-button usually placed in the dockpanel.
+ * @internal (but used by kmdi/dockcontainer.cpp)
+ *
+ * @author Max Judin.
+*/
+class KDEUI_EXPORT KDockButton_Private : public QPushButton
+{
+ Q_OBJECT
+public:
+ KDockButton_Private( QWidget *parent=0, const char *name=0 );
+ ~KDockButton_Private();
+
+protected:
+ virtual void drawButton( QPainter * );
+ virtual void enterEvent( QEvent * );
+ virtual void leaveEvent( QEvent * );
+
+private:
+ bool moveMouse;
+};
+
+/**
+ * resizing enum
+ **/
+
+
+
+/**
+ * additional KDockWidget stuff (private)
+*/
+class KDockWidgetPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ KDockWidgetPrivate();
+ ~KDockWidgetPrivate();
+
+public slots:
+ /**
+ * Especially used for Tab page docking. Switching the pages requires additional setFocus() for the embedded widget.
+ */
+ void slotFocusEmbeddedWidget(QWidget* w = 0L);
+
+public:
+ enum KDockWidgetResize
+{ResizeLeft,ResizeTop,ResizeRight,ResizeBottom,ResizeBottomLeft,ResizeTopLeft,ResizeBottomRight,ResizeTopRight};
+
+ int index;
+ int splitPosInPercent;
+ bool pendingFocusInEvent;
+ bool blockHasUndockedSignal;
+ bool pendingDtor;
+ int forcedWidth;
+ int forcedHeight;
+ bool isContainer;
+
+#ifndef NO_KDE2
+ NET::WindowType windowType;
+#endif
+
+ QWidget *_parent;
+ bool transient;
+
+ QGuardedPtr<QWidget> container;
+
+ QPoint resizePos;
+ bool resizing;
+ KDockWidgetResize resizeMode;
+};
+
+class KDockWidgetHeaderPrivate
+ : public QObject
+{
+public:
+ KDockWidgetHeaderPrivate( QObject* parent )
+ : QObject( parent )
+ {
+ forceCloseButtonHidden=false;
+ toDesktopButton = 0;
+ showToDesktopButton = true;
+ topLevel = false;
+ dummy=0;
+ }
+ KDockButton_Private* toDesktopButton;
+
+ bool showToDesktopButton;
+ bool topLevel;
+ QPtrList<KDockButton_Private> btns;
+ bool forceCloseButtonHidden;
+ QWidget *dummy;
+};
+
+#endif
diff --git a/kdeui/kdockwindow.h b/kdeui/kdockwindow.h
new file mode 100644
index 000000000..93d550a75
--- /dev/null
+++ b/kdeui/kdockwindow.h
@@ -0,0 +1,41 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Matthias Ettrich <ettrich@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef KDOCKWINDOW_H
+#define KDOCKWINDOW_H
+
+#include <qlabel.h>
+#include <ksystemtray.h>
+
+#ifndef KDE_NO_COMPAT
+/**
+ * \brief Obsolete system tray support
+ *
+ * @deprecated
+ * This class is obsolete, it is provided for compatibility only.
+ * Use KSystemTray instead.
+ */
+class KDE_DEPRECATED KDockWindow : public KSystemTray
+{
+ Q_OBJECT
+public:
+ KDockWindow( QWidget* parent = 0, const char* name = 0 )
+ : KSystemTray( parent, name ) {}
+ ~KDockWindow() {}
+};
+#endif
+#endif
diff --git a/kdeui/kdualcolorbtn.h b/kdeui/kdualcolorbtn.h
new file mode 100644
index 000000000..74f537688
--- /dev/null
+++ b/kdeui/kdualcolorbtn.h
@@ -0,0 +1,6 @@
+#ifndef KDE_NO_COMPAT
+#ifndef __KDUALCOLORBTN_H_
+#define __KDUALCOLORBTN_H_
+#include <kdualcolorbutton.h>
+#endif
+#endif
diff --git a/kdeui/kdualcolorbutton.cpp b/kdeui/kdualcolorbutton.cpp
new file mode 100644
index 000000000..24a4e9e0d
--- /dev/null
+++ b/kdeui/kdualcolorbutton.cpp
@@ -0,0 +1,283 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Daniel M. Duley <mosfet@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kdualcolorbutton.h"
+#include "kcolordialog.h"
+#include "kcolordrag.h"
+#include "dcolorarrow.xbm"
+#include "dcolorreset.xpm"
+#include <kglobalsettings.h>
+#include <qpainter.h>
+#include <qbitmap.h>
+#include <qdrawutil.h>
+
+class KDualColorButton::KDualColorPrivate
+{
+public:
+ QWidget* dialogParent;
+};
+
+KDualColorButton::KDualColorButton(QWidget *parent, const char *name, QWidget* dialogParent)
+ : QWidget(parent, name),
+ d (new KDualColorPrivate)
+{
+ if (!dialogParent && parent) {
+ d->dialogParent = parent;
+ } else {
+ d->dialogParent = dialogParent;
+ }
+
+ arrowBitmap = new QBitmap(dcolorarrow_width, dcolorarrow_height,
+ (const unsigned char *)dcolorarrow_bits, true);
+ arrowBitmap->setMask(*arrowBitmap); // heh
+ resetPixmap = new QPixmap((const char **)dcolorreset_xpm);
+ fg = QBrush(Qt::black, SolidPattern);
+ bg = QBrush(Qt::white, SolidPattern);
+ curColor = Foreground;
+ dragFlag = false;
+ miniCtlFlag = false;
+ if(sizeHint().isValid())
+ setMinimumSize(sizeHint());
+ setAcceptDrops(true);
+}
+
+KDualColorButton::KDualColorButton(const QColor &fgColor, const QColor &bgColor,
+ QWidget *parent, const char *name, QWidget* dialogParent)
+ : QWidget(parent, name),
+ d (new KDualColorPrivate)
+{
+ d->dialogParent = dialogParent;
+
+ arrowBitmap = new QBitmap(dcolorarrow_width, dcolorarrow_height,
+ (const unsigned char *)dcolorarrow_bits, true);
+ arrowBitmap->setMask(*arrowBitmap);
+ resetPixmap = new QPixmap((const char **)dcolorreset_xpm);
+ fg = QBrush(fgColor, SolidPattern);
+ bg = QBrush(bgColor, SolidPattern);
+ curColor = Foreground;
+ dragFlag = false;
+ miniCtlFlag = false;
+ if(sizeHint().isValid())
+ setMinimumSize(sizeHint());
+ setAcceptDrops(true);
+}
+
+KDualColorButton::~KDualColorButton()
+{
+ delete d;
+ delete arrowBitmap;
+ delete resetPixmap;
+}
+
+QColor KDualColorButton::foreground() const
+{
+ return fg.color();
+}
+
+QColor KDualColorButton::background() const
+{
+ return bg.color();
+}
+
+KDualColorButton::DualColor KDualColorButton::current() const
+{
+ return curColor;
+}
+
+QColor KDualColorButton::currentColor() const
+{
+ return (curColor == Background ? bg.color() : fg.color());
+}
+
+QSize KDualColorButton::sizeHint() const
+{
+ return QSize(34, 34);
+}
+
+void KDualColorButton::setForeground(const QColor &c)
+{
+ fg = QBrush(c, SolidPattern);
+ repaint(false);
+
+ emit fgChanged(fg.color());
+}
+
+void KDualColorButton::setBackground(const QColor &c)
+{
+ bg = QBrush(c, SolidPattern);
+ repaint(false);
+
+ emit bgChanged(bg.color());
+}
+
+void KDualColorButton::setCurrentColor(const QColor &c)
+{
+ if(curColor == Background)
+ bg = QBrush(c, SolidPattern);
+ else
+ fg = QBrush(c, SolidPattern);
+ repaint(false);
+}
+
+void KDualColorButton::setCurrent(DualColor s)
+{
+ curColor = s;
+ repaint(false);
+}
+
+void KDualColorButton::metrics(QRect &fgRect, QRect &bgRect)
+{
+ fgRect = QRect(0, 0, width()-14, height()-14);
+ bgRect = QRect(14, 14, width()-14, height()-14);
+}
+
+void KDualColorButton::paintEvent(QPaintEvent *)
+{
+ QRect fgRect, bgRect;
+ QPainter p(this);
+
+ metrics(fgRect, bgRect);
+ QBrush defBrush = colorGroup().brush(QColorGroup::Button);
+
+ qDrawShadeRect(&p, bgRect, colorGroup(), curColor == Background, 2, 0,
+ isEnabled() ? &bg : &defBrush);
+ qDrawShadeRect(&p, fgRect, colorGroup(), curColor == Foreground, 2, 0,
+ isEnabled() ? &fg : &defBrush);
+ p.setPen(colorGroup().shadow());
+ p.drawPixmap(fgRect.right()+2, 0, *arrowBitmap);
+ p.drawPixmap(0, fgRect.bottom()+2, *resetPixmap);
+
+}
+
+void KDualColorButton::dragEnterEvent(QDragEnterEvent *ev)
+{
+ ev->accept(isEnabled() && KColorDrag::canDecode(ev));
+}
+
+void KDualColorButton::dropEvent(QDropEvent *ev)
+{
+ QColor c;
+ if(KColorDrag::decode(ev, c)){
+ if(curColor == Foreground){
+ fg.setColor(c);
+ emit fgChanged(c);
+ }
+ else{
+ bg.setColor(c);
+ emit(bgChanged(c));
+ }
+ repaint(false);
+ }
+}
+
+void KDualColorButton::mousePressEvent(QMouseEvent *ev)
+{
+ QRect fgRect, bgRect;
+ metrics(fgRect, bgRect);
+ mPos = ev->pos();
+ tmpColor = curColor;
+ dragFlag = false;
+ if(fgRect.contains(mPos)){
+ curColor = Foreground;
+ miniCtlFlag = false;
+ }
+ else if(bgRect.contains(mPos)){
+ curColor = Background;
+ miniCtlFlag = false;
+ }
+ else if(ev->pos().x() > fgRect.width()){
+ // We handle the swap and reset controls as soon as the mouse is
+ // is pressed and ignore further events on this click (mosfet).
+ QBrush c = fg;
+ fg = bg;
+ bg = c;
+ emit fgChanged(fg.color());
+ emit bgChanged(bg.color());
+ miniCtlFlag = true;
+ }
+ else if(ev->pos().x() < bgRect.x()){
+ fg.setColor(Qt::black);
+ bg.setColor(Qt::white);
+ emit fgChanged(fg.color());
+ emit bgChanged(bg.color());
+ miniCtlFlag = true;
+ }
+ repaint(false);
+}
+
+
+void KDualColorButton::mouseMoveEvent(QMouseEvent *ev)
+{
+ if(!miniCtlFlag){
+ int delay = KGlobalSettings::dndEventDelay();
+ if(ev->x() >= mPos.x()+delay || ev->x() <= mPos.x()-delay ||
+ ev->y() >= mPos.y()+delay || ev->y() <= mPos.y()-delay) {
+ KColorDrag *d = new KColorDrag( curColor == Foreground ?
+ fg.color() : bg.color(),
+ this);
+ d->dragCopy();
+ dragFlag = true;
+ }
+ }
+}
+
+void KDualColorButton::mouseReleaseEvent(QMouseEvent *ev)
+{
+ if(!miniCtlFlag){
+ QRect fgRect, bgRect;
+
+ metrics(fgRect, bgRect);
+ if(dragFlag)
+ curColor = tmpColor;
+ else if(fgRect.contains(ev->pos()) && curColor == Foreground){
+ if(tmpColor == Background){
+ curColor = Foreground;
+ emit currentChanged(Foreground);
+ }
+ else{
+ QColor newColor = fg.color();
+ if(KColorDialog::getColor(newColor, d->dialogParent) != QDialog::Rejected){
+ fg.setColor(newColor);
+ emit fgChanged(newColor);
+ }
+ }
+ }
+ else if(bgRect.contains(ev->pos()) && curColor == Background){
+ if(tmpColor == Foreground){
+ curColor = Background;
+ emit currentChanged(Background);
+ }
+ else{
+ QColor newColor = bg.color();
+ if(KColorDialog::getColor(newColor, d->dialogParent) != QDialog::Rejected){
+ bg.setColor(newColor);
+ emit bgChanged(newColor);
+ }
+ }
+ }
+ repaint(false);
+ dragFlag = false;
+ }
+ else
+ miniCtlFlag = false;
+}
+
+void KDualColorButton::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "kdualcolorbutton.moc"
diff --git a/kdeui/kdualcolorbutton.h b/kdeui/kdualcolorbutton.h
new file mode 100644
index 000000000..eb4a71ab2
--- /dev/null
+++ b/kdeui/kdualcolorbutton.h
@@ -0,0 +1,159 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Daniel M. Duley <mosfet@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef __KDUALCOLORBTN_H
+#define __KDUALCOLORBTN_H
+
+class QBitmap;
+#include <qbrush.h>
+#include <qwidget.h>
+
+#include <kdelibs_export.h>
+
+/**
+ * @short A widget for selecting two related colors.
+ *
+ * KDualColorButton allows the user to select two cascaded colors (usually a
+ * foreground and background color). Other features include drag and drop
+ * from other KDE color widgets, a reset to black and white control, and a
+ * swap colors control.
+ *
+ * When the user clicks on the foreground or background rectangle the
+ * rectangle is first sunken and the currentChanged() signal is emitted.
+ * Further clicks will present a color dialog and emit either the fgChanged()
+ * or bgChanged() if a new color is selected.
+ *
+ * Note: With drag and drop when dropping a color the current selected color
+ * will be set, while when dragging a color it will use whatever color
+ * rectangle the mouse was pressed inside.
+ *
+ * \image html kdualcolorbutton.png "KDE Dual Color Button"
+ *
+ * @author Daniel M. Duley <mosfet@kde.org>
+ */
+class KDEUI_EXPORT KDualColorButton : public QWidget
+{
+ Q_OBJECT
+ Q_ENUMS( DualColor )
+ Q_PROPERTY( QColor foreground READ foreground WRITE setForeground )
+ Q_PROPERTY( QColor background READ background WRITE setBackground )
+ Q_PROPERTY( QColor currentColor READ currentColor WRITE setCurrentColor STORED false DESIGNABLE false )
+ Q_PROPERTY( DualColor current READ current WRITE setCurrent )
+
+public:
+
+ enum DualColor { Foreground, Background };
+ /**
+ * Constructs a new KDualColorButton using the default black and white
+ * colors.
+ *
+ * As of KDE 3.5.1, sets the dialog parent to the same as "parent" if that
+ * argument is non-null and the dialogParent argument is null.
+ */
+ KDualColorButton(QWidget *parent=0, const char *name=0, QWidget* dialogParent=0);
+
+ /**
+ * Constructs a new KDualColorButton with the supplied foreground and
+ * background colors.
+ */
+ KDualColorButton(const QColor &fgColor, const QColor &bgColor,
+ QWidget *parent=0, const char *name=0, QWidget* dialogParent=0);
+
+ ~KDualColorButton();
+ /**
+ * Returns the current foreground color.
+ */
+ QColor foreground() const;
+ /**
+ * Returns the current background color.
+ */
+ QColor background() const;
+ /**
+ * Returns the current color item selected by the user.
+ */
+ DualColor current() const;
+ /**
+ * Returns the color of the selected item.
+ */
+ QColor currentColor() const;
+ /**
+ * Returns the minimum size needed to display the widget and all its
+ * controls.
+ */
+ virtual QSize sizeHint() const;
+public slots:
+ /**
+ * Sets the foreground color.
+ */
+ void setForeground(const QColor &c);
+ /**
+ * Sets the background color.
+ */
+ void setBackground(const QColor &c);
+ /**
+ * Sets the current selected color item.
+ */
+ void setCurrent(DualColor s);
+ /**
+ * Sets the color of the selected item.
+ */
+ void setCurrentColor(const QColor &c);
+signals:
+ /**
+ * Emitted when the foreground color is changed.
+ */
+ void fgChanged(const QColor &c);
+ /**
+ * Emitted when the background color is changed.
+ */
+ void bgChanged(const QColor &c);
+ /**
+ * Emitted when the user changes the current color selection.
+ */
+ void currentChanged(KDualColorButton::DualColor s);
+protected:
+ /**
+ * Sets the supplied rectangles to the proper size and position for the
+ * current widget size. You can reimplement this to change the layout
+ * of the widget. Restrictions are that the swap control will always
+ * be at the top right, the reset control will always be at the bottom
+ * left, and you must leave at least a 14x14 space in those corners.
+ */
+ virtual void metrics(QRect &fgRect, QRect &bgRect);
+ virtual void paintEvent(QPaintEvent *ev);
+ virtual void mousePressEvent(QMouseEvent *ev);
+ virtual void mouseMoveEvent(QMouseEvent *ev);
+ virtual void mouseReleaseEvent(QMouseEvent *ev);
+ // Dnd
+ virtual void dragEnterEvent(QDragEnterEvent *ev);
+ virtual void dropEvent(QDropEvent *ev);
+private:
+ QBitmap *arrowBitmap;
+ QPixmap *resetPixmap;
+ QBrush fg, bg;
+ QPoint mPos;
+ bool dragFlag, miniCtlFlag;
+ DualColor curColor, tmpColor;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KDualColorPrivate;
+ KDualColorPrivate *d;
+};
+
+#endif
diff --git a/kdeui/keditcl.h b/kdeui/keditcl.h
new file mode 100644
index 000000000..b05148fb0
--- /dev/null
+++ b/kdeui/keditcl.h
@@ -0,0 +1,436 @@
+/* This file is part of the KDE libraries
+
+ Copyright (C) 1996 Bernd Johannes Wuebben <wuebben@math.cornell.edu>
+ Copyright (C) 2000 Waldo Bastian <bastian@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef __KEDITCL_H__
+#define __KEDITCL_H__
+
+#include <qmultilineedit.h>
+#include <qstring.h>
+#include <kdialogbase.h>
+
+class QDropEvent;
+class QPushButton;
+class QCheckBox;
+class QRadioButton;
+class QTextStream;
+class KHistoryCombo;
+class KIntNumInput;
+class QVButtonGroup;
+
+class KDEUI_EXPORT KEdGotoLine : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ KEdGotoLine( QWidget *parent=0, const char *name=0, bool modal=true );
+ int getLineNumber();
+
+public slots:
+ void selected( int );
+
+private:
+ KIntNumInput *lineNum;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KEdGotoLinePrivate;
+ KEdGotoLinePrivate *d;
+};
+
+///
+class KDEUI_EXPORT KEdFind : public KDialogBase
+{
+ Q_OBJECT
+ Q_PROPERTY( QString text READ getText WRITE setText )
+ Q_PROPERTY( bool caseSensitivity READ case_sensitive WRITE setCaseSensitive )
+ Q_PROPERTY( bool direction READ get_direction WRITE setDirection )
+public:
+
+ KEdFind( QWidget *parent = 0, const char *name=0, bool modal=true);
+ ~KEdFind();
+
+ QString getText() const;
+ void setText(QString string);
+ void setCaseSensitive( bool b );
+ bool case_sensitive() const;
+ void setDirection( bool b );
+ bool get_direction() const;
+
+ /**
+ * @returns the combobox containing the history of searches. Can be used
+ * to save and restore the history.
+ */
+ KHistoryCombo *searchCombo() const;
+
+protected slots:
+ void slotCancel( void );
+ void slotUser1( void );
+ void textSearchChanged ( const QString & );
+
+protected:
+ QVButtonGroup* group;
+
+private:
+ QCheckBox *sensitive;
+ QCheckBox *direction;
+
+ virtual void done(int i ) { KDialogBase::done(i); }
+
+signals:
+
+ void search();
+ void done();
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KEdFindPrivate;
+ KEdFindPrivate *d;
+};
+
+///
+class KDEUI_EXPORT KEdReplace : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+
+ KEdReplace ( QWidget *parent = 0, const char *name=0, bool modal=true );
+ ~KEdReplace();
+
+ QString getText();
+ QString getReplaceText();
+ void setText(QString);
+
+ /**
+ * @returns the combobox containing the history of searches. Can be used
+ * to save and restore the history.
+ */
+ KHistoryCombo *searchCombo() const;
+
+ /**
+ * @returns the combobox containing the history of replaces. Can be used
+ * to save and restore the history.
+ */
+ KHistoryCombo *replaceCombo() const;
+
+ bool case_sensitive();
+ bool get_direction();
+
+protected slots:
+ void slotCancel( void );
+ void slotClose( void );
+ void slotUser1( void );
+ void slotUser2( void );
+ void slotUser3( void );
+ void textSearchChanged ( const QString & );
+
+private:
+ QCheckBox *sensitive;
+ QCheckBox *direction;
+
+ virtual void done(int i ) { KDialogBase::done(i); }
+
+signals:
+ void replace();
+ void find();
+ void replaceAll();
+ void done();
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KEdReplacePrivate;
+ KEdReplacePrivate *d;
+};
+
+
+/**
+ * A simple text editor for the %KDE project.
+ * @deprecated Use KTextEditor::Editor or KTextEdit instead.
+ *
+ * @author Bernd Johannes Wuebben <wuebben@math.cornell.edu>, Waldo Bastian <bastian@kde.org>
+ **/
+
+class KDEUI_EXPORT_DEPRECATED KEdit : public QMultiLineEdit
+{
+ Q_OBJECT
+
+public:
+ /**
+ * The usual constructor.
+ **/
+ KEdit (QWidget *_parent=NULL, const char *name=NULL);
+
+ ~KEdit();
+
+ /**
+ * Search directions.
+ * @internal
+ **/
+ enum { NONE,
+ FORWARD,
+ BACKWARD };
+ /**
+ * Insert text from the text stream into the edit widget.
+ **/
+ void insertText(QTextStream *);
+
+ /**
+ * Save text from the edit widget to a text stream.
+ * If @p softWrap is false soft line wrappings are replaced with line-feeds
+ * If @p softWrap is true soft line wrappings are ignored.
+ * @since 3.1
+ **/
+ void saveText(QTextStream *, bool softWrap);
+ void saveText(QTextStream *); // KDE 4.0: remove
+
+ /**
+ * Let the user select a font and set the font of the textwidget to that
+ * selected font.
+ **/
+ void selectFont();
+
+ /**
+ * Present a search dialog to the user
+ **/
+ void search();
+
+ /**
+ * Repeat the last search specified on the search dialog.
+ *
+ * If the user hasn't searched for anything until now, this method
+ * will simply return without doing anything.
+ *
+ * @return @p true if a search was done. @p false if no search was done.
+ **/
+ bool repeatSearch();
+
+ /**
+ * Present a Search and Replace Dialog to the user.
+ **/
+ void replace();
+
+ /**
+ * Present a "Goto Line" dialog to the user.
+ */
+ void doGotoLine();
+
+ /**
+ * Clean up redundant whitespace from selected text.
+ */
+ void cleanWhiteSpace();
+
+ /**
+ * Install a context menu for KEdit.
+ *
+ * The Popup Menu will be activated on a right mouse button press event.
+ */
+ void installRBPopup( QPopupMenu* );
+
+ /**
+ * Retrieve the current line number.
+ *
+ * The current line is the line the cursor is on.
+ **/
+ int currentLine();
+
+ /**
+ * Retrieve the actual column number the cursor is on.
+ *
+ * This call differs
+ * from QMultiLineEdit::getCursorPosition() in that it returns the actual cursor
+ * position and not the character position. Use currentLine() and currentColumn()
+ * if you want to display the current line or column in the status bar for
+ * example.
+ */
+ int currentColumn();
+
+
+ /**
+ * Start spellchecking mode.
+ */
+ void spellcheck_start();
+
+ /**
+ * Exit spellchecking mode.
+ */
+ void spellcheck_stop();
+
+ /**
+ * Allow the user to toggle between insert mode and overwrite mode with
+ * the "Insert" key. See also toggle_overwrite_signal();
+ *
+ * The default is false: the user can not toggle.
+ */
+ void setOverwriteEnabled(bool b);
+
+ QString selectWordUnderCursor();
+
+ /// @since 3.3
+ QPopupMenu *createPopupMenu( const QPoint& pos );
+
+ void setAutoUpdate(bool b);
+
+signals:
+ /** This signal is emitted if the user dropped a URL over the text editor
+ * QMultiLineEdit widget.
+ *
+ * Note that the user can drop also Text on it, but
+ * this is already handled internally by QMultiLineEdit.
+ */
+ void gotUrlDrop(QDropEvent* e);
+
+ /** This signal is emitted whenever the cursor position changes.
+ *
+ * Use this in conjunction with currentLine(), currentColumn()
+ * if you need to know the cursor position.
+ */
+ void CursorPositionChanged();
+
+ /**
+ * This signal is emitted if the user toggles from insert to overwrite mode
+ * or vice versa.
+ *
+ * The user can do so by pressing the "Insert" button on a PC keyboard.
+ *
+ * This feature must be activated by calling setOverwriteEnabled(true)
+ * first.
+ */
+ void toggle_overwrite_signal();
+
+public slots:
+ /**
+ * @internal
+ **/
+ void corrected (const QString &originalword, const QString &newword, unsigned int pos);
+ /**
+ * @internal
+ **/
+ void misspelling (const QString &word, const QStringList &, unsigned int pos);
+private slots:
+
+ /**
+ * @internal
+ * Called from search dialog.
+ **/
+ void search_slot();
+
+ /**
+ * @internal
+ **/
+ void searchdone_slot();
+
+ /**
+ * @internal
+ **/
+ void replace_slot();
+
+ /**
+ * @internal
+ **/
+ void replace_all_slot();
+
+ /**
+ * @internal
+ **/
+ void replace_search_slot();
+
+ /**
+ * @internal
+ **/
+ void replacedone_slot();
+
+ /**
+ * Cursor moved...
+ */
+ void slotCursorPositionChanged();
+
+protected:
+ void computePosition();
+ int doSearch(QString s_pattern, bool case_sensitive,
+ bool regex, bool forward,int line, int col);
+
+ int doReplace(QString s_pattern, bool case_sensitive,
+ bool regex, bool forward,int line, int col,bool replace);
+
+ /**
+ * Sets line and col to the position pos, considering word wrap.
+ **/
+ void posToRowCol(unsigned int pos, unsigned int &line, unsigned int &col);
+
+ /**
+ * Reimplemented for internal reasons, the API is not affected.
+ */
+ virtual void create( WId = 0, bool initializeWindow = true,
+ bool destroyOldWindow = true );
+
+ /**
+ * Reimplemented for internal reasons, the API is not affected.
+ */
+ virtual void ensureCursorVisible();
+ virtual void setCursor( const QCursor & );
+ virtual void viewportPaintEvent( QPaintEvent* );
+
+protected:
+
+ void keyPressEvent ( QKeyEvent * );
+
+ // DnD interface
+ void dragMoveEvent(QDragMoveEvent* e);
+ void dragEnterEvent(QDragEnterEvent* e);
+ void dropEvent(QDropEvent* e);
+ void contentsDragMoveEvent(QDragMoveEvent* e);
+ void contentsDragEnterEvent(QDragEnterEvent* e);
+ void contentsDropEvent(QDropEvent* e);
+
+private:
+ QTimer* repaintTimer;
+
+ QString killbufferstring;
+ QWidget *parent;
+ KEdFind *srchdialog;
+ KEdReplace *replace_dialog;
+ KEdGotoLine *gotodialog;
+
+ QString pattern;
+
+ bool can_replace;
+ bool killing;
+ bool killtrue;
+ bool lastwasanewline;
+ bool saved_readonlystate;
+ int last_search;
+ int last_replace;
+ int replace_all_line;
+ int replace_all_col;
+
+ int line_pos, col_pos;
+ bool fill_column_is_set;
+ bool word_wrap_is_set;
+ int fill_column_value;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KEditPrivate;
+ KEditPrivate *d;
+};
+
+#endif
diff --git a/kdeui/keditcl1.cpp b/kdeui/keditcl1.cpp
new file mode 100644
index 000000000..56ab68c60
--- /dev/null
+++ b/kdeui/keditcl1.cpp
@@ -0,0 +1,718 @@
+/* This file is part of the KDE libraries
+
+ Copyright (C) 1997 Bernd Johannes Wuebben <wuebben@math.cornell.edu>
+ Copyright (C) 2000 Waldo Bastian <bastian@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qdragobject.h>
+#include <qpopupmenu.h>
+#include <qtextstream.h>
+#include <qtimer.h>
+
+#include <kapplication.h>
+#include <kcursor.h>
+#include <kdebug.h>
+#include <kcmenumngr.h>
+#include <kfontdialog.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kstdaccel.h>
+#include <kurldrag.h>
+
+#include "keditcl.h"
+#include "keditcl.moc"
+
+class KEdit::KEditPrivate
+{
+public:
+ bool overwriteEnabled:1;
+ bool posDirty:1;
+ bool autoUpdate:1;
+};
+
+
+KEdit::KEdit(QWidget *_parent, const char *name)
+ : QMultiLineEdit(_parent, name)
+{
+ d = new KEditPrivate;
+ d->overwriteEnabled = false;
+ d->posDirty = true;
+ d->autoUpdate = true;
+
+ parent = _parent;
+
+ // set some defaults
+
+ line_pos = col_pos = 0;
+
+ srchdialog = NULL;
+ replace_dialog= NULL;
+ gotodialog = NULL;
+
+ setAcceptDrops(true);
+ KCursor::setAutoHideCursor( this, true );
+
+ connect(this, SIGNAL(cursorPositionChanged(int,int)),
+ this, SLOT(slotCursorPositionChanged()));
+}
+
+
+KEdit::~KEdit()
+{
+ delete d;
+}
+
+void
+KEdit::setAutoUpdate(bool b)
+{
+ d->autoUpdate = b;
+}
+
+void
+KEdit::insertText(QTextStream *stream)
+{
+// setAutoUpdate(false);
+ int line, col;
+ getCursorPosition(&line, &col);
+ int saveline = line;
+ int savecol = col;
+ QString textLine;
+
+ // MS: Patch by Martin Schenk <martin@schenk.com>
+ // MS: disable UNDO, or QMultiLineEdit remembers every textLine !!!
+ // memory usage is:
+ // textLine: 2*size rounded up to nearest power of 2 (520Kb -> 1024Kb)
+ // widget: about (2*size + 60bytes*lines)
+ // -> without disabling undo, it often needs almost 8*size
+ int oldUndoDepth = undoDepth();
+ setUndoDepth( 0 ); // ### -1?
+
+ // MS: read everything at once if file <= 1MB,
+ // else read in 5000-line chunks to keep memory usage acceptable.
+ QIODevice *dev=stream->device();
+ if (dev && dev->size()>(1024*1024)) {
+ while(1) {
+ int i;
+ textLine="";
+ for (i=0; i<5000; i++) {
+ QString line=stream->readLine();
+ if (line.isNull()) break; // EOF
+ textLine+=line+'\n';
+ }
+ insertAt(textLine, line, col);
+ line+=i; col=0;
+ if (i!=5000) break;
+ }
+ }
+ else {
+ textLine = stream->read(); // Read all !
+ insertAt( textLine, line, col);
+ }
+ setUndoDepth( oldUndoDepth );
+
+ setCursorPosition(saveline, savecol);
+// setAutoUpdate(true);
+
+// repaint();
+
+ setModified(true);
+ setFocus();
+
+ // Bernd: Please don't leave debug message like that lying around
+ // they cause ENORMOUSE performance hits. Once upon a day
+ // kedit used to be really really fast using memmap etc .....
+ // oh well ....
+
+ // QString str = text();
+ // for (int i = 0; i < (int) str.length(); i++)
+ // printf("KEdit: U+%04X\n", str[i].unicode());
+
+}
+
+void
+KEdit::cleanWhiteSpace()
+{
+ d->autoUpdate = false;
+ if (!hasMarkedText())
+ selectAll();
+ QString oldText = markedText();
+ QString newText;
+ QStringList lines = QStringList::split('\n', oldText, true);
+ bool addSpace = false;
+ bool firstLine = true;
+ QChar lastChar = oldText[oldText.length()-1];
+ QChar firstChar = oldText[0];
+ for(QStringList::Iterator it = lines.begin();
+ it != lines.end();)
+ {
+ QString line = (*it).simplifyWhiteSpace();
+ if (line.isEmpty())
+ {
+ if (addSpace)
+ newText += QString::fromLatin1("\n\n");
+ if (firstLine)
+ {
+ if (firstChar.isSpace())
+ newText += '\n';
+ firstLine = false;
+ }
+ addSpace = false;
+ }
+ else
+ {
+ if (addSpace)
+ newText += ' ';
+ if (firstLine)
+ {
+ if (firstChar.isSpace())
+ newText += ' ';
+ firstLine = false;
+ }
+ newText += line;
+ addSpace = true;
+ }
+ it = lines.remove(it);
+ }
+ if (addSpace)
+ {
+ if (lastChar == '\n')
+ newText += '\n';
+ else if (lastChar.isSpace())
+ newText += ' ';
+ }
+
+ if (oldText == newText)
+ {
+ deselect();
+ d->autoUpdate = true;
+ repaint();
+ return;
+ }
+ if (wordWrap() == NoWrap)
+ {
+ // If wordwrap is off, we have to do some line-wrapping ourselves now
+ // We use another QMultiLineEdit for this, so that we get nice undo
+ // behavior.
+ QMultiLineEdit *we = new QMultiLineEdit();
+ we->setWordWrap(FixedColumnWidth);
+ we->setWrapColumnOrWidth(78);
+ we->setText(newText);
+ newText = QString::null;
+ for(int i = 0; i < we->numLines(); i++)
+ {
+ QString line = we->textLine(i);
+ if (line.right(1) != "\n")
+ line += '\n';
+ newText += line;
+ }
+ delete we;
+ }
+
+ insert(newText);
+ d->autoUpdate = true;
+ repaint();
+
+ setModified(true);
+ setFocus();
+}
+
+
+void
+KEdit::saveText(QTextStream *stream)
+{
+ saveText(stream, false);
+}
+
+void
+KEdit::saveText(QTextStream *stream, bool softWrap)
+{
+ int line_count = numLines()-1;
+ if (line_count < 0)
+ return;
+
+ if (softWrap || (wordWrap() == NoWrap))
+ {
+ for(int i = 0; i < line_count; i++)
+ {
+ (*stream) << textLine(i) << '\n';
+ }
+ (*stream) << textLine(line_count);
+ }
+ else
+ {
+ for(int i = 0; i <= line_count; i++)
+ {
+ int lines_in_parag = linesOfParagraph(i);
+ if (lines_in_parag == 1)
+ {
+ (*stream) << textLine(i);
+ }
+ else
+ {
+ QString parag_text = textLine(i);
+ int pos = 0;
+ int first_pos = 0;
+ int current_line = 0;
+ while(true) {
+ while(lineOfChar(i, pos) == current_line) pos++;
+ (*stream) << parag_text.mid(first_pos, pos - first_pos - 1) << '\n';
+ current_line++;
+ first_pos = pos;
+ if (current_line+1 == lines_in_parag)
+ {
+ // Last line
+ (*stream) << parag_text.mid(pos);
+ break;
+ }
+ }
+ }
+ if (i < line_count)
+ (*stream) << '\n';
+ }
+ }
+}
+
+int KEdit::currentLine(){
+
+ computePosition();
+ return line_pos;
+
+}
+
+int KEdit::currentColumn(){
+
+ computePosition();
+ return col_pos;
+}
+
+void KEdit::slotCursorPositionChanged()
+{
+ d->posDirty = true;
+ emit CursorPositionChanged();
+}
+
+void KEdit::computePosition()
+{
+ if (!d->posDirty) return;
+ d->posDirty = false;
+
+ int line, col;
+
+ getCursorPosition(&line,&col);
+
+ // line is expressed in paragraphs, we now need to convert to lines
+ line_pos = 0;
+ if (wordWrap() == NoWrap)
+ {
+ line_pos = line;
+ }
+ else
+ {
+ for(int i = 0; i < line; i++)
+ line_pos += linesOfParagraph(i);
+ }
+
+ int line_offset = lineOfChar(line, col);
+ line_pos += line_offset;
+
+ // We now calculate where the current line starts in the paragraph.
+ QString linetext = textLine(line);
+ int start_of_line = 0;
+ if (line_offset > 0)
+ {
+ start_of_line = col;
+ while(lineOfChar(line, --start_of_line) == line_offset);
+ start_of_line++;
+ }
+
+
+ // O.K here is the deal: The function getCursorPositoin returns the character
+ // position of the cursor, not the screenposition. I.e,. assume the line
+ // consists of ab\tc then the character c will be on the screen on position 8
+ // whereas getCursorPosition will return 3 if the cursors is on the character c.
+ // Therefore we need to compute the screen position from the character position.
+ // That's what all the following trouble is all about:
+
+ int coltemp = col-start_of_line;
+ int pos = 0;
+ int find = 0;
+ int mem = 0;
+ bool found_one = false;
+
+ // if you understand the following algorithm you are worthy to look at the
+ // kedit+ sources -- if not, go away ;-)
+
+
+ while(find >=0 && find <= coltemp- 1 ){
+ find = linetext.find('\t', find+start_of_line, true )-start_of_line;
+ if( find >=0 && find <= coltemp - 1 ){
+ found_one = true;
+ pos = pos + find - mem;
+ pos = pos + 8 - pos % 8;
+ mem = find;
+ find ++;
+ }
+ }
+
+ pos = pos + coltemp - mem; // add the number of characters behind the
+ // last tab on the line.
+
+ if (found_one){
+ pos = pos - 1;
+ }
+
+ col_pos = pos;
+}
+
+
+void KEdit::keyPressEvent ( QKeyEvent *e)
+{
+ // ignore Ctrl-Return so that KDialogBase can catch them
+ if ( e->key() == Key_Return && e->state() == ControlButton ) {
+ e->ignore();
+ return;
+ }
+
+ KKey key(e);
+ int keyQt = key.keyCodeQt();
+
+ if ( keyQt == CTRL+Key_K ){
+
+ int line = 0;
+ int col = 0;
+ QString killstring;
+
+ if(!killing){
+ killbufferstring = "";
+ killtrue = false;
+ lastwasanewline = false;
+ }
+
+ if(!atEnd()){
+
+ getCursorPosition(&line,&col);
+ killstring = textLine(line);
+ killstring = killstring.mid(col,killstring.length());
+
+
+ if(!killbufferstring.isEmpty() && !killtrue && !lastwasanewline){
+ killbufferstring += '\n';
+ }
+
+ if( (killstring.length() == 0) && !killtrue){
+ killbufferstring += '\n';
+ lastwasanewline = true;
+ }
+
+ if(killstring.length() > 0){
+
+ killbufferstring += killstring;
+ lastwasanewline = false;
+ killtrue = true;
+
+ }else{
+
+ lastwasanewline = false;
+ killtrue = !killtrue;
+
+ }
+
+ }else{
+
+ if(killbufferstring.isEmpty() && !killtrue && !lastwasanewline){
+ killtrue = true;
+ }
+
+ }
+
+ killing = true;
+
+ QMultiLineEdit::keyPressEvent(e);
+ setModified(true);
+ return;
+ }
+ else if ( keyQt == CTRL+Key_Y ){
+
+ int line = 0;
+ int col = 0;
+
+ getCursorPosition(&line,&col);
+
+ QString tmpstring = killbufferstring;
+ if(!killtrue)
+ tmpstring += '\n';
+
+ insertAt(tmpstring,line,col);
+
+ killing = false;
+ setModified(true);
+ return;
+ }
+
+ killing = false;
+
+ if ( KStdAccel::copy().contains( key ) )
+ copy();
+ else if ( isReadOnly() )
+ QMultiLineEdit::keyPressEvent( e );
+ // If this is an unmodified printable key, send it directly to QMultiLineEdit.
+ else if ( !(key.keyCodeQt() & (CTRL | ALT)) && !e->text().isEmpty() && e->text().unicode()->isPrint() )
+ QMultiLineEdit::keyPressEvent( e );
+ else if ( KStdAccel::paste().contains( key ) ) {
+ paste();
+ setModified(true);
+ slotCursorPositionChanged();
+ }
+ else if ( KStdAccel::cut().contains( key ) ) {
+ cut();
+ setModified(true);
+ slotCursorPositionChanged();
+ }
+ else if ( KStdAccel::undo().contains( key ) ) {
+ undo();
+ setModified(true);
+ slotCursorPositionChanged();
+ }
+ else if ( KStdAccel::redo().contains( key ) ) {
+ redo();
+ setModified(true);
+ slotCursorPositionChanged();
+ }
+ else if ( KStdAccel::deleteWordBack().contains( key ) ) {
+ moveCursor(MoveWordBackward, true);
+ if (hasSelectedText())
+ del();
+ setModified(true);
+ slotCursorPositionChanged();
+ }
+ else if ( KStdAccel::deleteWordForward().contains( key ) ) {
+ moveCursor(MoveWordForward, true);
+ if (hasSelectedText())
+ del();
+ setModified(true);
+ slotCursorPositionChanged();
+ }
+ else if ( KStdAccel::backwardWord().contains( key ) ) {
+ CursorAction action = MoveWordBackward;
+ int para, index;
+ getCursorPosition( &para, & index );
+ if (text(para).isRightToLeft())
+ action = MoveWordForward;
+ moveCursor(action, false );
+ slotCursorPositionChanged();
+ }
+ else if ( KStdAccel::forwardWord().contains( key ) ) {
+ CursorAction action = MoveWordForward;
+ int para, index;
+ getCursorPosition( &para, & index );
+ if (text(para).isRightToLeft())
+ action = MoveWordBackward;
+ moveCursor( action, false );
+ slotCursorPositionChanged();
+ }
+ else if ( KStdAccel::next().contains( key ) ) {
+ moveCursor( MovePgDown, false );
+ slotCursorPositionChanged();
+ }
+ else if ( KStdAccel::prior().contains( key ) ) {
+ moveCursor( MovePgUp, false );
+ slotCursorPositionChanged();
+ }
+ else if ( KStdAccel::home().contains( key ) ) {
+ moveCursor( MoveHome, false );
+ slotCursorPositionChanged();
+ }
+ else if ( KStdAccel::end().contains( key ) ) {
+ moveCursor( MoveEnd, false );
+ slotCursorPositionChanged();
+ }
+ else if ( KStdAccel::beginningOfLine().contains( key ) ) {
+ moveCursor( MoveLineStart, false);
+ slotCursorPositionChanged();
+ }
+ else if ( KStdAccel::endOfLine().contains( key ) ) {
+ moveCursor( MoveLineEnd, false);
+ slotCursorPositionChanged();
+ }
+ else if ( key == Key_Insert ) {
+ if (d->overwriteEnabled)
+ {
+ this->setOverwriteMode(!this->isOverwriteMode());
+ emit toggle_overwrite_signal();
+ }
+ }
+ else
+ QMultiLineEdit::keyPressEvent(e);
+}
+
+void KEdit::installRBPopup(QPopupMenu *p) {
+ KContextMenuManager::insert( this, p );
+}
+
+void KEdit::selectFont(){
+
+ QFont font = this->font();
+ KFontDialog::getFont(font);
+ this->setFont(font);
+
+}
+
+void KEdit::doGotoLine() {
+
+ if( !gotodialog )
+ gotodialog = new KEdGotoLine( parent, "gotodialog" );
+
+ this->clearFocus();
+
+ gotodialog->exec();
+ // this seems to be not necessary
+ // gotodialog->setFocus();
+ if( gotodialog->result() != KEdGotoLine::Accepted)
+ return;
+ int target_line = gotodialog->getLineNumber()-1;
+ if (wordWrap() == NoWrap)
+ {
+ setCursorPosition( target_line, 0 );
+ setFocus();
+ return;
+ }
+
+ int max_parag = paragraphs();
+
+ int line = 0;
+ int parag = -1;
+ int lines_in_parag = 0;
+ while ((++parag < max_parag) && (line + lines_in_parag < target_line))
+ {
+ line += lines_in_parag;
+ lines_in_parag = linesOfParagraph(parag);
+ }
+
+ int col = 0;
+ if (parag >= max_parag)
+ {
+ target_line = line + lines_in_parag - 1;
+ parag = max_parag-1;
+ }
+
+ while(1+line+lineOfChar(parag,col) < target_line) col++;
+ setCursorPosition( parag, col );
+ setFocus();
+}
+
+
+void KEdit::dragMoveEvent(QDragMoveEvent* e) {
+
+ if(KURLDrag::canDecode(e))
+ e->accept();
+ else if(QTextDrag::canDecode(e))
+ QMultiLineEdit::dragMoveEvent(e);
+}
+
+void KEdit::contentsDragMoveEvent(QDragMoveEvent* e) {
+
+ if(KURLDrag::canDecode(e))
+ e->accept();
+ else if(QTextDrag::canDecode(e))
+ QMultiLineEdit::contentsDragMoveEvent(e);
+}
+
+void KEdit::dragEnterEvent(QDragEnterEvent* e) {
+
+ kdDebug() << "KEdit::dragEnterEvent()" << endl;
+ e->accept(KURLDrag::canDecode(e) || QTextDrag::canDecode(e));
+}
+
+void KEdit::contentsDragEnterEvent(QDragEnterEvent* e) {
+
+ kdDebug() << "KEdit::contentsDragEnterEvent()" << endl;
+ e->accept(KURLDrag::canDecode(e) || QTextDrag::canDecode(e));
+}
+
+
+void KEdit::dropEvent(QDropEvent* e) {
+
+ kdDebug() << "KEdit::dropEvent()" << endl;
+
+ if(KURLDrag::canDecode(e)) {
+ emit gotUrlDrop(e);
+ }
+ else if(QTextDrag::canDecode(e))
+ QMultiLineEdit::dropEvent(e);
+}
+
+void KEdit::contentsDropEvent(QDropEvent* e) {
+
+ kdDebug() << "KEdit::contentsDropEvent()" << endl;
+
+ if(KURLDrag::canDecode(e)) {
+ emit gotUrlDrop(e);
+ }
+ else if(QTextDrag::canDecode(e))
+ QMultiLineEdit::contentsDropEvent(e);
+}
+
+void KEdit::setOverwriteEnabled(bool b)
+{
+ d->overwriteEnabled = b;
+}
+
+// QWidget::create() turns off mouse-Tracking which would break auto-hiding
+void KEdit::create( WId id, bool initializeWindow, bool destroyOldWindow )
+{
+ QMultiLineEdit::create( id, initializeWindow, destroyOldWindow );
+ KCursor::setAutoHideCursor( this, true );
+}
+
+void KEdit::ensureCursorVisible()
+{
+ if (!d->autoUpdate)
+ return;
+
+ QMultiLineEdit::ensureCursorVisible();
+}
+
+void KEdit::setCursor( const QCursor &c )
+{
+ if (!d->autoUpdate)
+ return;
+
+ QMultiLineEdit::setCursor(c);
+}
+
+void KEdit::viewportPaintEvent( QPaintEvent*pe )
+{
+ if (!d->autoUpdate)
+ return;
+
+ QMultiLineEdit::viewportPaintEvent(pe);
+}
+
+
+void KEdGotoLine::virtual_hook( int id, void* data )
+{ KDialogBase::virtual_hook( id, data ); }
+
+void KEdFind::virtual_hook( int id, void* data )
+{ KDialogBase::virtual_hook( id, data ); }
+
+void KEdReplace::virtual_hook( int id, void* data )
+{ KDialogBase::virtual_hook( id, data ); }
+
+void KEdit::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
diff --git a/kdeui/keditcl2.cpp b/kdeui/keditcl2.cpp
new file mode 100644
index 000000000..8a20eaad6
--- /dev/null
+++ b/kdeui/keditcl2.cpp
@@ -0,0 +1,1127 @@
+/* This file is part of the KDE libraries
+
+ Copyright (C) 1997 Bernd Johannes Wuebben <wuebben@math.cornell.edu>
+ Copyright (C) 2000 Waldo Bastian <bastian@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <limits.h> // INT_MAX
+
+#include <qframe.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qvbuttongroup.h>
+#include <qcheckbox.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qhbox.h>
+#include <qpopupmenu.h>
+
+#include <kapplication.h>
+#include <kcombobox.h>
+#include <knuminput.h>
+#include <kmessagebox.h>
+#include <knotifyclient.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kiconloader.h>
+
+#include "keditcl.h"
+
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Find Methods
+//
+
+void KEdit::search(){
+
+ if( replace_dialog && replace_dialog->isVisible() )
+ {
+ replace_dialog->hide();
+ }
+
+ if( !srchdialog )
+ {
+ srchdialog = new KEdFind( this, "searchdialog", false);
+ connect(srchdialog,SIGNAL(search()),this,SLOT(search_slot()));
+ connect(srchdialog,SIGNAL(done()),this,SLOT(searchdone_slot()));
+ }
+
+ // If we already searched / replaced something before make sure it shows
+ // up in the find dialog line-edit.
+
+ QString string;
+ string = srchdialog->getText();
+ srchdialog->setText(string.isEmpty() ? pattern : string);
+
+ deselect();
+ last_search = NONE;
+
+ srchdialog->show();
+ srchdialog->result();
+}
+
+
+void KEdit::search_slot(){
+
+ int line, col;
+
+ if (!srchdialog)
+ return;
+
+ QString to_find_string = srchdialog->getText();
+ getCursorPosition(&line,&col);
+
+ // srchdialog->get_direction() is true if searching backward
+
+ if (last_search != NONE && srchdialog->get_direction()){
+ col = col - pattern.length() - 1 ;
+ }
+
+again:
+ int result = doSearch(to_find_string, srchdialog->case_sensitive(),
+ false, (!srchdialog->get_direction()),line,col);
+
+ if(!result){
+ if(!srchdialog->get_direction()){ // forward search
+
+ int query = KMessageBox::questionYesNo(
+ srchdialog,
+ i18n("End of document reached.\n"\
+ "Continue from the beginning?"),
+ i18n("Find"),KStdGuiItem::cont(),i18n("Stop"));
+ if (query == KMessageBox::Yes){
+ line = 0;
+ col = 0;
+ goto again;
+ }
+ }
+ else{ //backward search
+
+ int query = KMessageBox::questionYesNo(
+ srchdialog,
+ i18n("Beginning of document reached.\n"\
+ "Continue from the end?"),
+ i18n("Find"),KStdGuiItem::cont(),i18n("Stop"));
+ if (query == KMessageBox::Yes){
+ QString string = textLine( numLines() - 1 );
+ line = numLines() - 1;
+ col = string.length();
+ last_search = BACKWARD;
+ goto again;
+ }
+ }
+ }
+ else{
+ emit CursorPositionChanged();
+ }
+}
+
+
+
+void KEdit::searchdone_slot(){
+
+ if (!srchdialog)
+ return;
+
+ srchdialog->hide();
+ setFocus();
+ last_search = NONE;
+}
+
+/* antlarr: KDE 4: make it const QString & */
+int KEdit::doSearch(QString s_pattern, bool case_sensitive,
+ bool wildcard, bool forward, int line, int col){
+
+ (void) wildcard; // reserved for possible extension to regex
+
+
+ int i, length;
+ int pos = -1;
+
+ if(forward){
+
+ QString string;
+
+ for(i = line; i < numLines(); i++) {
+
+ string = textLine(i);
+
+ pos = string.find(s_pattern, i == line ? col : 0, case_sensitive);
+
+ if( pos != -1){
+
+ length = s_pattern.length();
+
+ setCursorPosition(i,pos,false);
+
+ for(int l = 0 ; l < length; l++){
+ cursorRight(true);
+ }
+
+ setCursorPosition( i , pos + length, true );
+ pattern = s_pattern;
+ last_search = FORWARD;
+
+ return 1;
+ }
+ }
+ }
+ else{ // searching backwards
+
+ QString string;
+
+ for(i = line; i >= 0; i--) {
+
+ string = textLine(i);
+ int line_length = string.length();
+
+ pos = string.findRev(s_pattern, line == i ? col : line_length , case_sensitive);
+
+ if (pos != -1){
+
+ length = s_pattern.length();
+
+ if( ! (line == i && pos > col ) ){
+
+ setCursorPosition(i ,pos ,false );
+
+ for(int l = 0 ; l < length; l++){
+ cursorRight(true);
+ }
+
+ setCursorPosition(i ,pos + length ,true );
+ pattern = s_pattern;
+ last_search = BACKWARD;
+ return 1;
+
+ }
+ }
+
+ }
+ }
+
+ return 0;
+
+}
+
+
+
+bool KEdit::repeatSearch() {
+
+ if(!srchdialog || pattern.isEmpty())
+ {
+ search();
+ return true;
+ }
+
+ search_slot();
+
+ setFocus();
+ return true;
+
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Replace Methods
+//
+
+
+void KEdit::replace()
+{
+ if( srchdialog && srchdialog->isVisible() )
+ {
+ srchdialog->hide();
+ }
+
+ if( !replace_dialog )
+ {
+ replace_dialog = new KEdReplace( this, "replace_dialog", false );
+ connect(replace_dialog,SIGNAL(find()),this,SLOT(replace_search_slot()));
+ connect(replace_dialog,SIGNAL(replace()),this,SLOT(replace_slot()));
+ connect(replace_dialog,SIGNAL(replaceAll()),this,SLOT(replace_all_slot()));
+ connect(replace_dialog,SIGNAL(done()),this,SLOT(replacedone_slot()));
+ }
+
+ QString string = replace_dialog->getText();
+ replace_dialog->setText(string.isEmpty() ? pattern : string);
+
+
+ deselect();
+ last_replace = NONE;
+
+ replace_dialog->show();
+ replace_dialog->result();
+}
+
+
+void KEdit::replace_slot(){
+
+ if (!replace_dialog)
+ return;
+
+ if(!can_replace){
+ KNotifyClient::beep();
+ return;
+ }
+
+ int line,col, length;
+
+ QString string = replace_dialog->getReplaceText();
+ length = string.length();
+
+ this->cut();
+
+ getCursorPosition(&line,&col);
+
+ insertAt(string,line,col);
+ setModified(true);
+ can_replace = false;
+
+ if (replace_dialog->get_direction())
+ {
+ // Backward
+ setCursorPosition(line,col+length);
+ for( int k = 0; k < length; k++){
+ cursorLeft(true);
+ }
+ }
+ else
+ {
+ // Forward
+ setCursorPosition(line,col);
+ for( int k = 0; k < length; k++){
+ cursorRight(true);
+ }
+ }
+}
+
+void KEdit::replace_all_slot(){
+
+ if (!replace_dialog)
+ return;
+
+ QString to_find_string = replace_dialog->getText();
+
+ int lineFrom, lineTo, colFrom, colTo;
+ getSelection(&lineFrom, &colFrom, &lineTo, &colTo);
+
+ // replace_dialog->get_direction() is true if searching backward
+ if (replace_dialog->get_direction())
+ {
+ if (colTo != -1)
+ {
+ replace_all_col = colTo - to_find_string.length();
+ replace_all_line = lineTo;
+ }
+ else
+ {
+ getCursorPosition(&replace_all_line,&replace_all_col);
+ replace_all_col--;
+ }
+ }
+ else
+ {
+ if (colFrom != -1)
+ {
+ replace_all_col = colFrom;
+ replace_all_line = lineFrom;
+ }
+ else
+ {
+ getCursorPosition(&replace_all_line,&replace_all_col);
+ }
+ }
+
+ deselect();
+
+again:
+
+ setAutoUpdate(false);
+ int result = 1;
+
+ while(result){
+
+ result = doReplace(to_find_string, replace_dialog->case_sensitive(),
+ false, (!replace_dialog->get_direction()),
+ replace_all_line,replace_all_col,true);
+
+ }
+
+ setAutoUpdate(true);
+ update();
+
+ if(!replace_dialog->get_direction()){ // forward search
+
+ int query = KMessageBox::questionYesNo(
+ srchdialog,
+ i18n("End of document reached.\n"\
+ "Continue from the beginning?"),
+ i18n("Find"),KStdGuiItem::cont(),i18n("Stop"));
+ if (query == KMessageBox::Yes){
+ replace_all_line = 0;
+ replace_all_col = 0;
+ goto again;
+ }
+ }
+ else{ //backward search
+
+ int query = KMessageBox::questionYesNo(
+ srchdialog,
+ i18n("Beginning of document reached.\n"\
+ "Continue from the end?"),
+ i18n("Find"),KStdGuiItem::cont(),i18n("Stop"));
+ if (query == KMessageBox::Yes){
+ QString string = textLine( numLines() - 1 );
+ replace_all_line = numLines() - 1;
+ replace_all_col = string.length();
+ last_replace = BACKWARD;
+ goto again;
+ }
+ }
+
+ emit CursorPositionChanged();
+
+}
+
+
+void KEdit::replace_search_slot(){
+
+ int line, col;
+
+ if (!replace_dialog)
+ return;
+
+ QString to_find_string = replace_dialog->getText();
+
+ int lineFrom, lineTo, colFrom, colTo;
+ getSelection(&lineFrom, &colFrom, &lineTo, &colTo);
+
+ // replace_dialog->get_direction() is true if searching backward
+ if (replace_dialog->get_direction())
+ {
+ if (colFrom != -1)
+ {
+ col = colFrom - to_find_string.length();
+ line = lineFrom;
+ }
+ else
+ {
+ getCursorPosition(&line,&col);
+ col--;
+ }
+ }
+ else
+ {
+ if (colTo != -1)
+ {
+ col = colTo;
+ line = lineTo;
+ }
+ else
+ {
+ getCursorPosition(&line,&col);
+ }
+ }
+
+again:
+
+ int result = doReplace(to_find_string, replace_dialog->case_sensitive(),
+ false, (!replace_dialog->get_direction()), line, col, false );
+
+ if(!result){
+ if(!replace_dialog->get_direction()){ // forward search
+
+ int query = KMessageBox::questionYesNo(
+ replace_dialog,
+ i18n("End of document reached.\n"\
+ "Continue from the beginning?"),
+ i18n("Replace"),KStdGuiItem::cont(),i18n("Stop"));
+ if (query == KMessageBox::Yes){
+ line = 0;
+ col = 0;
+ goto again;
+ }
+ }
+ else{ //backward search
+
+ int query = KMessageBox::questionYesNo(
+ replace_dialog,
+ i18n("Beginning of document reached.\n"\
+ "Continue from the end?"),
+ i18n("Replace"),KStdGuiItem::cont(),i18n("Stop"));
+ if (query == KMessageBox::Yes){
+ QString string = textLine( numLines() - 1 );
+ line = numLines() - 1;
+ col = string.length();
+ last_replace = BACKWARD;
+ goto again;
+ }
+ }
+ }
+ else{
+
+ emit CursorPositionChanged();
+ }
+}
+
+
+
+void KEdit::replacedone_slot(){
+
+ if (!replace_dialog)
+ return;
+
+ replace_dialog->hide();
+ // replace_dialog->clearFocus();
+
+ setFocus();
+
+ last_replace = NONE;
+ can_replace = false;
+
+}
+
+
+
+/* antlarr: KDE 4: make it const QString & */
+int KEdit::doReplace(QString s_pattern, bool case_sensitive,
+ bool wildcard, bool forward, int line, int col, bool replace_all){
+
+
+ (void) wildcard; // reserved for possible extension to regex
+
+ int line_counter, length;
+ int pos = -1;
+
+ QString string;
+ QString stringnew;
+ QString replacement;
+
+ replacement = replace_dialog->getReplaceText();
+ line_counter = line;
+ replace_all_col = col;
+
+ if(forward){
+
+ int num_lines = numLines();
+
+ while (line_counter < num_lines){
+
+ string = textLine(line_counter);
+
+ if (replace_all){
+ pos = string.find(s_pattern, replace_all_col, case_sensitive);
+ }
+ else{
+ pos = string.find(s_pattern, line_counter == line ? col : 0, case_sensitive);
+ }
+
+ if (pos == -1 ){
+ line_counter++;
+ replace_all_col = 0;
+ replace_all_line = line_counter;
+ }
+
+ if( pos != -1){
+
+ length = s_pattern.length();
+
+ if(replace_all){ // automatic
+
+ stringnew = string.copy();
+ do
+ {
+ stringnew.replace(pos,length,replacement);
+
+ replace_all_col = pos + replacement.length();
+ replace_all_line = line_counter;
+
+ pos = stringnew.find(s_pattern, replace_all_col, case_sensitive);
+ }
+ while( pos != -1);
+
+ removeLine(line_counter);
+ insertLine(stringnew,line_counter);
+
+ setModified(true);
+ }
+ else{ // interactive
+
+ setCursorPosition( line_counter , pos, false );
+
+ for(int l = 0 ; l < length; l++){
+ cursorRight(true);
+ }
+
+ setCursorPosition( line_counter , pos + length, true );
+ pattern = s_pattern;
+ last_replace = FORWARD;
+ can_replace = true;
+
+ return 1;
+
+ }
+
+ }
+ }
+ }
+ else{ // searching backwards
+
+ while(line_counter >= 0){
+
+ string = textLine(line_counter);
+
+ int line_length = string.length();
+
+ if( replace_all ){
+ if (replace_all_col < 0)
+ pos = -1;
+ else
+ pos = string.findRev(s_pattern, replace_all_col , case_sensitive);
+ }
+ else{
+ if ((line == line_counter) && (col < 0))
+ pos = -1;
+ else
+ pos = string.findRev(s_pattern,
+ line == line_counter ? col : line_length , case_sensitive);
+ }
+
+ if (pos == -1 ){
+ line_counter--;
+
+ replace_all_col = 0;
+ if(line_counter >= 0){
+ string = textLine(line_counter);
+ replace_all_col = string.length();
+
+ }
+ replace_all_line = line_counter;
+ }
+
+
+ if (pos != -1){
+ length = s_pattern.length();
+
+ if(replace_all){ // automatic
+
+ stringnew = string.copy();
+ stringnew.replace(pos,length,replacement);
+
+ removeLine(line_counter);
+ insertLine(stringnew,line_counter);
+
+ replace_all_col = pos-length;
+ replace_all_line = line_counter;
+ if (replace_all_col < 0)
+ {
+ line_counter--;
+
+ if(line_counter >= 0){
+ string = textLine(line_counter);
+ replace_all_col = string.length();
+ }
+ replace_all_line = line_counter;
+ }
+
+ setModified(true);
+ }
+ else{ // interactive
+
+ // printf("line_counter %d pos %d col %d\n",line_counter, pos,col);
+ if( ! (line == line_counter && pos > col ) ){
+
+ setCursorPosition(line_counter, pos + length ,false );
+
+ for(int l = 0 ; l < length; l++){
+ cursorLeft(true);
+ }
+
+ setCursorPosition(line_counter, pos ,true );
+ pattern = s_pattern;
+
+ last_replace = BACKWARD;
+ can_replace = true;
+
+ return 1;
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
+
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////
+//
+// Find Dialog
+//
+
+class KEdFind::KEdFindPrivate
+{
+public:
+ KEdFindPrivate( QWidget *parent ) {
+ combo = new KHistoryCombo( parent, "value" );
+ combo->setMaxCount( 20 ); // just some default
+ }
+ ~KEdFindPrivate() {
+ delete combo;
+ }
+
+ KHistoryCombo *combo;
+};
+
+
+KEdFind::KEdFind( QWidget *parent, const char *name, bool modal )
+ :KDialogBase( parent, name, modal, i18n("Find"),
+ modal ? User1|Cancel : User1|Close, User1, false, KGuiItem( i18n("&Find"), "find") )
+{
+ setWFlags( WType_TopLevel );
+
+ QWidget *page = new QWidget( this );
+ setMainWidget(page);
+ QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
+
+ d = new KEdFindPrivate( page );
+
+ QString text = i18n("Find:");
+ QLabel *label = new QLabel( text, page , "find" );
+ topLayout->addWidget( label );
+
+ d->combo->setMinimumWidth(fontMetrics().maxWidth()*20);
+ d->combo->setFocus();
+
+ connect(d->combo, SIGNAL(textChanged ( const QString & )),
+ this,SLOT(textSearchChanged ( const QString & )));
+
+ topLayout->addWidget(d->combo);
+
+ group = new QVButtonGroup( i18n("Options"), page );
+ topLayout->addWidget( group );
+
+ QHBox* row1 = new QHBox( group );
+
+ text = i18n("Case &sensitive");
+ sensitive = new QCheckBox( text, row1, "case");
+ text = i18n("Find &backwards");
+ direction = new QCheckBox( text, row1, "direction" );
+
+
+ enableButton( KDialogBase::User1, !d->combo->currentText().isEmpty() );
+
+ if ( !modal )
+ connect( this, SIGNAL( closeClicked() ), this, SLOT( slotCancel() ) );
+}
+
+KEdFind::~KEdFind()
+{
+ delete d;
+}
+
+void KEdFind::textSearchChanged ( const QString &text )
+{
+ enableButton( KDialogBase::User1, !text.isEmpty() );
+}
+
+void KEdFind::slotCancel( void )
+{
+ emit done();
+ KDialogBase::slotCancel();
+}
+
+void KEdFind::slotUser1( void )
+{
+ if( !d->combo->currentText().isEmpty() )
+ {
+ d->combo->addToHistory( d->combo->currentText() );
+ emit search();
+ }
+}
+
+
+QString KEdFind::getText() const
+{
+ return d->combo->currentText();
+}
+
+
+/* antlarr: KDE 4: make it const QString & */
+void KEdFind::setText(QString string)
+{
+ d->combo->setEditText(string);
+ d->combo->lineEdit()->selectAll();
+}
+
+void KEdFind::setCaseSensitive( bool b )
+{
+ sensitive->setChecked( b );
+}
+
+bool KEdFind::case_sensitive() const
+{
+ return sensitive->isChecked();
+}
+
+void KEdFind::setDirection( bool b )
+{
+ direction->setChecked( b );
+}
+
+bool KEdFind::get_direction() const
+{
+ return direction->isChecked();
+}
+
+KHistoryCombo * KEdFind::searchCombo() const
+{
+ return d->combo;
+}
+
+
+
+////////////////////////////////////////////////////////////////////
+//
+// Replace Dialog
+//
+
+class KEdReplace::KEdReplacePrivate
+{
+public:
+ KEdReplacePrivate( QWidget *parent ) {
+ searchCombo = new KHistoryCombo( parent, "value" );
+ replaceCombo = new KHistoryCombo( parent, "replace_value" );
+
+ searchCombo->setMaxCount( 20 ); // just some defaults
+ replaceCombo->setMaxCount( 20 );
+ }
+ ~KEdReplacePrivate() {
+ delete searchCombo;
+ delete replaceCombo;
+ }
+
+ KHistoryCombo *searchCombo, *replaceCombo;
+};
+
+KEdReplace::KEdReplace( QWidget *parent, const char *name, bool modal )
+ :KDialogBase( parent, name, modal, i18n("Replace"),
+ modal ? User3|User2|User1|Cancel : User3|User2|User1|Close,
+ User3, false,
+ i18n("Replace &All"), i18n("&Replace"), KGuiItem( i18n("&Find"), "find") )
+{
+ setWFlags( WType_TopLevel );
+
+ setButtonBoxOrientation( Vertical );
+
+ QFrame *page = makeMainWidget();
+ QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
+
+ d = new KEdReplacePrivate( page );
+
+ QString text = i18n("Find:");
+ QLabel *label = new QLabel( text, page, "find" );
+ topLayout->addWidget( label );
+
+ d->searchCombo->setMinimumWidth(fontMetrics().maxWidth()*20);
+ d->searchCombo->setFocus();
+ topLayout->addWidget(d->searchCombo);
+
+ text = i18n("Replace with:");
+ label = new QLabel( text, page, "replace" );
+ topLayout->addWidget( label );
+
+ d->replaceCombo->setMinimumWidth(fontMetrics().maxWidth()*20);
+ topLayout->addWidget(d->replaceCombo);
+
+ connect(d->searchCombo, SIGNAL(textChanged ( const QString & )),
+ this,SLOT(textSearchChanged ( const QString & )));
+
+ QButtonGroup *group = new QButtonGroup( i18n("Options"), page );
+ topLayout->addWidget( group );
+
+ QGridLayout *gbox = new QGridLayout( group, 3, 2, spacingHint() );
+ gbox->addRowSpacing( 0, fontMetrics().lineSpacing() );
+
+ text = i18n("Case &sensitive");
+ sensitive = new QCheckBox( text, group, "case");
+ text = i18n("Find &backwards");
+ direction = new QCheckBox( text, group, "direction" );
+ gbox->addWidget( sensitive, 1, 0 );
+ gbox->addWidget( direction, 1, 1 );
+ gbox->setRowStretch( 2, 10 );
+}
+
+
+KEdReplace::~KEdReplace()
+{
+ delete d;
+}
+
+void KEdReplace::textSearchChanged ( const QString &text )
+{
+ bool state=text.isEmpty();
+ enableButton( KDialogBase::User1, !state );
+ enableButton( KDialogBase::User2, !state );
+ enableButton( KDialogBase::User3, !state );
+}
+
+void KEdReplace::slotCancel( void )
+{
+ emit done();
+ d->searchCombo->clearEdit();
+ d->replaceCombo->clearEdit();
+ KDialogBase::slotCancel();
+}
+
+void KEdReplace::slotClose( void )
+{
+ slotCancel();
+}
+
+void KEdReplace::slotUser1( void )
+{
+ if( !d->searchCombo->currentText().isEmpty() )
+ {
+ d->replaceCombo->addToHistory( d->replaceCombo->currentText() );
+ emit replaceAll();
+ }
+}
+
+
+void KEdReplace::slotUser2( void )
+{
+ if( !d->searchCombo->currentText().isEmpty() )
+ {
+ d->replaceCombo->addToHistory( d->replaceCombo->currentText() );
+ emit replace();
+ }
+}
+
+void KEdReplace::slotUser3( void )
+{
+ if( !d->searchCombo->currentText().isEmpty() )
+ {
+ d->searchCombo->addToHistory( d->searchCombo->currentText() );
+ emit find();
+ }
+}
+
+
+QString KEdReplace::getText()
+{
+ return d->searchCombo->currentText();
+}
+
+
+QString KEdReplace::getReplaceText()
+{
+ return d->replaceCombo->currentText();
+}
+
+
+/* antlarr: KDE 4: make it const QString & */
+void KEdReplace::setText(QString string)
+{
+ d->searchCombo->setEditText(string);
+ d->searchCombo->lineEdit()->selectAll();
+}
+
+
+bool KEdReplace::case_sensitive()
+{
+ return sensitive->isChecked();
+}
+
+
+bool KEdReplace::get_direction()
+{
+ return direction->isChecked();
+}
+
+KHistoryCombo * KEdReplace::searchCombo() const
+{
+ return d->searchCombo;
+}
+
+KHistoryCombo * KEdReplace::replaceCombo() const
+{
+ return d->replaceCombo;
+}
+
+
+KEdGotoLine::KEdGotoLine( QWidget *parent, const char *name, bool modal )
+ :KDialogBase( parent, name, modal, i18n("Go to Line"), modal ? Ok|Cancel : Ok|Close, Ok, false )
+{
+ QWidget *page = new QWidget( this );
+ setMainWidget(page);
+ QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
+
+ lineNum = new KIntNumInput( 1, page);
+ lineNum->setRange(1, 1000000, 1, false);
+ lineNum->setLabel(i18n("Go to line:"), AlignVCenter | AlignLeft);
+// lineNum->setMinimumWidth(fontMetrics().maxWidth()*20);
+ topLayout->addWidget( lineNum );
+
+ topLayout->addStretch(10);
+ lineNum->setFocus();
+}
+
+
+void KEdGotoLine::selected(int)
+{
+ accept();
+}
+
+
+int KEdGotoLine::getLineNumber()
+{
+ return lineNum->value();
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Spell Checking
+//
+
+void KEdit::spellcheck_start()
+{
+ saved_readonlystate = isReadOnly();
+ setReadOnly(true);
+}
+
+void KEdit::misspelling (const QString &word, const QStringList &, unsigned int pos)
+{
+
+ unsigned int l = 0;
+ unsigned int cnt = 0;
+ posToRowCol (pos, l, cnt);
+ setSelection(l, cnt, l, cnt+word.length());
+
+ /*
+ if (cursorPoint().y()>height()/2)
+ kspell->moveDlg (10, height()/2-kspell->heightDlg()-15);
+ else
+ kspell->moveDlg (10, height()/2 + 15);
+ */
+
+}
+
+//need to use pos for insert, not cur, so forget cur altogether
+void KEdit::corrected (const QString &originalword, const QString &newword, unsigned int pos)
+{
+ //we'll reselect the original word in case the user has played with
+ //the selection in eframe or the word was auto-replaced
+
+ unsigned int l = 0;
+ unsigned int cnt = 0;
+
+ if( newword != originalword )
+ {
+ posToRowCol (pos, l, cnt);
+ setSelection(l, cnt, l, cnt+originalword.length());
+
+ setReadOnly ( false );
+ removeSelectedText();
+ insert(newword);
+ setReadOnly ( true );
+ }
+ else
+ {
+ deselect();
+ }
+}
+
+void KEdit::posToRowCol(unsigned int pos, unsigned int &line, unsigned int &col)
+{
+ for (line = 0; line < static_cast<uint>(numLines()) && col <= pos; line++)
+ {
+ col += lineLength(line)+1;
+ }
+ line--;
+ col = pos - col + lineLength(line) + 1;
+}
+
+void KEdit::spellcheck_stop()
+{
+ deselect();
+
+ setReadOnly ( saved_readonlystate);
+}
+
+QString KEdit::selectWordUnderCursor( )
+{
+ int parag;
+ int pos;
+
+ getCursorPosition(&parag, &pos);
+
+ QString txt = text(parag);
+
+ // Find start
+ int start = pos;
+ while( start > 0 )
+ {
+ const QChar &ch = txt[start-1];
+ if (ch.isSpace() || ch.isPunct())
+ break;
+ start--;
+ }
+
+ // Find end
+ int end = pos;
+ int len = txt.length();
+ while( end < len )
+ {
+ const QChar &ch = txt[end];
+ if (ch.isSpace() || ch.isPunct())
+ break;
+ end++;
+ }
+ setSelection(parag, start, parag, end);
+ return txt.mid(start, end-start);
+}
+
+QPopupMenu *KEdit::createPopupMenu( const QPoint& pos )
+{
+ enum { IdUndo, IdRedo, IdSep1, IdCut, IdCopy, IdPaste, IdClear, IdSep2, IdSelectAll };
+
+ QPopupMenu *menu = QMultiLineEdit::createPopupMenu( pos );
+
+ if ( isReadOnly() )
+ menu->changeItem( menu->idAt(0), SmallIconSet("editcopy"), menu->text( menu->idAt(0) ) );
+ else {
+ int id = menu->idAt(0);
+ menu->changeItem( id - IdUndo, SmallIconSet("undo"), menu->text( id - IdUndo) );
+ menu->changeItem( id - IdRedo, SmallIconSet("redo"), menu->text( id - IdRedo) );
+ menu->changeItem( id - IdCut, SmallIconSet("editcut"), menu->text( id - IdCut) );
+ menu->changeItem( id - IdCopy, SmallIconSet("editcopy"), menu->text( id - IdCopy) );
+ menu->changeItem( id - IdPaste, SmallIconSet("editpaste"), menu->text( id - IdPaste) );
+ menu->changeItem( id - IdClear, SmallIconSet("editclear"), menu->text( id - IdClear) );
+ }
+
+ return menu;
+}
diff --git a/kdeui/keditlistbox.cpp b/kdeui/keditlistbox.cpp
new file mode 100644
index 000000000..88942ebc7
--- /dev/null
+++ b/kdeui/keditlistbox.cpp
@@ -0,0 +1,418 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 David Faure <faure@kde.org>, Alexander Neundorf <neundorf@kde.org>
+ 2000, 2002 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qstringlist.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qgroupbox.h>
+#include <qlistbox.h>
+#include <qwhatsthis.h>
+#include <qlabel.h>
+
+#include <kcombobox.h>
+#include <kdebug.h>
+#include <kdialog.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <kapplication.h>
+#include <knotifyclient.h>
+
+#include "keditlistbox.h"
+
+#include <assert.h>
+
+class KEditListBoxPrivate
+{
+public:
+ bool m_checkAtEntering;
+ uint buttons;
+};
+
+KEditListBox::KEditListBox(QWidget *parent, const char *name,
+ bool checkAtEntering, int buttons )
+ :QGroupBox(parent, name ), d(new KEditListBoxPrivate)
+{
+ init( checkAtEntering, buttons );
+}
+
+KEditListBox::KEditListBox(const QString& title, QWidget *parent,
+ const char *name, bool checkAtEntering, int buttons)
+ :QGroupBox(title, parent, name ), d(new KEditListBoxPrivate)
+{
+ init( checkAtEntering, buttons );
+}
+
+KEditListBox::KEditListBox(const QString& title, const CustomEditor& custom,
+ QWidget *parent, const char *name,
+ bool checkAtEntering, int buttons)
+ :QGroupBox(title, parent, name ), d(new KEditListBoxPrivate)
+{
+ m_lineEdit = custom.lineEdit();
+ init( checkAtEntering, buttons, custom.representationWidget() );
+}
+
+KEditListBox::~KEditListBox()
+{
+ delete d;
+}
+
+void KEditListBox::init( bool checkAtEntering, int buttons,
+ QWidget *representationWidget )
+{
+ d->m_checkAtEntering = checkAtEntering;
+
+ servNewButton = servRemoveButton = servUpButton = servDownButton = 0L;
+ setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding,
+ QSizePolicy::MinimumExpanding));
+
+ QGridLayout * grid = new QGridLayout(this, 7, 2,
+ KDialog::marginHint(),
+ KDialog::spacingHint());
+ grid->addRowSpacing(0, fontMetrics().lineSpacing());
+ grid->setRowStretch( 6, 1 );
+
+ grid->setMargin(15);
+
+ if ( representationWidget )
+ representationWidget->reparent( this, QPoint(0,0) );
+ else
+ m_lineEdit=new KLineEdit(this);
+
+ m_listBox = new QListBox(this);
+
+ QWidget *editingWidget = representationWidget ?
+ representationWidget : m_lineEdit;
+ grid->addMultiCellWidget(editingWidget,1,1,0,1);
+ grid->addMultiCellWidget(m_listBox, 2, 6, 0, 0);
+
+ d->buttons = 0;
+ setButtons( buttons );
+
+ connect(m_lineEdit,SIGNAL(textChanged(const QString&)),this,SLOT(typedSomething(const QString&)));
+ m_lineEdit->setTrapReturnKey(true);
+ connect(m_lineEdit,SIGNAL(returnPressed()),this,SLOT(addItem()));
+ connect(m_listBox, SIGNAL(highlighted(int)), SLOT(enableMoveButtons(int)));
+
+ // maybe supplied lineedit has some text already
+ typedSomething( m_lineEdit->text() );
+}
+
+void KEditListBox::setButtons( uint buttons )
+{
+ if ( d->buttons == buttons )
+ return;
+
+ QGridLayout* grid = static_cast<QGridLayout *>( layout() );
+ if ( ( buttons & Add ) && !servNewButton ) {
+ servNewButton = new QPushButton(i18n("&Add"), this);
+ servNewButton->setEnabled(false);
+ servNewButton->show();
+ connect(servNewButton, SIGNAL(clicked()), SLOT(addItem()));
+
+ grid->addWidget(servNewButton, 2, 1);
+ } else if ( ( buttons & Add ) == 0 && servNewButton ) {
+ delete servNewButton;
+ servNewButton = 0;
+ }
+
+ if ( ( buttons & Remove ) && !servRemoveButton ) {
+ servRemoveButton = new QPushButton(i18n("&Remove"), this);
+ servRemoveButton->setEnabled(false);
+ servRemoveButton->show();
+ connect(servRemoveButton, SIGNAL(clicked()), SLOT(removeItem()));
+
+ grid->addWidget(servRemoveButton, 3, 1);
+ } else if ( ( buttons & Remove ) == 0 && servRemoveButton ) {
+ delete servRemoveButton;
+ servRemoveButton = 0;
+ }
+
+ if ( ( buttons & UpDown ) && !servUpButton ) {
+ servUpButton = new QPushButton(i18n("Move &Up"), this);
+ servUpButton->setEnabled(false);
+ servUpButton->show();
+ connect(servUpButton, SIGNAL(clicked()), SLOT(moveItemUp()));
+
+ servDownButton = new QPushButton(i18n("Move &Down"), this);
+ servDownButton->setEnabled(false);
+ servDownButton->show();
+ connect(servDownButton, SIGNAL(clicked()), SLOT(moveItemDown()));
+
+ grid->addWidget(servUpButton, 4, 1);
+ grid->addWidget(servDownButton, 5, 1);
+ } else if ( ( buttons & UpDown ) == 0 && servUpButton ) {
+ delete servUpButton; servUpButton = 0;
+ delete servDownButton; servDownButton = 0;
+ }
+
+ d->buttons = buttons;
+}
+
+void KEditListBox::typedSomething(const QString& text)
+{
+ if(currentItem() >= 0) {
+ if(currentText() != m_lineEdit->text())
+ {
+ // IMHO changeItem() shouldn't do anything with the value
+ // of currentItem() ... like changing it or emitting signals ...
+ // but TT disagree with me on this one (it's been that way since ages ... grrr)
+ bool block = m_listBox->signalsBlocked();
+ m_listBox->blockSignals( true );
+ m_listBox->changeItem(text, currentItem());
+ m_listBox->blockSignals( block );
+ emit changed();
+ }
+ }
+
+ if ( !servNewButton )
+ return;
+
+ if (!d->m_checkAtEntering)
+ servNewButton->setEnabled(!text.isEmpty());
+ else
+ {
+ if (text.isEmpty())
+ {
+ servNewButton->setEnabled(false);
+ }
+ else
+ {
+ StringComparisonMode mode = (StringComparisonMode) (ExactMatch | CaseSensitive );
+ bool enable = (!m_listBox->findItem( text, mode ));
+ servNewButton->setEnabled( enable );
+ }
+ }
+}
+
+void KEditListBox::moveItemUp()
+{
+ if (!m_listBox->isEnabled())
+ {
+ KNotifyClient::beep();
+ return;
+ }
+
+ const unsigned int selIndex = m_listBox->currentItem();
+ if (selIndex == 0)
+ {
+ KNotifyClient::beep();
+ return;
+ }
+
+ QListBoxItem *selItem = m_listBox->item(selIndex);
+ m_listBox->takeItem(selItem);
+ m_listBox->insertItem(selItem, selIndex-1);
+ m_listBox->setCurrentItem(selIndex - 1);
+
+ emit changed();
+}
+
+void KEditListBox::moveItemDown()
+{
+ if (!m_listBox->isEnabled())
+ {
+ KNotifyClient::beep();
+ return;
+ }
+
+ unsigned int selIndex = m_listBox->currentItem();
+ if (selIndex == m_listBox->count() - 1)
+ {
+ KNotifyClient::beep();
+ return;
+ }
+
+ QListBoxItem *selItem = m_listBox->item(selIndex);
+ m_listBox->takeItem(selItem);
+ m_listBox->insertItem(selItem, selIndex+1);
+ m_listBox->setCurrentItem(selIndex + 1);
+
+ emit changed();
+}
+
+void KEditListBox::addItem()
+{
+ // when m_checkAtEntering is true, the add-button is disabled, but this
+ // slot can still be called through Key_Return/Key_Enter. So we guard
+ // against this.
+ if ( !servNewButton || !servNewButton->isEnabled() )
+ return;
+
+ const QString& currentTextLE=m_lineEdit->text();
+ bool alreadyInList(false);
+ //if we didn't check for dupes at the inserting we have to do it now
+ if (!d->m_checkAtEntering)
+ {
+ // first check current item instead of dumb iterating the entire list
+ if ( m_listBox->currentText() == currentTextLE )
+ alreadyInList = true;
+ else
+ {
+ StringComparisonMode mode = (StringComparisonMode) (ExactMatch | CaseSensitive );
+ alreadyInList =(m_listBox->findItem(currentTextLE, mode) );
+ }
+ }
+
+ if ( servNewButton )
+ servNewButton->setEnabled(false);
+
+ bool block = m_lineEdit->signalsBlocked();
+ m_lineEdit->blockSignals(true);
+ m_lineEdit->clear();
+ m_lineEdit->blockSignals(block);
+
+ m_listBox->setSelected(currentItem(), false);
+
+ if (!alreadyInList)
+ {
+ block = m_listBox->signalsBlocked();
+ m_listBox->blockSignals( true );
+ m_listBox->insertItem(currentTextLE);
+ m_listBox->blockSignals( block );
+ emit changed();
+ emit added( currentTextLE );
+ }
+}
+
+int KEditListBox::currentItem() const
+{
+ int nr = m_listBox->currentItem();
+ if(nr >= 0 && !m_listBox->item(nr)->isSelected()) return -1;
+ return nr;
+}
+
+void KEditListBox::removeItem()
+{
+ int selected = m_listBox->currentItem();
+
+ if ( selected >= 0 )
+ {
+ QString removedText = m_listBox->currentText();
+
+ m_listBox->removeItem( selected );
+ if ( count() > 0 )
+ m_listBox->setSelected( QMIN( selected, count() - 1 ), true );
+
+ emit changed();
+ emit removed( removedText );
+ }
+
+ if ( servRemoveButton && m_listBox->currentItem() == -1 )
+ servRemoveButton->setEnabled(false);
+}
+
+void KEditListBox::enableMoveButtons(int index)
+{
+ // Update the lineEdit when we select a different line.
+ if(currentText() != m_lineEdit->text())
+ m_lineEdit->setText(currentText());
+
+ bool moveEnabled = servUpButton && servDownButton;
+
+ if (moveEnabled )
+ {
+ if (m_listBox->count() <= 1)
+ {
+ servUpButton->setEnabled(false);
+ servDownButton->setEnabled(false);
+ }
+ else if ((uint) index == (m_listBox->count() - 1))
+ {
+ servUpButton->setEnabled(true);
+ servDownButton->setEnabled(false);
+ }
+ else if (index == 0)
+ {
+ servUpButton->setEnabled(false);
+ servDownButton->setEnabled(true);
+ }
+ else
+ {
+ servUpButton->setEnabled(true);
+ servDownButton->setEnabled(true);
+ }
+ }
+
+ if ( servRemoveButton )
+ servRemoveButton->setEnabled(true);
+}
+
+void KEditListBox::clear()
+{
+ m_lineEdit->clear();
+ m_listBox->clear();
+ emit changed();
+}
+
+void KEditListBox::insertStringList(const QStringList& list, int index)
+{
+ m_listBox->insertStringList(list,index);
+}
+
+void KEditListBox::insertStrList(const QStrList* list, int index)
+{
+ m_listBox->insertStrList(list,index);
+}
+
+void KEditListBox::insertStrList(const QStrList& list, int index)
+{
+ m_listBox->insertStrList(list,index);
+}
+
+void KEditListBox::insertStrList(const char ** list, int numStrings, int index)
+{
+ m_listBox->insertStrList(list,numStrings,index);
+}
+
+QStringList KEditListBox::items() const
+{
+ QStringList list;
+ for (QListBoxItem const * i = m_listBox->firstItem(); i != 0; i = i->next() )
+ list.append( i->text());
+
+ return list;
+}
+
+void KEditListBox::setItems(const QStringList& items)
+{
+ m_listBox->clear();
+ m_listBox->insertStringList(items, 0);
+}
+
+int KEditListBox::buttons() const
+{
+ return d->buttons;
+}
+
+void KEditListBox::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+
+///////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////
+
+KEditListBox::CustomEditor::CustomEditor( KComboBox *combo )
+{
+ m_representationWidget = combo;
+ m_lineEdit = dynamic_cast<KLineEdit*>( combo->lineEdit() );
+ assert( m_lineEdit );
+}
+
+#include "keditlistbox.moc"
diff --git a/kdeui/keditlistbox.h b/kdeui/keditlistbox.h
new file mode 100644
index 000000000..bb27d89f7
--- /dev/null
+++ b/kdeui/keditlistbox.h
@@ -0,0 +1,272 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 David Faure <faure@kde.org>, Alexander Neundorf <neundorf@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KEDITLISTBOX_H
+#define KEDITLISTBOX_H
+
+#include <qgroupbox.h>
+#include <qlistbox.h>
+
+#include <kdelibs_export.h>
+
+class KLineEdit;
+class KComboBox;
+class QPushButton;
+
+class KEditListBoxPrivate;
+/**
+ * An editable listbox
+ *
+ * This class provides a editable listbox ;-), this means
+ * a listbox which is accompanied by a line edit to enter new
+ * items into the listbox and pushbuttons to add and remove
+ * items from the listbox and two buttons to move items up and down.
+ *
+ * \image html keditlistbox.png "KDE Edit List Box Widget"
+ *
+ */
+class KDEUI_EXPORT KEditListBox : public QGroupBox
+{
+ Q_OBJECT
+
+ Q_SETS( Button )
+ Q_PROPERTY( Button buttons READ buttons WRITE setButtons )
+ Q_PROPERTY( QStringList items READ items WRITE setItems )
+
+public:
+ /**
+ * Custom editor class
+ *
+ * @since 3.1
+ **/
+ // ### KDE4: add virtual destructor
+ class CustomEditor
+ {
+ public:
+ KDEUI_EXPORT CustomEditor()
+ : m_representationWidget( 0L ),
+ m_lineEdit( 0L ) {}
+ KDEUI_EXPORT CustomEditor( QWidget *repWidget, KLineEdit *edit )
+ : m_representationWidget( repWidget ),
+ m_lineEdit( edit ) {}
+ KDEUI_EXPORT CustomEditor( KComboBox *combo );
+
+ KDEUI_EXPORT void setRepresentationWidget( QWidget *repWidget ) {
+ m_representationWidget = repWidget;
+ }
+ KDEUI_EXPORT void setLineEdit( KLineEdit *edit ) {
+ m_lineEdit = edit;
+ }
+
+ KDEUI_EXPORT virtual QWidget *representationWidget() const {
+ return m_representationWidget;
+ }
+ KDEUI_EXPORT virtual KLineEdit *lineEdit() const {
+ return m_lineEdit;
+ }
+
+ protected:
+ QWidget *m_representationWidget;
+ KLineEdit *m_lineEdit;
+ };
+
+ public:
+
+ /**
+ * Enumeration of the buttons, the listbox offers. Specify them in the
+ * constructor in the buttons parameter, or in setButtons.
+ */
+ enum Button { Add = 1, Remove = 2, UpDown = 4 };
+ enum { All = Add|Remove|UpDown }; // separated so that it doesn't appear in Qt designer
+
+ /**
+ * Create an editable listbox.
+ *
+ * If @p checkAtEntering is true, after every character you type
+ * in the line edit KEditListBox will enable or disable
+ * the Add-button, depending whether the current content of the
+ * line edit is already in the listbox. Maybe this can become a
+ * performance hit with large lists on slow machines.
+ * If @p checkAtEntering is false,
+ * it will be checked if you press the Add-button. It is not
+ * possible to enter items twice into the listbox.
+ */
+ KEditListBox(QWidget *parent = 0, const char *name = 0,
+ bool checkAtEntering=false, int buttons = All );
+ /**
+ * Create an editable listbox.
+ *
+ * The same as the other constructor, additionally it takes
+ * @p title, which will be the title of the frame around the listbox.
+ */
+ KEditListBox(const QString& title, QWidget *parent = 0,
+ const char *name = 0, bool checkAtEntering=false,
+ int buttons = All );
+
+ /**
+ * Another constructor, which allows to use a custom editing widget
+ * instead of the standard KLineEdit widget. E.g. you can use a
+ * KURLRequester or a KComboBox as input widget. The custom
+ * editor must consist of a lineedit and optionally another widget that
+ * is used as representation. A KComboBox or a KURLRequester have a
+ * KLineEdit as child-widget for example, so the KComboBox is used as
+ * the representation widget.
+ *
+ * @see KURLRequester::customEditor()
+ * @since 3.1
+ */
+ KEditListBox( const QString& title,
+ const CustomEditor &customEditor,
+ QWidget *parent = 0, const char *name = 0,
+ bool checkAtEntering = false, int buttons = All );
+
+ virtual ~KEditListBox();
+
+ /**
+ * Return a pointer to the embedded QListBox.
+ */
+ QListBox* listBox() const { return m_listBox; }
+ /**
+ * Return a pointer to the embedded QLineEdit.
+ */
+ KLineEdit* lineEdit() const { return m_lineEdit; }
+ /**
+ * Return a pointer to the Add button
+ */
+ QPushButton* addButton() const { return servNewButton; }
+ /**
+ * Return a pointer to the Remove button
+ */
+ QPushButton* removeButton() const { return servRemoveButton; }
+ /**
+ * Return a pointer to the Up button
+ */
+ QPushButton* upButton() const { return servUpButton; }
+ /**
+ * Return a pointer to the Down button
+ */
+ QPushButton* downButton() const { return servDownButton; }
+
+ /**
+ * See QListBox::count()
+ */
+ int count() const { return int(m_listBox->count()); }
+ /**
+ * See QListBox::insertStringList()
+ */
+ void insertStringList(const QStringList& list, int index=-1);
+ /**
+ * See QListBox::insertStringList()
+ */
+ void insertStrList(const QStrList* list, int index=-1);
+ /**
+ * See QListBox::insertStrList()
+ */
+ void insertStrList(const QStrList& list, int index=-1);
+ /**
+ * See QListBox::insertStrList()
+ */
+ void insertStrList(const char ** list, int numStrings=-1, int index=-1);
+ /**
+ * See QListBox::insertItem()
+ */
+ void insertItem(const QString& text, int index=-1) {m_listBox->insertItem(text,index);}
+ /**
+ * Clears both the listbox and the line edit.
+ */
+ void clear();
+ /**
+ * See QListBox::text()
+ */
+ QString text(int index) const { return m_listBox->text(index); }
+ /**
+ * See QListBox::currentItem()
+ */
+ int currentItem() const;
+ /**
+ * See QListBox::currentText()
+ */
+ QString currentText() const { return m_listBox->currentText(); }
+
+ /**
+ * @returns a stringlist of all items in the listbox
+ */
+ QStringList items() const;
+
+ /**
+ * Clears the listbox and sets the contents to @p items
+ *
+ * @since 3.4
+ */
+ void setItems(const QStringList& items);
+
+ /**
+ * Returns which buttons are visible
+ */
+ int buttons() const;
+
+ /**
+ * Specifies which buttons should be visible
+ */
+ void setButtons( uint buttons );
+
+ signals:
+ void changed();
+
+ /**
+ * This signal is emitted when the user adds a new string to the list,
+ * the parameter is the added string.
+ * @since 3.2
+ */
+ void added( const QString & text );
+
+ /**
+ * This signal is emitted when the user removes a string from the list,
+ * the parameter is the removed string.
+ * @since 3.2
+ */
+ void removed( const QString & text );
+
+ protected slots:
+ //the names should be self-explaining
+ void moveItemUp();
+ void moveItemDown();
+ void addItem();
+ void removeItem();
+ void enableMoveButtons(int index);
+ void typedSomething(const QString& text);
+
+ private:
+ QListBox *m_listBox;
+ QPushButton *servUpButton, *servDownButton;
+ QPushButton *servNewButton, *servRemoveButton;
+ KLineEdit *m_lineEdit;
+
+ //this is called in both ctors, to avoid code duplication
+ void init( bool checkAtEntering, int buttons,
+ QWidget *representationWidget = 0L );
+
+ protected:
+ virtual void virtual_hook( int id, void* data );
+ private:
+ //our lovely private d-pointer
+ KEditListBoxPrivate* const d;
+};
+
+#endif
diff --git a/kdeui/kedittoolbar.cpp b/kdeui/kedittoolbar.cpp
new file mode 100644
index 000000000..09fa3dee0
--- /dev/null
+++ b/kdeui/kedittoolbar.cpp
@@ -0,0 +1,1455 @@
+// -*- mode: c++; c-basic-offset: 2 -*-
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Kurt Granroth <granroth@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#include <kedittoolbar.h>
+
+#include <qdom.h>
+#include <qlayout.h>
+#include <qdir.h>
+#include <qfile.h>
+#include <qheader.h>
+#include <qcombobox.h>
+#include <qdragobject.h>
+#include <qtoolbutton.h>
+#include <qlabel.h>
+#include <qvaluelist.h>
+#include <qapplication.h>
+#include <qtextstream.h>
+
+#include <kaction.h>
+#include <kstandarddirs.h>
+#include <klocale.h>
+#include <kicontheme.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kxmlguifactory.h>
+#include <kseparator.h>
+#include <kconfig.h>
+#include <klistview.h>
+#include <kdebug.h>
+#include <kpushbutton.h>
+#include <kprocio.h>
+
+static const char * const lineseparatorstring = I18N_NOOP("--- line separator ---");
+static const char * const separatorstring = I18N_NOOP("--- separator ---");
+
+#define LINESEPARATORSTRING i18n(lineseparatorstring)
+#define SEPARATORSTRING i18n(separatorstring)
+
+static void dump_xml(const QDomDocument& doc)
+{
+ QString str;
+ QTextStream ts(&str, IO_WriteOnly);
+ ts << doc;
+ kdDebug() << str << endl;
+}
+
+typedef QValueList<QDomElement> ToolbarList;
+
+namespace
+{
+class XmlData
+{
+public:
+ enum XmlType { Shell = 0, Part, Local, Merged };
+ XmlData()
+ {
+ m_isModified = false;
+ m_actionCollection = 0;
+ }
+
+ QString m_xmlFile;
+ QDomDocument m_document;
+ XmlType m_type;
+ bool m_isModified;
+ KActionCollection* m_actionCollection;
+
+ ToolbarList m_barList;
+};
+
+typedef QValueList<XmlData> XmlDataList;
+
+class ToolbarItem : public QListViewItem
+{
+public:
+ ToolbarItem(KListView *parent, const QString& tag = QString::null, const QString& name = QString::null, const QString& statusText = QString::null)
+ : QListViewItem(parent),
+ m_tag(tag),
+ m_name(name),
+ m_statusText(statusText)
+ {
+ }
+
+ ToolbarItem(KListView *parent, QListViewItem *item, const QString &tag = QString::null, const QString& name = QString::null, const QString& statusText = QString::null)
+ : QListViewItem(parent, item),
+ m_tag(tag),
+ m_name(name),
+ m_statusText(statusText)
+ {
+ }
+
+ virtual QString key(int column, bool) const
+ {
+ QString s = text( column );
+ if ( s == LINESEPARATORSTRING )
+ return "0";
+ if ( s == SEPARATORSTRING )
+ return "1";
+ return "2" + s;
+ }
+
+ void setInternalTag(const QString &tag) { m_tag = tag; }
+ void setInternalName(const QString &name) { m_name = name; }
+ void setStatusText(const QString &text) { m_statusText = text; }
+ QString internalTag() const { return m_tag; }
+ QString internalName() const { return m_name; }
+ QString statusText() const { return m_statusText; }
+private:
+ QString m_tag;
+ QString m_name;
+ QString m_statusText;
+};
+
+#define TOOLBARITEMMIMETYPE "data/x-kde.toolbar.item"
+class ToolbarItemDrag : public QStoredDrag
+{
+public:
+ ToolbarItemDrag(ToolbarItem *toolbarItem,
+ QWidget *dragSource = 0, const char *name = 0)
+ : QStoredDrag( TOOLBARITEMMIMETYPE, dragSource, name )
+ {
+ if (toolbarItem) {
+ QByteArray data;
+ QDataStream out(data, IO_WriteOnly);
+ out << toolbarItem->internalTag();
+ out << toolbarItem->internalName();
+ out << toolbarItem->statusText();
+ out << toolbarItem->text(1); // separators need this.
+ setEncodedData(data);
+ }
+ }
+
+ static bool canDecode(QMimeSource* e)
+ {
+ return e->provides(TOOLBARITEMMIMETYPE);
+ }
+
+ static bool decode( const QMimeSource* e, ToolbarItem& item )
+ {
+ if (!e)
+ return false;
+
+ QByteArray data = e->encodedData(TOOLBARITEMMIMETYPE);
+ if ( data.isEmpty() )
+ return false;
+
+ QString internalTag, internalName, statusText, text;
+ QDataStream in(data, IO_ReadOnly);
+ in >> internalTag;
+ in >> internalName;
+ in >> statusText;
+ in >> text;
+
+ item.setInternalTag( internalTag );
+ item.setInternalName( internalName );
+ item.setStatusText( statusText );
+ item.setText(1, text);
+
+ return true;
+ }
+};
+
+class ToolbarListView : public KListView
+{
+public:
+ ToolbarListView(QWidget *parent=0, const char *name=0)
+ : KListView(parent, name)
+ {
+ }
+protected:
+ virtual QDragObject *dragObject()
+ {
+ ToolbarItem *item = dynamic_cast<ToolbarItem*>(selectedItem());
+ if ( item ) {
+ ToolbarItemDrag *obj = new ToolbarItemDrag(item,
+ this, "ToolbarAction drag item");
+ const QPixmap *pm = item->pixmap(0);
+ if( pm )
+ obj->setPixmap( *pm );
+ return obj;
+ }
+ return 0;
+ }
+
+ virtual bool acceptDrag(QDropEvent *event) const
+ {
+ return ToolbarItemDrag::canDecode( event );
+ }
+};
+} // namespace
+
+class KEditToolbarWidgetPrivate
+{
+public:
+ /**
+ * @param instance The instance.
+ * @param collection In a non-KParts application, this is the collection passed
+ * to the KEditToolbar constructor.
+ * In a KParts application we let create a KXMLGUIClient create a dummy one,
+ * but it probably isn't used.
+ */
+ KEditToolbarWidgetPrivate(KInstance *instance, KActionCollection* collection)
+ : m_collection( collection )
+ {
+ m_instance = instance;
+ m_isPart = false;
+ m_helpArea = 0L;
+ m_kdialogProcess = 0;
+ }
+ ~KEditToolbarWidgetPrivate()
+ {
+ }
+
+ QString xmlFile(const QString& xml_file)
+ {
+ return xml_file.isNull() ? QString(m_instance->instanceName()) + "ui.rc" :
+ xml_file;
+ }
+
+ /**
+ * Load in the specified XML file and dump the raw xml
+ */
+ QString loadXMLFile(const QString& _xml_file)
+ {
+ QString raw_xml;
+ QString xml_file = xmlFile(_xml_file);
+ //kdDebug() << "loadXMLFile xml_file=" << xml_file << endl;
+
+ if ( !QDir::isRelativePath(xml_file) )
+ raw_xml = KXMLGUIFactory::readConfigFile(xml_file);
+ else
+ raw_xml = KXMLGUIFactory::readConfigFile(xml_file, m_instance);
+
+ return raw_xml;
+ }
+
+ /**
+ * Return a list of toolbar elements given a toplevel element
+ */
+ ToolbarList findToolbars(QDomNode n)
+ {
+ static const QString &tagToolbar = KGlobal::staticQString( "ToolBar" );
+ static const QString &attrNoEdit = KGlobal::staticQString( "noEdit" );
+ ToolbarList list;
+
+ for( ; !n.isNull(); n = n.nextSibling() )
+ {
+ QDomElement elem = n.toElement();
+ if (elem.isNull())
+ continue;
+
+ if (elem.tagName() == tagToolbar && elem.attribute( attrNoEdit ) != "true" )
+ list.append(elem);
+
+ list += findToolbars(elem.firstChild());
+ }
+
+ return list;
+ }
+
+ /**
+ * Return the name of a given toolbar
+ */
+ QString toolbarName( const XmlData& xmlData, const QDomElement& it ) const
+ {
+ static const QString &tagText = KGlobal::staticQString( "text" );
+ static const QString &tagText2 = KGlobal::staticQString( "Text" );
+ static const QString &attrName = KGlobal::staticQString( "name" );
+
+ QString name;
+ QCString txt( it.namedItem( tagText ).toElement().text().utf8() );
+ if ( txt.isEmpty() )
+ txt = it.namedItem( tagText2 ).toElement().text().utf8();
+ if ( txt.isEmpty() )
+ name = it.attribute( attrName );
+ else
+ name = i18n( txt );
+
+ // the name of the toolbar might depend on whether or not
+ // it is in kparts
+ if ( ( xmlData.m_type == XmlData::Shell ) ||
+ ( xmlData.m_type == XmlData::Part ) )
+ {
+ QString doc_name(xmlData.m_document.documentElement().attribute( attrName ));
+ name += " <" + doc_name + ">";
+ }
+ return name;
+ }
+ /**
+ * Look for a given item in the current toolbar
+ */
+ QDomElement findElementForToolbarItem( const ToolbarItem* item ) const
+ {
+ static const QString &attrName = KGlobal::staticQString( "name" );
+ for(QDomNode n = m_currentToolbarElem.firstChild(); !n.isNull(); n = n.nextSibling())
+ {
+ QDomElement elem = n.toElement();
+ if ((elem.attribute(attrName) == item->internalName()) &&
+ (elem.tagName() == item->internalTag()))
+ return elem;
+ }
+ return QDomElement();
+ }
+
+#ifndef NDEBUG
+ void dump()
+ {
+ static const char* s_XmlTypeToString[] = { "Shell", "Part", "Local", "Merged" };
+ XmlDataList::Iterator xit = m_xmlFiles.begin();
+ for ( ; xit != m_xmlFiles.end(); ++xit )
+ {
+ kdDebug(240) << "XmlData type " << s_XmlTypeToString[(*xit).m_type] << " xmlFile: " << (*xit).m_xmlFile << endl;
+ for( QValueList<QDomElement>::Iterator it = (*xit).m_barList.begin();
+ it != (*xit).m_barList.end(); ++it ) {
+ kdDebug(240) << " Toolbar: " << toolbarName( *xit, *it ) << endl;
+ }
+ if ( (*xit).m_actionCollection )
+ kdDebug(240) << " " << (*xit).m_actionCollection->count() << " actions in the collection." << endl;
+ else
+ kdDebug(240) << " no action collection." << endl;
+ }
+ }
+#endif
+
+ //QValueList<KAction*> m_actionList;
+ KActionCollection* m_collection;
+ KInstance *m_instance;
+
+ XmlData* m_currentXmlData;
+ QDomElement m_currentToolbarElem;
+
+ QString m_xmlFile;
+ QString m_globalFile;
+ QString m_rcFile;
+ QDomDocument m_localDoc;
+ bool m_isPart;
+
+ ToolbarList m_barList;
+
+ XmlDataList m_xmlFiles;
+
+ QLabel *m_comboLabel;
+ KSeparator *m_comboSeparator;
+ QLabel * m_helpArea;
+ KPushButton* m_changeIcon;
+ KProcIO* m_kdialogProcess;
+ bool m_hasKDialog;
+};
+
+class KEditToolbarPrivate {
+public:
+ bool m_accept;
+
+ // Save parameters for recreating widget after resetting toolbar
+ bool m_global;
+ KActionCollection* m_collection;
+ QString m_file;
+ KXMLGUIFactory* m_factory;
+};
+
+const char *KEditToolbar::s_defaultToolbar = 0L;
+
+KEditToolbar::KEditToolbar(KActionCollection *collection, const QString& file,
+ bool global, QWidget* parent, const char* name)
+ : KDialogBase(Swallow, i18n("Configure Toolbars"), Default|Ok|Apply|Cancel, Ok, parent, name),
+ m_widget(new KEditToolbarWidget(QString::fromLatin1(s_defaultToolbar), collection, file, global, this))
+{
+ init();
+ d->m_global = global;
+ d->m_collection = collection;
+ d->m_file = file;
+}
+
+KEditToolbar::KEditToolbar(const QString& defaultToolbar, KActionCollection *collection,
+ const QString& file, bool global,
+ QWidget* parent, const char* name)
+ : KDialogBase(Swallow, i18n("Configure Toolbars"), Default|Ok|Apply|Cancel, Ok, parent, name),
+ m_widget(new KEditToolbarWidget(defaultToolbar, collection, file, global, this))
+{
+ init();
+ d->m_global = global;
+ d->m_collection = collection;
+ d->m_file = file;
+}
+
+KEditToolbar::KEditToolbar(KXMLGUIFactory* factory, QWidget* parent, const char* name)
+ : KDialogBase(Swallow, i18n("Configure Toolbars"), Default|Ok|Apply|Cancel, Ok, parent, name),
+ m_widget(new KEditToolbarWidget(QString::fromLatin1(s_defaultToolbar), factory, this))
+{
+ init();
+ d->m_factory = factory;
+}
+
+KEditToolbar::KEditToolbar(const QString& defaultToolbar,KXMLGUIFactory* factory,
+ QWidget* parent, const char* name)
+ : KDialogBase(Swallow, i18n("Configure Toolbars"), Default|Ok|Apply|Cancel, Ok, parent, name),
+ m_widget(new KEditToolbarWidget(defaultToolbar, factory, this))
+{
+ init();
+ d->m_factory = factory;
+}
+
+void KEditToolbar::init()
+{
+ d = new KEditToolbarPrivate();
+ d->m_accept = false;
+ d->m_factory = 0;
+
+ setMainWidget(m_widget);
+
+ connect(m_widget, SIGNAL(enableOk(bool)), SLOT(acceptOK(bool)));
+ connect(m_widget, SIGNAL(enableOk(bool)), SLOT(enableButtonApply(bool)));
+ enableButtonApply(false);
+
+ setMinimumSize(sizeHint());
+ s_defaultToolbar = 0L;
+}
+
+KEditToolbar::~KEditToolbar()
+{
+ delete d;
+}
+
+void KEditToolbar::acceptOK(bool b)
+{
+ enableButtonOK(b);
+ d->m_accept = b;
+}
+
+void KEditToolbar::slotDefault()
+{
+ if ( KMessageBox::warningContinueCancel(this, i18n("Do you really want to reset all toolbars of this application to their default? The changes will be applied immediately."), i18n("Reset Toolbars"),i18n("Reset"))!=KMessageBox::Continue )
+ return;
+
+ delete m_widget;
+ d->m_accept = false;
+
+ if ( d->m_factory )
+ {
+ const QString localPrefix = locateLocal("data", "");
+ QPtrList<KXMLGUIClient> clients(d->m_factory->clients());
+ QPtrListIterator<KXMLGUIClient> it( clients );
+
+ for( ; it.current(); ++it)
+ {
+ KXMLGUIClient *client = it.current();
+ QString file = client->xmlFile();
+
+ if (file.isNull())
+ continue;
+
+ if (QDir::isRelativePath(file))
+ {
+ const KInstance *instance = client->instance() ? client->instance() : KGlobal::instance();
+ file = locateLocal("data", QString::fromLatin1( instance->instanceName() + '/' ) + file);
+ }
+ else
+ {
+ if (!file.startsWith(localPrefix))
+ continue;
+ }
+
+ if ( QFile::exists( file ) )
+ if ( !QFile::remove( file ) )
+ kdWarning() << "Could not delete " << file << endl;
+ }
+
+ m_widget = new KEditToolbarWidget(QString::null, d->m_factory, this);
+ m_widget->rebuildKXMLGUIClients();
+ }
+ else
+ {
+ int slash = d->m_file.findRev('/')+1;
+ if (slash)
+ d->m_file = d->m_file.mid(slash);
+ QString xml_file = locateLocal("data", QString::fromLatin1( KGlobal::instance()->instanceName() + '/' ) + d->m_file);
+
+ if ( QFile::exists( xml_file ) )
+ if ( !QFile::remove( xml_file ) )
+ kdWarning() << "Could not delete " << xml_file << endl;
+
+ m_widget = new KEditToolbarWidget(QString::null, d->m_collection, d->m_file, d->m_global, this);
+ }
+
+ setMainWidget(m_widget);
+ m_widget->show();
+
+ connect(m_widget, SIGNAL(enableOk(bool)), SLOT(acceptOK(bool)));
+ connect(m_widget, SIGNAL(enableOk(bool)), SLOT(enableButtonApply(bool)));
+
+ enableButtonApply(false);
+ emit newToolbarConfig();
+}
+
+void KEditToolbar::slotOk()
+{
+ if (!d->m_accept) {
+ reject();
+ return;
+ }
+
+ if (!m_widget->save())
+ {
+ // some error box here is needed
+ }
+ else
+ {
+ emit newToolbarConfig();
+ accept();
+ }
+}
+
+void KEditToolbar::slotApply()
+{
+ (void)m_widget->save();
+ enableButtonApply(false);
+ emit newToolbarConfig();
+}
+
+void KEditToolbar::setDefaultToolbar(const char *toolbarName)
+{
+ s_defaultToolbar = toolbarName;
+}
+
+KEditToolbarWidget::KEditToolbarWidget(KActionCollection *collection,
+ const QString& file,
+ bool global, QWidget *parent)
+ : QWidget(parent),
+ d(new KEditToolbarWidgetPrivate(instance(), collection))
+{
+ initNonKPart(collection, file, global);
+ // now load in our toolbar combo box
+ loadToolbarCombo();
+ adjustSize();
+ setMinimumSize(sizeHint());
+}
+
+KEditToolbarWidget::KEditToolbarWidget(const QString& defaultToolbar,
+ KActionCollection *collection,
+ const QString& file, bool global,
+ QWidget *parent)
+ : QWidget(parent),
+ d(new KEditToolbarWidgetPrivate(instance(), collection))
+{
+ initNonKPart(collection, file, global);
+ // now load in our toolbar combo box
+ loadToolbarCombo(defaultToolbar);
+ adjustSize();
+ setMinimumSize(sizeHint());
+}
+
+KEditToolbarWidget::KEditToolbarWidget( KXMLGUIFactory* factory,
+ QWidget *parent)
+ : QWidget(parent),
+ d(new KEditToolbarWidgetPrivate(instance(), KXMLGUIClient::actionCollection() /*create new one*/))
+{
+ initKPart(factory);
+ // now load in our toolbar combo box
+ loadToolbarCombo();
+ adjustSize();
+ setMinimumSize(sizeHint());
+}
+
+KEditToolbarWidget::KEditToolbarWidget( const QString& defaultToolbar,
+ KXMLGUIFactory* factory,
+ QWidget *parent)
+ : QWidget(parent),
+ d(new KEditToolbarWidgetPrivate(instance(), KXMLGUIClient::actionCollection() /*create new one*/))
+{
+ initKPart(factory);
+ // now load in our toolbar combo box
+ loadToolbarCombo(defaultToolbar);
+ adjustSize();
+ setMinimumSize(sizeHint());
+}
+
+KEditToolbarWidget::~KEditToolbarWidget()
+{
+ delete d;
+}
+
+void KEditToolbarWidget::initNonKPart(KActionCollection *collection,
+ const QString& file, bool global)
+{
+ //d->m_actionList = collection->actions();
+
+ // handle the merging
+ if (global)
+ setXMLFile(locate("config", "ui/ui_standards.rc"));
+ QString localXML = d->loadXMLFile(file);
+ setXML(localXML, true);
+
+ // reusable vars
+ QDomElement elem;
+
+ // first, get all of the necessary info for our local xml
+ XmlData local;
+ local.m_xmlFile = d->xmlFile(file);
+ local.m_type = XmlData::Local;
+ local.m_document.setContent(localXML);
+ elem = local.m_document.documentElement().toElement();
+ local.m_barList = d->findToolbars(elem);
+ local.m_actionCollection = collection;
+ d->m_xmlFiles.append(local);
+
+ // then, the merged one (ui_standards + local xml)
+ XmlData merge;
+ merge.m_xmlFile = QString::null;
+ merge.m_type = XmlData::Merged;
+ merge.m_document = domDocument();
+ elem = merge.m_document.documentElement().toElement();
+ merge.m_barList = d->findToolbars(elem);
+ merge.m_actionCollection = collection;
+ d->m_xmlFiles.append(merge);
+
+#ifndef NDEBUG
+ //d->dump();
+#endif
+
+ // okay, that done, we concern ourselves with the GUI aspects
+ setupLayout();
+}
+
+void KEditToolbarWidget::initKPart(KXMLGUIFactory* factory)
+{
+ // reusable vars
+ QDomElement elem;
+
+ setFactory( factory );
+ actionCollection()->setWidget( this );
+
+ // add all of the client data
+ QPtrList<KXMLGUIClient> clients(factory->clients());
+ QPtrListIterator<KXMLGUIClient> it( clients );
+ for( ; it.current(); ++it)
+ {
+ KXMLGUIClient *client = it.current();
+
+ if (client->xmlFile().isNull())
+ continue;
+
+ XmlData data;
+ data.m_xmlFile = client->localXMLFile();
+ if ( it.atFirst() )
+ data.m_type = XmlData::Shell;
+ else
+ data.m_type = XmlData::Part;
+ data.m_document.setContent( KXMLGUIFactory::readConfigFile( client->xmlFile(), client->instance() ) );
+ elem = data.m_document.documentElement().toElement();
+ data.m_barList = d->findToolbars(elem);
+ data.m_actionCollection = client->actionCollection();
+ d->m_xmlFiles.append(data);
+
+ //d->m_actionList += client->actionCollection()->actions();
+ }
+
+#ifndef NDEBUG
+ //d->dump();
+#endif
+
+ // okay, that done, we concern ourselves with the GUI aspects
+ setupLayout();
+}
+
+bool KEditToolbarWidget::save()
+{
+ //kdDebug(240) << "KEditToolbarWidget::save" << endl;
+ XmlDataList::Iterator it = d->m_xmlFiles.begin();
+ for ( ; it != d->m_xmlFiles.end(); ++it)
+ {
+ // let's not save non-modified files
+ if ( !((*it).m_isModified) )
+ continue;
+
+ // let's also skip (non-existent) merged files
+ if ( (*it).m_type == XmlData::Merged )
+ continue;
+
+ dump_xml((*it).m_document);
+
+ kdDebug(240) << "Saving " << (*it).m_xmlFile << endl;
+ // if we got this far, we might as well just save it
+ KXMLGUIFactory::saveConfigFile((*it).m_document, (*it).m_xmlFile);
+ }
+
+ if ( !factory() )
+ return true;
+
+ rebuildKXMLGUIClients();
+
+ return true;
+}
+
+void KEditToolbarWidget::rebuildKXMLGUIClients()
+{
+ if ( !factory() )
+ return;
+
+ QPtrList<KXMLGUIClient> clients(factory()->clients());
+ //kdDebug(240) << "factory: " << clients.count() << " clients" << endl;
+
+ // remove the elements starting from the last going to the first
+ KXMLGUIClient *client = clients.last();
+ while ( client )
+ {
+ //kdDebug(240) << "factory->removeClient " << client << endl;
+ factory()->removeClient( client );
+ client = clients.prev();
+ }
+
+ KXMLGUIClient *firstClient = clients.first();
+
+ // now, rebuild the gui from the first to the last
+ //kdDebug(240) << "rebuilding the gui" << endl;
+ QPtrListIterator<KXMLGUIClient> cit( clients );
+ for( ; cit.current(); ++cit)
+ {
+ KXMLGUIClient* client = cit.current();
+ //kdDebug(240) << "updating client " << client << " " << client->instance()->instanceName() << " xmlFile=" << client->xmlFile() << endl;
+ QString file( client->xmlFile() ); // before setting ui_standards!
+ if ( !file.isEmpty() )
+ {
+ // passing an empty stream forces the clients to reread the XML
+ client->setXMLGUIBuildDocument( QDomDocument() );
+
+ // for the shell, merge in ui_standards.rc
+ if ( client == firstClient ) // same assumption as in the ctor: first==shell
+ client->setXMLFile(locate("config", "ui/ui_standards.rc"));
+
+ // and this forces it to use the *new* XML file
+ client->setXMLFile( file, client == firstClient /* merge if shell */ );
+ }
+ }
+
+ // Now we can add the clients to the factory
+ // We don't do it in the loop above because adding a part automatically
+ // adds its plugins, so we must make sure the plugins were updated first.
+ cit.toFirst();
+ for( ; cit.current(); ++cit)
+ factory()->addClient( cit.current() );
+}
+
+void KEditToolbarWidget::setupLayout()
+{
+ // the toolbar name combo
+ d->m_comboLabel = new QLabel(i18n("&Toolbar:"), this);
+ m_toolbarCombo = new QComboBox(this);
+ m_toolbarCombo->setEnabled(false);
+ d->m_comboLabel->setBuddy(m_toolbarCombo);
+ d->m_comboSeparator = new KSeparator(this);
+ connect(m_toolbarCombo, SIGNAL(activated(const QString&)),
+ this, SLOT(slotToolbarSelected(const QString&)));
+
+// QPushButton *new_toolbar = new QPushButton(i18n("&New"), this);
+// new_toolbar->setPixmap(BarIcon("filenew", KIcon::SizeSmall));
+// new_toolbar->setEnabled(false); // disabled until implemented
+// QPushButton *del_toolbar = new QPushButton(i18n("&Delete"), this);
+// del_toolbar->setPixmap(BarIcon("editdelete", KIcon::SizeSmall));
+// del_toolbar->setEnabled(false); // disabled until implemented
+
+ // our list of inactive actions
+ QLabel *inactive_label = new QLabel(i18n("A&vailable actions:"), this);
+ m_inactiveList = new ToolbarListView(this);
+ m_inactiveList->setDragEnabled(true);
+ m_inactiveList->setAcceptDrops(true);
+ m_inactiveList->setDropVisualizer(false);
+ m_inactiveList->setAllColumnsShowFocus(true);
+ m_inactiveList->setMinimumSize(180, 250);
+ m_inactiveList->header()->hide();
+ m_inactiveList->addColumn(""); // icon
+ int column2 = m_inactiveList->addColumn(""); // text
+ m_inactiveList->setSorting( column2 );
+ inactive_label->setBuddy(m_inactiveList);
+ connect(m_inactiveList, SIGNAL(selectionChanged(QListViewItem *)),
+ this, SLOT(slotInactiveSelected(QListViewItem *)));
+ connect(m_inactiveList, SIGNAL( doubleClicked( QListViewItem *, const QPoint &, int )),
+ this, SLOT(slotInsertButton()));
+
+ // our list of active actions
+ QLabel *active_label = new QLabel(i18n("Curr&ent actions:"), this);
+ m_activeList = new ToolbarListView(this);
+ m_activeList->setDragEnabled(true);
+ m_activeList->setAcceptDrops(true);
+ m_activeList->setDropVisualizer(true);
+ m_activeList->setAllColumnsShowFocus(true);
+ m_activeList->setMinimumWidth(m_inactiveList->minimumWidth());
+ m_activeList->header()->hide();
+ m_activeList->addColumn(""); // icon
+ m_activeList->addColumn(""); // text
+ m_activeList->setSorting(-1);
+ active_label->setBuddy(m_activeList);
+
+ connect(m_inactiveList, SIGNAL(dropped(KListView*,QDropEvent*,QListViewItem*)),
+ this, SLOT(slotDropped(KListView*,QDropEvent*,QListViewItem*)));
+ connect(m_activeList, SIGNAL(dropped(KListView*,QDropEvent*,QListViewItem*)),
+ this, SLOT(slotDropped(KListView*,QDropEvent*,QListViewItem*)));
+ connect(m_activeList, SIGNAL(selectionChanged(QListViewItem *)),
+ this, SLOT(slotActiveSelected(QListViewItem *)));
+ connect(m_activeList, SIGNAL( doubleClicked( QListViewItem *, const QPoint &, int )),
+ this, SLOT(slotRemoveButton()));
+
+ // "change icon" button
+ d->m_changeIcon = new KPushButton( i18n( "Change &Icon..." ), this );
+ QString kdialogExe = KStandardDirs::findExe(QString::fromLatin1("kdialog"));
+ d->m_hasKDialog = !kdialogExe.isEmpty();
+ d->m_changeIcon->setEnabled( d->m_hasKDialog );
+
+ connect( d->m_changeIcon, SIGNAL( clicked() ),
+ this, SLOT( slotChangeIcon() ) );
+
+ // The buttons in the middle
+ QIconSet iconSet;
+
+ m_upAction = new QToolButton(this);
+ iconSet = SmallIconSet( "up" );
+ m_upAction->setIconSet( iconSet );
+ m_upAction->setEnabled(false);
+ m_upAction->setAutoRepeat(true);
+ connect(m_upAction, SIGNAL(clicked()), SLOT(slotUpButton()));
+
+ m_insertAction = new QToolButton(this);
+ iconSet = QApplication::reverseLayout() ? SmallIconSet( "back" ) : SmallIconSet( "forward" );
+ m_insertAction->setIconSet( iconSet );
+ m_insertAction->setEnabled(false);
+ connect(m_insertAction, SIGNAL(clicked()), SLOT(slotInsertButton()));
+
+ m_removeAction = new QToolButton(this);
+ iconSet = QApplication::reverseLayout() ? SmallIconSet( "forward" ) : SmallIconSet( "back" );
+ m_removeAction->setIconSet( iconSet );
+ m_removeAction->setEnabled(false);
+ connect(m_removeAction, SIGNAL(clicked()), SLOT(slotRemoveButton()));
+
+ m_downAction = new QToolButton(this);
+ iconSet = SmallIconSet( "down" );
+ m_downAction->setIconSet( iconSet );
+ m_downAction->setEnabled(false);
+ m_downAction->setAutoRepeat(true);
+ connect(m_downAction, SIGNAL(clicked()), SLOT(slotDownButton()));
+
+ d->m_helpArea = new QLabel(this);
+ d->m_helpArea->setAlignment( Qt::WordBreak );
+
+ // now start with our layouts
+ QVBoxLayout *top_layout = new QVBoxLayout(this, 0, KDialog::spacingHint());
+
+ QVBoxLayout *name_layout = new QVBoxLayout(KDialog::spacingHint());
+ QHBoxLayout *list_layout = new QHBoxLayout(KDialog::spacingHint());
+
+ QVBoxLayout *inactive_layout = new QVBoxLayout(KDialog::spacingHint());
+ QVBoxLayout *active_layout = new QVBoxLayout(KDialog::spacingHint());
+ QHBoxLayout *changeIcon_layout = new QHBoxLayout(KDialog::spacingHint());
+
+ QGridLayout *button_layout = new QGridLayout(5, 3, 0);
+
+ name_layout->addWidget(d->m_comboLabel);
+ name_layout->addWidget(m_toolbarCombo);
+// name_layout->addWidget(new_toolbar);
+// name_layout->addWidget(del_toolbar);
+
+ button_layout->setRowStretch( 0, 10 );
+ button_layout->addWidget(m_upAction, 1, 1);
+ button_layout->addWidget(m_removeAction, 2, 0);
+ button_layout->addWidget(m_insertAction, 2, 2);
+ button_layout->addWidget(m_downAction, 3, 1);
+ button_layout->setRowStretch( 4, 10 );
+
+ inactive_layout->addWidget(inactive_label);
+ inactive_layout->addWidget(m_inactiveList, 1);
+
+ active_layout->addWidget(active_label);
+ active_layout->addWidget(m_activeList, 1);
+ active_layout->addLayout(changeIcon_layout);
+
+ changeIcon_layout->addStretch( 1 );
+ changeIcon_layout->addWidget( d->m_changeIcon );
+ changeIcon_layout->addStretch( 1 );
+
+ list_layout->addLayout(inactive_layout);
+ list_layout->addLayout(button_layout);
+ list_layout->addLayout(active_layout);
+
+ top_layout->addLayout(name_layout);
+ top_layout->addWidget(d->m_comboSeparator);
+ top_layout->addLayout(list_layout,10);
+ top_layout->addWidget(d->m_helpArea);
+ top_layout->addWidget(new KSeparator(this));
+}
+
+void KEditToolbarWidget::loadToolbarCombo(const QString& defaultToolbar)
+{
+ static const QString &attrName = KGlobal::staticQString( "name" );
+ // just in case, we clear our combo
+ m_toolbarCombo->clear();
+
+ int defaultToolbarId = -1;
+ int count = 0;
+ // load in all of the toolbar names into this combo box
+ XmlDataList::Iterator xit = d->m_xmlFiles.begin();
+ for ( ; xit != d->m_xmlFiles.end(); ++xit)
+ {
+ // skip the local one in favor of the merged
+ if ( (*xit).m_type == XmlData::Local )
+ continue;
+
+ // each xml file may have any number of toolbars
+ ToolbarList::Iterator it = (*xit).m_barList.begin();
+ for ( ; it != (*xit).m_barList.end(); ++it)
+ {
+ QString name = d->toolbarName( *xit, *it );
+ m_toolbarCombo->setEnabled( true );
+ m_toolbarCombo->insertItem( name );
+ if (defaultToolbarId == -1 && (name == defaultToolbar || defaultToolbar == (*it).attribute( attrName )))
+ defaultToolbarId = count;
+ count++;
+ }
+ }
+ bool showCombo = (count > 1);
+ d->m_comboLabel->setShown(showCombo);
+ d->m_comboSeparator->setShown(showCombo);
+ m_toolbarCombo->setShown(showCombo);
+ if (defaultToolbarId == -1)
+ defaultToolbarId = 0;
+ // we want to the specified item selected and its actions loaded
+ m_toolbarCombo->setCurrentItem(defaultToolbarId);
+ slotToolbarSelected(m_toolbarCombo->currentText());
+}
+
+void KEditToolbarWidget::loadActionList(QDomElement& elem)
+{
+ static const QString &tagSeparator = KGlobal::staticQString( "Separator" );
+ static const QString &tagMerge = KGlobal::staticQString( "Merge" );
+ static const QString &tagActionList= KGlobal::staticQString( "ActionList" );
+ static const QString &attrName = KGlobal::staticQString( "name" );
+ static const QString &attrLineSeparator = KGlobal::staticQString( "lineSeparator" );
+
+ int sep_num = 0;
+ QString sep_name("separator_%1");
+
+ // clear our lists
+ m_inactiveList->clear();
+ m_activeList->clear();
+ m_insertAction->setEnabled(false);
+ m_removeAction->setEnabled(false);
+ m_upAction->setEnabled(false);
+ m_downAction->setEnabled(false);
+
+ // We'll use this action collection
+ KActionCollection* actionCollection = d->m_currentXmlData->m_actionCollection;
+
+ // store the names of our active actions
+ QMap<QString, bool> active_list;
+
+ // see if our current action is in this toolbar
+ KIconLoader *loader = KGlobal::instance()->iconLoader();
+ QDomNode n = elem.lastChild();
+ for( ; !n.isNull(); n = n.previousSibling() )
+ {
+ QDomElement it = n.toElement();
+ if (it.isNull()) continue;
+ if (it.tagName() == tagSeparator)
+ {
+ ToolbarItem *act = new ToolbarItem(m_activeList, tagSeparator, sep_name.arg(sep_num++), QString::null);
+ bool isLineSep = ( it.attribute(attrLineSeparator, "true").lower() == QString::fromLatin1("true") );
+ if(isLineSep)
+ act->setText(1, LINESEPARATORSTRING);
+ else
+ act->setText(1, SEPARATORSTRING);
+ it.setAttribute( attrName, act->internalName() );
+ continue;
+ }
+
+ if (it.tagName() == tagMerge)
+ {
+ // Merge can be named or not - use the name if there is one
+ QString name = it.attribute( attrName );
+ ToolbarItem *act = new ToolbarItem(m_activeList, tagMerge, name, i18n("This element will be replaced with all the elements of an embedded component."));
+ if ( name.isEmpty() )
+ act->setText(1, i18n("<Merge>"));
+ else
+ act->setText(1, i18n("<Merge %1>").arg(name));
+ continue;
+ }
+
+ if (it.tagName() == tagActionList)
+ {
+ ToolbarItem *act = new ToolbarItem(m_activeList, tagActionList, it.attribute(attrName), i18n("This is a dynamic list of actions. You can move it, but if you remove it you won't be able to re-add it.") );
+ act->setText(1, i18n("ActionList: %1").arg(it.attribute(attrName)));
+ continue;
+ }
+
+ // iterate through this client's actions
+ // This used to iterate through _all_ actions, but we don't support
+ // putting any action into any client...
+ for (unsigned int i = 0; i < actionCollection->count(); i++)
+ {
+ KAction *action = actionCollection->action( i );
+
+ // do we have a match?
+ if (it.attribute( attrName ) == action->name())
+ {
+ // we have a match!
+ ToolbarItem *act = new ToolbarItem(m_activeList, it.tagName(), action->name(), action->toolTip());
+ act->setText(1, action->plainText());
+ if (action->hasIcon())
+ if (!action->icon().isEmpty())
+ act->setPixmap(0, loader->loadIcon(action->icon(), KIcon::Toolbar, 16, KIcon::DefaultState, 0, true) );
+ else // Has iconset
+ act->setPixmap(0, action->iconSet(KIcon::Toolbar).pixmap());
+
+ active_list.insert(action->name(), true);
+ break;
+ }
+ }
+ }
+
+ // go through the rest of the collection
+ for (int i = actionCollection->count() - 1; i > -1; --i)
+ {
+ KAction *action = actionCollection->action( i );
+
+ // skip our active ones
+ if (active_list.contains(action->name()))
+ continue;
+
+ ToolbarItem *act = new ToolbarItem(m_inactiveList, tagActionList, action->name(), action->toolTip());
+ act->setText(1, action->plainText());
+ if (action->hasIcon())
+ if (!action->icon().isEmpty())
+ act->setPixmap(0, loader->loadIcon(action->icon(), KIcon::Toolbar, 16, KIcon::DefaultState, 0, true) );
+ else // Has iconset
+ act->setPixmap(0, action->iconSet(KIcon::Toolbar).pixmap());
+ }
+
+ // finally, add default separators to the inactive list
+ ToolbarItem *act = new ToolbarItem(m_inactiveList, tagSeparator, sep_name.arg(sep_num++), QString::null);
+ act->setText(1, LINESEPARATORSTRING);
+ act = new ToolbarItem(m_inactiveList, tagSeparator, sep_name.arg(sep_num++), QString::null);
+ act->setText(1, SEPARATORSTRING);
+}
+
+KActionCollection *KEditToolbarWidget::actionCollection() const
+{
+ return d->m_collection;
+}
+
+void KEditToolbarWidget::slotToolbarSelected(const QString& _text)
+{
+ // iterate through everything
+ XmlDataList::Iterator xit = d->m_xmlFiles.begin();
+ for ( ; xit != d->m_xmlFiles.end(); ++xit)
+ {
+ // each xml file may have any number of toolbars
+ ToolbarList::Iterator it = (*xit).m_barList.begin();
+ for ( ; it != (*xit).m_barList.end(); ++it)
+ {
+ QString name = d->toolbarName( *xit, *it );
+ // is this our toolbar?
+ if ( name == _text )
+ {
+ // save our current settings
+ d->m_currentXmlData = & (*xit);
+ d->m_currentToolbarElem = (*it);
+
+ // load in our values
+ loadActionList(d->m_currentToolbarElem);
+
+ if ((*xit).m_type == XmlData::Part || (*xit).m_type == XmlData::Shell)
+ setDOMDocument( (*xit).m_document );
+ return;
+ }
+ }
+ }
+}
+
+void KEditToolbarWidget::slotInactiveSelected(QListViewItem *item)
+{
+ ToolbarItem* toolitem = static_cast<ToolbarItem *>(item);
+ if (item)
+ {
+ m_insertAction->setEnabled(true);
+ QString statusText = toolitem->statusText();
+ d->m_helpArea->setText( statusText );
+ }
+ else
+ {
+ m_insertAction->setEnabled(false);
+ d->m_helpArea->setText( QString::null );
+ }
+}
+
+void KEditToolbarWidget::slotActiveSelected(QListViewItem *item)
+{
+ ToolbarItem* toolitem = static_cast<ToolbarItem *>(item);
+ m_removeAction->setEnabled( item );
+
+ static const QString &tagAction = KGlobal::staticQString( "Action" );
+ d->m_changeIcon->setEnabled( item &&
+ d->m_hasKDialog &&
+ toolitem->internalTag() == tagAction );
+
+ if (item)
+ {
+ if (item->itemAbove())
+ m_upAction->setEnabled(true);
+ else
+ m_upAction->setEnabled(false);
+
+ if (item->itemBelow())
+ m_downAction->setEnabled(true);
+ else
+ m_downAction->setEnabled(false);
+ QString statusText = toolitem->statusText();
+ d->m_helpArea->setText( statusText );
+ }
+ else
+ {
+ m_upAction->setEnabled(false);
+ m_downAction->setEnabled(false);
+ d->m_helpArea->setText( QString::null );
+ }
+}
+
+void KEditToolbarWidget::slotDropped(KListView *list, QDropEvent *e, QListViewItem *after)
+{
+ ToolbarItem *item = new ToolbarItem(m_inactiveList); // needs parent, use inactiveList temporarily
+ if(!ToolbarItemDrag::decode(e, *item)) {
+ delete item;
+ return;
+ }
+
+ if (list == m_activeList) {
+ if (e->source() == m_activeList) {
+ // has been dragged within the active list (moved).
+ moveActive(item, after);
+ }
+ else
+ insertActive(item, after, true);
+ } else if (list == m_inactiveList) {
+ // has been dragged to the inactive list -> remove from the active list.
+ removeActive(item);
+ }
+
+ delete item; item = 0; // not neded anymore
+
+ // we're modified, so let this change
+ emit enableOk(true);
+
+ slotToolbarSelected( m_toolbarCombo->currentText() );
+}
+
+void KEditToolbarWidget::slotInsertButton()
+{
+ ToolbarItem *item = (ToolbarItem*)m_inactiveList->currentItem();
+ insertActive(item, m_activeList->currentItem(), false);
+
+ // we're modified, so let this change
+ emit enableOk(true);
+
+ // TODO: #### this causes #97572.
+ // It would be better to just "delete item; loadActions( ... , ActiveListOnly );" or something.
+ slotToolbarSelected( m_toolbarCombo->currentText() );
+}
+
+void KEditToolbarWidget::slotRemoveButton()
+{
+ removeActive( dynamic_cast<ToolbarItem*>(m_activeList->currentItem()) );
+
+ // we're modified, so let this change
+ emit enableOk(true);
+
+ slotToolbarSelected( m_toolbarCombo->currentText() );
+}
+
+void KEditToolbarWidget::insertActive(ToolbarItem *item, QListViewItem *before, bool prepend)
+{
+ if (!item)
+ return;
+
+ static const QString &tagAction = KGlobal::staticQString( "Action" );
+ static const QString &tagSeparator = KGlobal::staticQString( "Separator" );
+ static const QString &attrName = KGlobal::staticQString( "name" );
+ static const QString &attrLineSeparator = KGlobal::staticQString( "lineSeparator" );
+ static const QString &attrNoMerge = KGlobal::staticQString( "noMerge" );
+
+ QDomElement new_item;
+ // let's handle the separator specially
+ if (item->text(1) == LINESEPARATORSTRING) {
+ new_item = domDocument().createElement(tagSeparator);
+ } else if (item->text(1) == SEPARATORSTRING) {
+ new_item = domDocument().createElement(tagSeparator);
+ new_item.setAttribute(attrLineSeparator, "false");
+ } else
+ new_item = domDocument().createElement(tagAction);
+ new_item.setAttribute(attrName, item->internalName());
+
+ if (before)
+ {
+ // we have the item in the active list which is before the new
+ // item.. so let's try our best to add our new item right after it
+ ToolbarItem *act_item = (ToolbarItem*)before;
+ QDomElement elem = d->findElementForToolbarItem( act_item );
+ Q_ASSERT( !elem.isNull() );
+ d->m_currentToolbarElem.insertAfter(new_item, elem);
+ }
+ else
+ {
+ // simply put it at the beginning or the end of the list.
+ if (prepend)
+ d->m_currentToolbarElem.insertBefore(new_item, d->m_currentToolbarElem.firstChild());
+ else
+ d->m_currentToolbarElem.appendChild(new_item);
+ }
+
+ // and set this container as a noMerge
+ d->m_currentToolbarElem.setAttribute( attrNoMerge, "1");
+
+ // update the local doc
+ updateLocal(d->m_currentToolbarElem);
+}
+
+void KEditToolbarWidget::removeActive(ToolbarItem *item)
+{
+ if (!item)
+ return;
+
+ static const QString &attrNoMerge = KGlobal::staticQString( "noMerge" );
+
+ // we're modified, so let this change
+ emit enableOk(true);
+
+ // now iterate through to find the child to nuke
+ QDomElement elem = d->findElementForToolbarItem( item );
+ if ( !elem.isNull() )
+ {
+ // nuke myself!
+ d->m_currentToolbarElem.removeChild(elem);
+
+ // and set this container as a noMerge
+ d->m_currentToolbarElem.setAttribute( attrNoMerge, "1");
+
+ // update the local doc
+ updateLocal(d->m_currentToolbarElem);
+ }
+}
+
+void KEditToolbarWidget::slotUpButton()
+{
+ ToolbarItem *item = (ToolbarItem*)m_activeList->currentItem();
+
+ // make sure we're not the top item already
+ if (!item->itemAbove())
+ return;
+
+ // we're modified, so let this change
+ emit enableOk(true);
+
+ moveActive( item, item->itemAbove()->itemAbove() );
+ delete item;
+}
+
+void KEditToolbarWidget::moveActive( ToolbarItem* item, QListViewItem* before )
+{
+ QDomElement e = d->findElementForToolbarItem( item );
+
+ if ( e.isNull() )
+ return;
+
+ // cool, i found me. now clone myself
+ ToolbarItem *clone = new ToolbarItem(m_activeList,
+ before,
+ item->internalTag(),
+ item->internalName(),
+ item->statusText());
+
+ clone->setText(1, item->text(1));
+
+ // only set new pixmap if exists
+ if( item->pixmap(0) )
+ clone->setPixmap(0, *item->pixmap(0));
+
+ // select my clone
+ m_activeList->setSelected(clone, true);
+
+ // make clone visible
+ m_activeList->ensureItemVisible(clone);
+
+ // and do the real move in the DOM
+ if ( !before )
+ d->m_currentToolbarElem.insertBefore(e, d->m_currentToolbarElem.firstChild() );
+ else
+ d->m_currentToolbarElem.insertAfter(e, d->findElementForToolbarItem( (ToolbarItem*)before ));
+
+ // and set this container as a noMerge
+ static const QString &attrNoMerge = KGlobal::staticQString( "noMerge" );
+ d->m_currentToolbarElem.setAttribute( attrNoMerge, "1");
+
+ // update the local doc
+ updateLocal(d->m_currentToolbarElem);
+}
+
+void KEditToolbarWidget::slotDownButton()
+{
+ ToolbarItem *item = (ToolbarItem*)m_activeList->currentItem();
+
+ // make sure we're not the bottom item already
+ if (!item->itemBelow())
+ return;
+
+ // we're modified, so let this change
+ emit enableOk(true);
+
+ moveActive( item, item->itemBelow() );
+ delete item;
+}
+
+void KEditToolbarWidget::updateLocal(QDomElement& elem)
+{
+ static const QString &attrName = KGlobal::staticQString( "name" );
+
+ XmlDataList::Iterator xit = d->m_xmlFiles.begin();
+ for ( ; xit != d->m_xmlFiles.end(); ++xit)
+ {
+ if ( (*xit).m_type == XmlData::Merged )
+ continue;
+
+ if ( (*xit).m_type == XmlData::Shell ||
+ (*xit).m_type == XmlData::Part )
+ {
+ if ( d->m_currentXmlData->m_xmlFile == (*xit).m_xmlFile )
+ {
+ (*xit).m_isModified = true;
+ return;
+ }
+
+ continue;
+ }
+
+ (*xit).m_isModified = true;
+
+ ToolbarList::Iterator it = (*xit).m_barList.begin();
+ for ( ; it != (*xit).m_barList.end(); ++it)
+ {
+ QString name( (*it).attribute( attrName ) );
+ QString tag( (*it).tagName() );
+ if ( (tag != elem.tagName()) || (name != elem.attribute(attrName)) )
+ continue;
+
+ QDomElement toolbar = (*xit).m_document.documentElement().toElement();
+ toolbar.replaceChild(elem, (*it));
+ return;
+ }
+
+ // just append it
+ QDomElement toolbar = (*xit).m_document.documentElement().toElement();
+ toolbar.appendChild(elem);
+ }
+}
+
+void KEditToolbarWidget::slotChangeIcon()
+{
+ // We can't use KIconChooser here, since it's in libkio
+ // ##### KDE4: reconsider this, e.g. move KEditToolbar to libkio
+
+ //if the process is already running (e.g. when somebody clicked the change button twice (see #127149)) - do nothing...
+ //otherwise m_kdialogProcess will be overwritten and set to zero in slotProcessExited()...crash!
+ if ( d->m_kdialogProcess && d->m_kdialogProcess->isRunning() )
+ return;
+
+ d->m_kdialogProcess = new KProcIO;
+ QString kdialogExe = KStandardDirs::findExe(QString::fromLatin1("kdialog"));
+ (*d->m_kdialogProcess) << kdialogExe;
+ (*d->m_kdialogProcess) << "--embed";
+ (*d->m_kdialogProcess) << QString::number( (ulong)topLevelWidget()->winId() );
+ (*d->m_kdialogProcess) << "--geticon";
+ (*d->m_kdialogProcess) << "Toolbar";
+ (*d->m_kdialogProcess) << "Actions";
+ if ( !d->m_kdialogProcess->start( KProcess::NotifyOnExit ) ) {
+ kdError(240) << "Can't run " << kdialogExe << endl;
+ delete d->m_kdialogProcess;
+ d->m_kdialogProcess = 0;
+ return;
+ }
+
+ m_activeList->setEnabled( false ); // don't change the current item
+ m_toolbarCombo->setEnabled( false ); // don't change the current toolbar
+
+ connect( d->m_kdialogProcess, SIGNAL( processExited( KProcess* ) ),
+ this, SLOT( slotProcessExited( KProcess* ) ) );
+}
+
+void KEditToolbarWidget::slotProcessExited( KProcess* )
+{
+ m_activeList->setEnabled( true );
+ m_toolbarCombo->setEnabled( true );
+
+ QString icon;
+
+ if (!d->m_kdialogProcess) {
+ kdError(240) << "Something is wrong here! m_kdialogProcess is zero!" << endl;
+ return;
+ }
+
+ if ( !d->m_kdialogProcess->normalExit() ||
+ d->m_kdialogProcess->exitStatus() ||
+ d->m_kdialogProcess->readln(icon, true) <= 0 ) {
+ delete d->m_kdialogProcess;
+ d->m_kdialogProcess = 0;
+ return;
+ }
+
+ ToolbarItem *item = (ToolbarItem*)m_activeList->currentItem();
+ if(item){
+ item->setPixmap(0, BarIcon(icon, 16));
+
+ Q_ASSERT( d->m_currentXmlData->m_type != XmlData::Merged );
+
+ d->m_currentXmlData->m_isModified = true;
+
+ // Get hold of ActionProperties tag
+ QDomElement elem = KXMLGUIFactory::actionPropertiesElement( d->m_currentXmlData->m_document );
+ // Find or create an element for this action
+ QDomElement act_elem = KXMLGUIFactory::findActionByName( elem, item->internalName(), true /*create*/ );
+ Q_ASSERT( !act_elem.isNull() );
+ act_elem.setAttribute( "icon", icon );
+
+ // we're modified, so let this change
+ emit enableOk(true);
+ }
+
+ delete d->m_kdialogProcess;
+ d->m_kdialogProcess = 0;
+}
+
+void KEditToolbar::virtual_hook( int id, void* data )
+{ KDialogBase::virtual_hook( id, data ); }
+
+void KEditToolbarWidget::virtual_hook( int id, void* data )
+{ KXMLGUIClient::virtual_hook( id, data ); }
+
+#include "kedittoolbar.moc"
diff --git a/kdeui/kedittoolbar.h b/kdeui/kedittoolbar.h
new file mode 100644
index 000000000..fe41775f0
--- /dev/null
+++ b/kdeui/kedittoolbar.h
@@ -0,0 +1,439 @@
+// -*- mode: c++; c-basic-offset: 2 -*-
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Kurt Granroth <granroth@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef _KEDITTOOLBAR_H
+#define _KEDITTOOLBAR_H
+
+#include <qwidget.h>
+#include <kxmlguiclient.h>
+#include <kdialogbase.h>
+
+class KProcess;
+class KActionCollection;
+class QComboBox;
+class QToolButton;
+class KListView;
+class QListViewItem;
+
+class KEditToolbarWidget;
+class KEditToolbarPrivate;
+class KEditToolbarWidgetPrivate;
+namespace
+{
+ class ToolbarItem;
+ class ToolbarListView;
+}
+/**
+ * @short A dialog used to customize or configure toolbars.
+ *
+ * This dialog only works if your application uses the XML UI
+ * framework for creating menus and toolbars. It depends on the XML
+ * files to describe the toolbar layouts and it requires the actions
+ * to determine which buttons are active.
+ *
+ * Typically, you would include the KStdAction::configureToolbars()
+ * standard action in your application. In your slot to this action,
+ * you would have something like so:
+ *
+ * \code
+ * KEditToolbar dlg(actionCollection());
+ * if (dlg.exec())
+ * {
+ * createGUI();
+ * }
+ * \endcode
+ *
+ * That code snippet also takes care of redrawing the menu and
+ * toolbars if you have made any changes.
+ *
+ * If you are using KMainWindow's settings methods (either save/apply manually
+ * or autoSaveSettings), you should write something like:
+ * \code
+ * void MyClass::slotConfigureToolbars()
+ * {
+ * saveMainWindowSettings( KGlobal::config(), "MainWindow" );
+ * KEditToolbar dlg(actionCollection());
+ * connect(&dlg,SIGNAL(newToolbarConfig()),this,SLOT(slotNewToolbarConfig()));
+ * dlg.exec();
+ * }
+ *
+ * void MyClass::slotNewToolbarConfig() // This is called when OK, Apply or Defaults is clicked
+ * {
+ * ...if you use any action list, use plugActionList on each here...
+ * createGUI();
+ * applyMainWindowSettings( KGlobal::config(), "MainWindow" );
+ * }
+ * \endcode
+ *
+ * Note that the procedure is a bit different for KParts applications.
+ * In this case, you need only pass along a pointer to your
+ * application's KXMLGUIFactory object. The editor will take care of
+ * finding all of the action collections and XML files. The editor
+ * aims to be semi-intelligent about where it assigns any
+ * modifications. In other words, it will not write out part specific
+ * changes to your shell's XML file.
+ *
+ * An example would be:
+ *
+ * \code
+ * saveMainWindowSettings( KGlobal::config(), "MainWindow" );
+ * KEditToolbar dlg(factory());
+ * connect(&dlg,SIGNAL(newToolbarConfig()),this,SLOT(slotNewToolbarConfig()));
+ * dlg.exec();
+ *
+ * void MyClass::slotNewToolbarConfig() // This is called when OK, Apply or Defaults is clicked
+ * {
+ * ...if you use any action list, use plugActionList on each here...
+ * // Do NOT call createGUI()!
+ * applyMainWindowSettings( KGlobal::config(), "MainWindow" );
+ * }
+ * \endcode
+ *
+ * @author Kurt Granroth <granroth@kde.org>
+ * @version $Id$
+ */
+class KDEUI_EXPORT KEditToolbar : public KDialogBase
+{
+ Q_OBJECT
+public:
+ /**
+ * Constructor for apps that do not use components.
+ *
+ * This is the
+ * only entry point to this class. You @em must pass along your
+ * collection of actions (some of which appear in your toolbars).
+ * The other two parameters are optional.
+ *
+ * The second parameter, xmlfile(), is the name (absolute or
+ * relative) of your application's UI resource file. If it is
+ * left blank, then the resource file: share/apps/appname/appnameui.rc
+ * is used. This is the same resource file that is used by the
+ * default createGUI() function in KMainWindow so you're usually
+ * pretty safe in leaving it blank.
+ *
+ * The third parameter, global(), controls whether or not the
+ * global resource file is used. If this is @p true, then you may
+ * edit all of the actions in your toolbars -- global ones and
+ * local one. If it is @p false, then you may edit only your
+ * application's entries. The only time you should set this to
+ * false is if your application does not use the global resource
+ * file at all (very rare).
+ *
+ * @param collection The collection of actions to work on.
+ * @param xmlfile The application's local resource file.
+ * @param global If @p true, then the global resource file will also
+ * be parsed.
+ * @param parent The parent of the dialog.
+ * @param name An internal name.
+ */
+ KEditToolbar(KActionCollection *collection,
+ const QString& xmlfile = QString::null, bool global = true,
+ QWidget* parent = 0, const char* name = 0);
+
+ //KDE 4.0: merge the two constructors
+ /* Constructor for apps that do not use components, which has an extra argument
+ * specifying the toolbar to be shown.
+ * @param defaultToolbar The toolbar with this name will appear for editing.
+ * @param collection The collection of actions to work on.
+ * @param xmlfile The application's local resource file.
+ * @param global If @p true, then the global resource file will also
+ * be parsed.
+ * @param parent The parent of the dialog.
+ * @param name An internal name.
+ * @since 3.2
+ */
+ KEditToolbar(const QString& defaultToolbar, KActionCollection *collection,
+ const QString& xmlfile = QString::null, bool global = true,
+ QWidget* parent = 0, const char* name = 0);
+ /**
+ * Constructor for KParts based apps.
+ *
+ * The main parameter, factory(), is a pointer to the
+ * XML GUI factory object for your application. It contains a list
+ * of all of the GUI clients (along with the action collections and
+ * xml files) and the toolbar editor uses that.
+ *
+ * Use this like so:
+ * \code
+ * KEditToolbar edit(factory());
+ * if ( edit.exec() )
+ * ...
+ * \endcode
+ *
+ * @param factory Your application's factory object
+ * @param parent The usual parent for the dialog.
+ * @param name An internal name.
+ *
+ * Some people seem tempted to use this also in non-KParts apps, using KMainWindow::guiFactory().
+ * This works, but only _if_ setting conserveMemory to false when calling
+ * KMainWindow::createGUI()! If not, use the other KEditToolbar constructor.
+ */
+ KEditToolbar(KXMLGUIFactory* factory, QWidget* parent = 0, const char* name = 0);
+
+ //KDE 4.0: merge the two constructors
+ /** Constructor for KParts based apps, which has an extra argument
+ * specifying the toolbar to be shown.
+ *
+ * @param defaultToolbar The toolbar with this name will appear for editing.
+ * @param factory Your application's factory object
+ * @param parent The usual parent for the dialog.
+ * @param name An internal name.
+ * @since 3.2
+ */
+ KEditToolbar(const QString& defaultToolbar, KXMLGUIFactory* factory,
+ QWidget* parent = 0, const char* name = 0);
+
+ /// destructor
+ ~KEditToolbar();
+
+ /** Sets the default toolbar, which will be auto-selected when the constructor without the
+ * defaultToolbar argument is used.
+ * @param toolbarName the name of the toolbar
+ * @since 3.3
+ */
+ static void setDefaultToolbar(const char *toolbarName);
+
+protected slots:
+ /**
+ * Overridden in order to save any changes made to the toolbars
+ */
+ virtual void slotOk();
+ /**
+ * idem
+ */
+ virtual void slotApply();
+
+ /** should OK really save?
+ * @internal
+ **/
+ void acceptOK(bool b);
+
+ /**
+ * Set toolbars to default value
+ **/
+ void slotDefault();
+
+signals:
+ /**
+ * Signal emitted when 'apply' or 'ok' is clicked or toolbars were resetted.
+ * Connect to it, to plug action lists and to call applyMainWindowSettings
+ * (see sample code in this class's documentation)
+ */
+ void newToolbarConfig();
+
+private:
+ void init();
+ KEditToolbarWidget *m_widget;
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KEditToolbarPrivate *d;
+
+ static const char *s_defaultToolbar;
+};
+
+
+/**
+ * @short A widget used to customize or configure toolbars
+ *
+ * This is the widget that does all of the work for the
+ * KEditToolbar dialog. In most cases, you will want to use the
+ * dialog instead of this widget directly.
+ *
+ * Typically, you would use this widget only if you wanted to embed
+ * the toolbar editing directly into your existing configure or
+ * preferences dialog.
+ *
+ * This widget only works if your application uses the XML UI
+ * framework for creating menus and toolbars. It depends on the XML
+ * files to describe the toolbar layouts and it requires the actions
+ * to determine which buttons are active.
+ *
+ * @author Kurt Granroth <granroth@kde.org>
+ * @version $Id$
+ */
+class KDEUI_EXPORT KEditToolbarWidget : public QWidget, virtual public KXMLGUIClient
+{
+ Q_OBJECT
+public:
+ /**
+ * Constructor. This is the only entry point to this class. You
+ * @p must pass along your collection of actions (some of which
+ * appear in your toolbars). The other three parameters are
+ * optional.
+ *
+ * The second parameter, xmlfile, is the name (absolute or
+ * relative) of your application's UI resource file. If it is
+ * left blank, then the resource file: share/apps/appname/appnameui.rc
+ * is used. This is the same resource file that is used by the
+ * default createGUI function in KMainWindow so you're usually
+ * pretty safe in leaving it blank.
+ *
+ * The third parameter, global, controls whether or not the
+ * global resource file is used. If this is true, then you may
+ * edit all of the actions in your toolbars -- global ones and
+ * local one. If it is false, then you may edit only your
+ * application's entries. The only time you should set this to
+ * false is if your application does not use the global resource
+ * file at all (very rare)
+ *
+ * The last parameter, parent, is the standard parent stuff.
+ *
+ * @param collection The collection of actions to work on
+ * @param xmlfile The application's local resource file
+ * @param global If true, then the global resource file will also
+ * be parsed
+ * @param parent This widget's parent
+ */
+ KEditToolbarWidget(KActionCollection *collection,
+ const QString& xmlfile = QString::null,
+ bool global = true, QWidget *parent = 0L);
+
+ //KDE 4.0: merge the two constructors
+ /* Same as above, with an extra agrument specifying the toolbar to be shown.
+ *
+ * @param defaultToolbar The toolbar with this name will appear for editing.
+ * @param collection The collection of actions to work on
+ * @param xmlfile The application's local resource file
+ * @param global If true, then the global resource file will also
+ * be parsed
+ * @param parent This widget's parent
+ * @since 3.2
+ */
+ KEditToolbarWidget(const QString& defaultToolbar,
+ KActionCollection *collection,
+ const QString& file = QString::null,
+ bool global = true,
+ QWidget *parent = 0L);
+
+ /**
+ * Constructor for KParts based apps.
+ *
+ * The first parameter, factory, is a pointer to the XML GUI
+ * factory object for your application. It contains a list of all
+ * of the GUI clients (along with the action collections and xml
+ * files) and the toolbar editor uses that.
+ *
+ * The second parameter, parent, is the standard parent
+ *
+ * Use this like so:
+ * \code
+ * KEditToolbar edit(factory());
+ * if ( edit.exec() )
+ * ...
+ * \endcode
+ *
+ * @param factory Your application's factory object
+ * @param parent This widget's parent
+ */
+ KEditToolbarWidget(KXMLGUIFactory* factory, QWidget *parent = 0L);
+
+ //KDE 4.0: merge the two constructors
+ /* Same as above, with an extra agrument specifying the toolbar to be shown.
+ *
+ *
+ * @param defaultToolbar The toolbar with this name will appear for editing.
+ * @param factory Your application's factory object
+ * @param parent This widget's parent
+ * @since 3.2
+ */
+ KEditToolbarWidget(const QString& defaultToolbar,
+ KXMLGUIFactory* factory,
+ QWidget *parent = 0L);
+
+ /**
+ * Destructor. Note that any changes done in this widget will
+ * @p NOT be saved in the destructor. You @p must call save()
+ * to do that.
+ */
+ virtual ~KEditToolbarWidget();
+
+ /**
+ * @internal Reimplemented for internal purposes.
+ */
+ virtual KActionCollection *actionCollection() const;
+
+ /**
+ * Save any changes the user made. The file will be in the user's
+ * local directory (usually $HOME/.kde/share/apps/\<appname\>). The
+ * filename will be the one specified in the constructor.. or the
+ * made up one if the filename was NULL.
+ *
+ * @return The status of whether or not the save succeeded.
+ */
+ bool save();
+
+ /**
+ * Remove and readd all KMXLGUIClients to update the GUI
+ * @since 3.5
+ */
+ void rebuildKXMLGUIClients();
+
+signals:
+ /**
+ * Emitted whenever any modifications are made by the user.
+ */
+ void enableOk(bool);
+
+protected slots:
+ void slotToolbarSelected(const QString& text);
+
+ void slotInactiveSelected(QListViewItem *item);
+ void slotActiveSelected(QListViewItem *item);
+
+ void slotDropped(KListView *list, QDropEvent *e, QListViewItem *after);
+
+ void slotInsertButton();
+ void slotRemoveButton();
+ void slotUpButton();
+ void slotDownButton();
+
+ void slotChangeIcon();
+
+private slots:
+ void slotProcessExited( KProcess* );
+
+protected: // KDE4: make private
+ void setupLayout();
+
+ void insertActive(ToolbarItem *item, QListViewItem *before, bool prepend = false);
+ void removeActive(ToolbarItem *item);
+ void moveActive(ToolbarItem *item, QListViewItem *before);
+ void initNonKPart(KActionCollection *collection, const QString& file, bool global);
+ void initKPart(KXMLGUIFactory* factory);
+ void loadToolbarCombo(const QString& defaultToolbar = QString::null);
+ void loadActionList(QDomElement& elem);
+ void updateLocal(QDomElement& elem);
+
+private:
+ ToolbarListView *m_inactiveList;
+ ToolbarListView *m_activeList;
+ QComboBox *m_toolbarCombo;
+
+ QToolButton *m_upAction;
+ QToolButton *m_removeAction;
+ QToolButton *m_insertAction;
+ QToolButton *m_downAction;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KEditToolbarWidgetPrivate *d;
+};
+
+#endif // _KEDITTOOLBAR_H
diff --git a/kdeui/kfontcombo.cpp b/kdeui/kfontcombo.cpp
new file mode 100644
index 000000000..d4f04812f
--- /dev/null
+++ b/kdeui/kfontcombo.cpp
@@ -0,0 +1,354 @@
+/* This file is part of the KDE libraries
+ Copyright (c) 2001 Malte Starostik <malte@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#include <qfontdatabase.h>
+#include <qlistbox.h>
+#include <qpainter.h>
+
+#include <kcharsets.h>
+#include <kconfig.h>
+#include <kglobal.h>
+#include <kfontdialog.h>
+
+#include "kfontcombo.h"
+#include "kfontcombo.moc"
+
+struct KFontComboPrivate
+{
+ KFontComboPrivate()
+ : bold(false),
+ italic(false),
+ underline(false),
+ strikeOut(false),
+ modified(false),
+ size(0),
+ lineSpacing(0)
+ {
+ }
+
+ bool bold : 1;
+ bool italic : 1;
+ bool underline : 1;
+ bool strikeOut : 1;
+ bool displayFonts : 1;
+ bool modified : 1;
+ int size;
+ int lineSpacing;
+ QString defaultFamily;
+};
+
+class KFontListItem : public QListBoxItem
+{
+public:
+ KFontListItem(const QString &fontName, KFontCombo *combo);
+ virtual ~KFontListItem();
+
+ virtual int width(const QListBox *) const;
+ virtual int height(const QListBox *) const;
+
+ void updateFont();
+
+protected:
+ virtual void paint(QPainter *p);
+
+private:
+ void createFont();
+
+private:
+ KFontCombo *m_combo;
+ QString m_fontName;
+ QFont *m_font;
+ bool m_canPaintName;
+};
+
+KFontListItem::KFontListItem(const QString &fontName, KFontCombo *combo)
+ : QListBoxItem(combo->listBox()),
+ m_combo(combo),
+ m_fontName(fontName),
+ m_font(0),
+ m_canPaintName(true)
+{
+ setText(fontName);
+}
+
+KFontListItem::~KFontListItem()
+{
+ delete m_font;
+}
+
+int KFontListItem::width(const QListBox *lb) const
+{
+ if (m_font)
+ return QFontMetrics(*m_font).width(text()) + 6;
+ return lb->fontMetrics().width(text()) + 6;
+}
+
+int KFontListItem::height(const QListBox *lb) const
+{
+ if (m_combo->d->displayFonts)
+ return m_combo->d->lineSpacing + 2;
+ QFontMetrics fm(lb->fontMetrics());
+ return fm.lineSpacing() + 2;
+}
+
+void KFontListItem::paint(QPainter *p)
+{
+ if (m_combo->d->displayFonts)
+ {
+ if (!m_font)
+ createFont();
+
+ QString t = m_fontName;
+ if (p->device() != m_combo)
+ {
+ if (m_canPaintName)
+ p->setFont(*m_font);
+ else
+ t = QString::fromLatin1("(%1)").arg(m_fontName);
+ }
+ QFontMetrics fm(p->fontMetrics());
+ p->drawText(3, (m_combo->d->lineSpacing + fm.ascent() + fm.leading() / 2) / 2, t);
+ }
+ else
+ {
+ QFontMetrics fm(p->fontMetrics());
+ p->drawText(3, fm.ascent() + fm.leading() / 2, m_fontName);
+ }
+}
+
+void KFontListItem::updateFont()
+{
+ if (!m_font)
+ return;
+
+ m_font->setBold(m_combo->d->bold);
+ m_font->setItalic(m_combo->d->italic);
+ m_font->setUnderline(m_combo->d->underline);
+ m_font->setStrikeOut(m_combo->d->strikeOut);
+ m_font->setPointSize(m_combo->d->size);
+}
+
+void KFontListItem::createFont()
+{
+ if (m_font)
+ return;
+
+ m_font = new QFont(m_fontName);
+ QFontMetrics fm(*m_font);
+ for (unsigned int i = 0; i < m_fontName.length(); ++i)
+ if (!fm.inFont(m_fontName[i]))
+ {
+ m_canPaintName = false;
+ break;
+ }
+ updateFont();
+}
+
+KFontCombo::KFontCombo(QWidget *parent, const char *name)
+ : KComboBox(true, parent, name)
+{
+ init();
+ QStringList families;
+ KFontChooser::getFontList(families, 0);
+ setFonts(families);
+}
+
+KFontCombo::KFontCombo(const QStringList &fonts, QWidget *parent, const char *name)
+ : KComboBox(true, parent, name)
+{
+ init();
+ setFonts(fonts);
+}
+
+void KFontCombo::setFonts(const QStringList &fonts)
+{
+ clear();
+ for (QStringList::ConstIterator it = fonts.begin(); it != fonts.end(); ++it)
+ new KFontListItem(*it, this);
+}
+
+/*
+ * Maintenance note: Keep in sync with KFontAction::setFont()
+ */
+void KFontCombo::setCurrentFont(const QString &family)
+{
+ QString lowerName = family.lower();
+ int c = count();
+ for(int i = 0; i < c; i++)
+ {
+ if (text(i).lower() == lowerName)
+ {
+ setCurrentItem(i);
+ d->defaultFamily = text(i);
+ d->modified = false;
+ return;
+ }
+ }
+ int x = lowerName.find(" [");
+ if (x>-1)
+ {
+ lowerName = lowerName.left(x);
+ for(int i = 0; i < c; i++)
+ {
+ if (text(i).lower() == lowerName)
+ {
+ setCurrentItem(i);
+ d->defaultFamily = text(i);
+ d->modified = false;
+ return;
+ }
+ }
+ }
+
+ lowerName += " [";
+ for(int i = 0; i < c; i++)
+ {
+ if (text(i).lower().startsWith(lowerName))
+ {
+ setCurrentItem(i);
+ d->defaultFamily = text(i);
+ d->modified = false;
+ return;
+ }
+ }
+}
+
+void KFontCombo::slotModified( int )
+{
+ d->modified = 1;
+}
+
+QString KFontCombo::currentFont() const
+{
+ if (d->modified)
+ return currentText();
+ return d->defaultFamily;
+}
+
+void KFontCombo::setCurrentItem(int i)
+{
+ d->modified = true;
+ QComboBox::setCurrentItem(i);
+}
+
+void KFontCombo::init()
+{
+ d = new KFontComboPrivate;
+ d->displayFonts = displayFonts();
+ setInsertionPolicy(NoInsertion);
+ setAutoCompletion(true);
+ setSize(12);
+ connect( this, SIGNAL(highlighted(int)), SLOT(slotModified(int)));
+}
+
+KFontCombo::~KFontCombo()
+{
+ delete d;
+}
+
+void KFontCombo::setBold(bool bold)
+{
+ if (d->bold == bold)
+ return;
+ d->bold = bold;
+ updateFonts();
+}
+
+bool KFontCombo::bold() const
+{
+ return d->bold;
+}
+
+void KFontCombo::setItalic(bool italic)
+{
+ if (d->italic == italic)
+ return;
+ d->italic = italic;
+ updateFonts();
+}
+
+bool KFontCombo::italic() const
+{
+ return d->italic;
+}
+
+void KFontCombo::setUnderline(bool underline)
+{
+ if (d->underline == underline)
+ return;
+ d->underline = underline;
+ updateFonts();
+}
+
+bool KFontCombo::underline() const
+{
+ return d->underline;
+}
+
+void KFontCombo::setStrikeOut(bool strikeOut)
+{
+ if (d->strikeOut == strikeOut)
+ return;
+ d->strikeOut = strikeOut;
+ updateFonts();
+}
+
+bool KFontCombo::strikeOut() const
+{
+ return d->strikeOut;
+}
+
+void KFontCombo::setSize(int size)
+{
+ if (d->size == size)
+ return;
+ d->size = size;
+ QFont f;
+ f.setPointSize(size);
+ QFontMetrics fm(f);
+ d->lineSpacing = fm.lineSpacing();
+ updateFonts();
+}
+
+int KFontCombo::size() const
+{
+ return d->size;
+}
+
+void KFontCombo::updateFonts()
+{
+ if (!d->displayFonts)
+ return;
+
+ for (unsigned int i = 0; i < listBox()->count(); ++i)
+ {
+ KFontListItem *item = static_cast<KFontListItem *>(listBox()->item(i));
+ item->updateFont();
+ }
+}
+
+bool KFontCombo::displayFonts()
+{
+ KConfigGroupSaver saver(KGlobal::config(), "KDE");
+ return KGlobal::config()->readBoolEntry("DisplayFontItems", true);
+}
+
+void KFontCombo::virtual_hook( int id, void* data )
+{ KComboBox::virtual_hook( id, data ); }
+
diff --git a/kdeui/kfontcombo.h b/kdeui/kfontcombo.h
new file mode 100644
index 000000000..f3c5d1169
--- /dev/null
+++ b/kdeui/kfontcombo.h
@@ -0,0 +1,179 @@
+/* This file is part of the KDE libraries
+ Copyright (c) 2001 Malte Starostik <malte@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// $Id$
+
+#ifndef _KFONTCOMBO_H_
+#define _KFONTCOMBO_H_
+
+#include <kcombobox.h>
+
+/**
+ * @short A combobox that lists the available fonts.
+ *
+ * The items are painted using the respective font itself, so the user
+ * can easily choose a font based on its look. This can be turned off
+ * globally if the user wishes so.
+ *
+ * @author Malte Starostik <malte@kde.org>
+ */
+class KDEUI_EXPORT KFontCombo : public KComboBox
+{
+ Q_OBJECT
+ Q_PROPERTY(QString family READ currentFont WRITE setCurrentFont)
+ Q_PROPERTY(bool bold READ bold WRITE setBold DESIGNABLE true)
+ Q_PROPERTY(bool italic READ italic WRITE setItalic DESIGNABLE true)
+ Q_PROPERTY(bool underline READ underline WRITE setUnderline DESIGNABLE true)
+ Q_PROPERTY(bool strikeOut READ strikeOut WRITE setStrikeOut DESIGNABLE true)
+ Q_PROPERTY(int fontSize READ size WRITE setSize DESIGNABLE true)
+public:
+ /**
+ * Constructor
+ *
+ * @param parent The parent widget
+ * @param name The object name for the widget
+ */
+ KFontCombo(QWidget *parent, const char *name = 0);
+ /**
+ * Constructor that takes an already initialzed font list
+ *
+ * @param fonts A list of fonts to show
+ * @param parent The parent widget
+ * @param name The object name for the widget
+ */
+ KFontCombo(const QStringList &fonts, QWidget *parent, const char *name = 0);
+ /**
+ * Destructor
+ */
+ virtual ~KFontCombo();
+
+ /**
+ * Sets the font list.
+ *
+ * @param fonts Font list to show
+ */
+ void setFonts(const QStringList &fonts);
+ /**
+ * Sets the currently selected font.
+ *
+ * @param family Font to select.
+ */
+ void setCurrentFont(const QString &family);
+ /**
+ * @return the currently selected font.
+ */
+ QString currentFont() const;
+
+ /**
+ * Sets the listed fonts to bold or normal.
+ *
+ * @param bold Set to true to display fonts in bold
+ */
+ void setBold(bool bold);
+ /**
+ * Returns the current bold status.
+ *
+ * @return true if fonts are bold
+ */
+ bool bold() const;
+ /**
+ * Sets the listed fonts to italic or regular.
+ *
+ * @param italic Set to true to display fonts italic
+ */
+ void setItalic(bool italic);
+ /**
+ * Returns the current italic status
+ *
+ * @return True if fonts are italic
+ */
+ bool italic() const;
+ /**
+ * Sets the listed fonts to underlined or not underlined
+ *
+ * @param underline Set to true to display fonts underlined
+ */
+ void setUnderline(bool underline);
+ /**
+ * Returns the current underline status
+ *
+ * @return True if fonts are underlined
+ */
+ bool underline() const;
+ /**
+ * Sets the listed fonts to striked out or not
+ *
+ * @param strikeOut Set to true to display fonts striked out
+ */
+ void setStrikeOut(bool strikeOut);
+ /**
+ * Returns the current strike out status
+ *
+ * @return True if fonts are striked out
+ */
+ bool strikeOut() const;
+ /**
+ * Sets the listed fonts' size
+ *
+ * @param size Set to the point size to display the fonts in
+ */
+ void setSize(int size);
+ /**
+ * Returns the current font size
+ *
+ * @return The point size of the fonts
+ */
+ int size() const;
+
+ /**
+ * Returns the user's setting of whether the items should be painted
+ * in the respective fonts or not
+ *
+ * @return True if the respective fonts are used for painting
+ */
+ static bool displayFonts();
+
+ virtual void setCurrentItem(int i);
+
+protected slots:
+ /**
+ * @internal
+ * Listens to highlighted(int)
+ */
+ void slotModified( int i );
+
+protected:
+ /**
+ * Updated the combo's listBox() to reflect changes made to the
+ * fonts' attributed
+ */
+ void updateFonts();
+
+private:
+ void init();
+
+private:
+ friend class KFontListItem;
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ struct KFontComboPrivate *d;
+};
+
+#endif
+
diff --git a/kdeui/kfontdialog.cpp b/kdeui/kfontdialog.cpp
new file mode 100644
index 000000000..64de6e4c6
--- /dev/null
+++ b/kdeui/kfontdialog.cpp
@@ -0,0 +1,799 @@
+/*
+
+ Requires the Qt widget libraries, available at no cost at
+ http://www.troll.no
+
+ Copyright (C) 1996 Bernd Johannes Wuebben <wuebben@kde.org>
+ Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+ Copyright (c) 1999 Mario Weilguni <mweilguni@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <qcombobox.h>
+#include <qcheckbox.h>
+#include <qfile.h>
+#include <qfont.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qscrollbar.h>
+#include <qstringlist.h>
+#include <qfontdatabase.h>
+#include <qwhatsthis.h>
+#include <qtooltip.h>
+
+#include <kapplication.h>
+#include <kcharsets.h>
+#include <kconfig.h>
+#include <kdialog.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+#include <qlineedit.h>
+#include <klistbox.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+#include <knuminput.h>
+
+#include "kfontdialog.moc"
+
+static int minimumListWidth( const QListBox *list )
+{
+ int w=0;
+ for( uint i=0; i<list->count(); i++ )
+ {
+ int itemWidth = list->item(i)->width(list);
+ w = QMAX(w,itemWidth);
+ }
+ if( w == 0 ) { w = 40; }
+ w += list->frameWidth() * 2;
+ w += list->verticalScrollBar()->sizeHint().width();
+ return w;
+}
+
+static int minimumListHeight( const QListBox *list, int numVisibleEntry )
+{
+ int w = list->count() > 0 ? list->item(0)->height(list) :
+ list->fontMetrics().lineSpacing();
+
+ if( w < 0 ) { w = 10; }
+ if( numVisibleEntry <= 0 ) { numVisibleEntry = 4; }
+ return ( w * numVisibleEntry + 2 * list->frameWidth() );
+}
+
+class KFontChooser::KFontChooserPrivate
+{
+public:
+ KFontChooserPrivate()
+ { m_palette.setColor(QPalette::Active, QColorGroup::Text, Qt::black);
+ m_palette.setColor(QPalette::Active, QColorGroup::Base, Qt::white); }
+ QPalette m_palette;
+};
+
+KFontChooser::KFontChooser(QWidget *parent, const char *name,
+ bool onlyFixed, const QStringList &fontList,
+ bool makeFrame, int visibleListSize, bool diff,
+ QButton::ToggleState *sizeIsRelativeState )
+ : QWidget(parent, name), usingFixed(onlyFixed)
+{
+ charsetsCombo = 0;
+
+ QString mainWhatsThisText =
+ i18n( "Here you can choose the font to be used." );
+ QWhatsThis::add( this, mainWhatsThisText );
+
+ d = new KFontChooserPrivate;
+ QVBoxLayout *topLayout = new QVBoxLayout( this, 0, KDialog::spacingHint() );
+ int checkBoxGap = KDialog::spacingHint() / 2;
+
+ QWidget *page;
+ QGridLayout *gridLayout;
+ int row = 0;
+ if( makeFrame )
+ {
+ page = new QGroupBox( i18n("Requested Font"), this );
+ topLayout->addWidget(page);
+ gridLayout = new QGridLayout( page, 5, 3, KDialog::marginHint(), KDialog::spacingHint() );
+ gridLayout->addRowSpacing( 0, fontMetrics().lineSpacing() );
+ row = 1;
+ }
+ else
+ {
+ page = new QWidget( this );
+ topLayout->addWidget(page);
+ gridLayout = new QGridLayout( page, 4, 3, 0, KDialog::spacingHint() );
+ }
+
+ //
+ // first, create the labels across the top
+ //
+ QHBoxLayout *familyLayout = new QHBoxLayout();
+ familyLayout->addSpacing( checkBoxGap );
+ if (diff) {
+ familyCheckbox = new QCheckBox(i18n("Font"), page);
+ connect(familyCheckbox, SIGNAL(toggled(bool)), SLOT(toggled_checkbox()));
+ familyLayout->addWidget(familyCheckbox, 0, Qt::AlignLeft);
+ QString familyCBToolTipText =
+ i18n("Change font family?");
+ QString familyCBWhatsThisText =
+ i18n("Enable this checkbox to change the font family settings.");
+ QWhatsThis::add( familyCheckbox, familyCBWhatsThisText );
+ QToolTip::add( familyCheckbox, familyCBToolTipText );
+ familyLabel = 0;
+ } else {
+ familyCheckbox = 0;
+ familyLabel = new QLabel( i18n("Font:"), page, "familyLabel" );
+ familyLayout->addWidget(familyLabel, 1, Qt::AlignLeft);
+ }
+ gridLayout->addLayout(familyLayout, row, 0 );
+
+ QHBoxLayout *styleLayout = new QHBoxLayout();
+ if (diff) {
+ styleCheckbox = new QCheckBox(i18n("Font style"), page);
+ connect(styleCheckbox, SIGNAL(toggled(bool)), SLOT(toggled_checkbox()));
+ styleLayout->addWidget(styleCheckbox, 0, Qt::AlignLeft);
+ QString styleCBToolTipText =
+ i18n("Change font style?");
+ QString styleCBWhatsThisText =
+ i18n("Enable this checkbox to change the font style settings.");
+ QWhatsThis::add( styleCheckbox, styleCBWhatsThisText );
+ QToolTip::add( styleCheckbox, styleCBToolTipText );
+ styleLabel = 0;
+ } else {
+ styleCheckbox = 0;
+ styleLabel = new QLabel( i18n("Font style:"), page, "styleLabel");
+ styleLayout->addWidget(styleLabel, 1, Qt::AlignLeft);
+ }
+ styleLayout->addSpacing( checkBoxGap );
+ gridLayout->addLayout(styleLayout, row, 1 );
+
+ QHBoxLayout *sizeLayout = new QHBoxLayout();
+ if (diff) {
+ sizeCheckbox = new QCheckBox(i18n("Size"),page);
+ connect(sizeCheckbox, SIGNAL(toggled(bool)), SLOT(toggled_checkbox()));
+ sizeLayout->addWidget(sizeCheckbox, 0, Qt::AlignLeft);
+ QString sizeCBToolTipText =
+ i18n("Change font size?");
+ QString sizeCBWhatsThisText =
+ i18n("Enable this checkbox to change the font size settings.");
+ QWhatsThis::add( sizeCheckbox, sizeCBWhatsThisText );
+ QToolTip::add( sizeCheckbox, sizeCBToolTipText );
+ sizeLabel = 0;
+ } else {
+ sizeCheckbox = 0;
+ sizeLabel = new QLabel( i18n("Size:"), page, "sizeLabel");
+ sizeLayout->addWidget(sizeLabel, 1, Qt::AlignLeft);
+ }
+ sizeLayout->addSpacing( checkBoxGap );
+ sizeLayout->addSpacing( checkBoxGap ); // prevent label from eating border
+ gridLayout->addLayout(sizeLayout, row, 2 );
+
+ row ++;
+
+ //
+ // now create the actual boxes that hold the info
+ //
+ familyListBox = new KListBox( page, "familyListBox");
+ familyListBox->setEnabled( !diff );
+ gridLayout->addWidget( familyListBox, row, 0 );
+ QString fontFamilyWhatsThisText =
+ i18n("Here you can choose the font family to be used." );
+ QWhatsThis::add( familyListBox, fontFamilyWhatsThisText );
+ QWhatsThis::add(diff?(QWidget *) familyCheckbox:(QWidget *) familyLabel, fontFamilyWhatsThisText );
+ connect(familyListBox, SIGNAL(highlighted(const QString &)),
+ SLOT(family_chosen_slot(const QString &)));
+ if(!fontList.isEmpty())
+ {
+ familyListBox->insertStringList(fontList);
+ }
+ else
+ {
+ fillFamilyListBox(onlyFixed);
+ }
+
+ familyListBox->setMinimumWidth( minimumListWidth( familyListBox ) );
+ familyListBox->setMinimumHeight(
+ minimumListHeight( familyListBox, visibleListSize ) );
+
+ styleListBox = new KListBox( page, "styleListBox");
+ styleListBox->setEnabled( !diff );
+ gridLayout->addWidget(styleListBox, row, 1);
+ QString fontStyleWhatsThisText =
+ i18n("Here you can choose the font style to be used." );
+ QWhatsThis::add( styleListBox, fontStyleWhatsThisText );
+ QWhatsThis::add(diff?(QWidget *)styleCheckbox:(QWidget *)styleLabel, fontFamilyWhatsThisText );
+ styleListBox->insertItem(i18n("Regular"));
+ styleListBox->insertItem(i18n("Italic"));
+ styleListBox->insertItem(i18n("Bold"));
+ styleListBox->insertItem(i18n("Bold Italic"));
+ styleListBox->setMinimumWidth( minimumListWidth( styleListBox ) );
+ styleListBox->setMinimumHeight(
+ minimumListHeight( styleListBox, visibleListSize ) );
+
+ connect(styleListBox, SIGNAL(highlighted(const QString &)),
+ SLOT(style_chosen_slot(const QString &)));
+
+
+ sizeListBox = new KListBox( page, "sizeListBox");
+ sizeOfFont = new KIntNumInput( page, "sizeOfFont");
+ sizeOfFont->setMinValue(4);
+
+ sizeListBox->setEnabled( !diff );
+ sizeOfFont->setEnabled( !diff );
+ if( sizeIsRelativeState ) {
+ QString sizeIsRelativeCBText =
+ i18n("Relative");
+ QString sizeIsRelativeCBToolTipText =
+ i18n("Font size<br><i>fixed</i> or <i>relative</i><br>to environment");
+ QString sizeIsRelativeCBWhatsThisText =
+ i18n("Here you can switch between fixed font size and font size "
+ "to be calculated dynamically and adjusted to changing "
+ "environment (e.g. widget dimensions, paper size)." );
+ sizeIsRelativeCheckBox = new QCheckBox( sizeIsRelativeCBText,
+ page,
+ "sizeIsRelativeCheckBox" );
+ sizeIsRelativeCheckBox->setTristate( diff );
+ QGridLayout *sizeLayout2 = new QGridLayout( 3,2, KDialog::spacingHint()/2, "sizeLayout2" );
+ gridLayout->addLayout(sizeLayout2, row, 2);
+ sizeLayout2->setColStretch( 1, 1 ); // to prevent text from eating the right border
+ sizeLayout2->addMultiCellWidget( sizeOfFont, 0, 0, 0, 1);
+ sizeLayout2->addMultiCellWidget(sizeListBox, 1,1, 0,1);
+ sizeLayout2->addWidget(sizeIsRelativeCheckBox, 2, 0, Qt::AlignLeft);
+ QWhatsThis::add( sizeIsRelativeCheckBox, sizeIsRelativeCBWhatsThisText );
+ QToolTip::add( sizeIsRelativeCheckBox, sizeIsRelativeCBToolTipText );
+ }
+ else {
+ sizeIsRelativeCheckBox = 0L;
+ QGridLayout *sizeLayout2 = new QGridLayout( 2,1, KDialog::spacingHint()/2, "sizeLayout2" );
+ gridLayout->addLayout(sizeLayout2, row, 2);
+ sizeLayout2->addWidget( sizeOfFont, 0, 0);
+ sizeLayout2->addMultiCellWidget(sizeListBox, 1,1, 0,0);
+ }
+ QString fontSizeWhatsThisText =
+ i18n("Here you can choose the font size to be used." );
+ QWhatsThis::add( sizeListBox, fontSizeWhatsThisText );
+ QWhatsThis::add( diff?(QWidget *)sizeCheckbox:(QWidget *)sizeLabel, fontSizeWhatsThisText );
+
+ fillSizeList();
+ sizeListBox->setMinimumWidth( minimumListWidth(sizeListBox) +
+ sizeListBox->fontMetrics().maxWidth() );
+ sizeListBox->setMinimumHeight(
+ minimumListHeight( sizeListBox, visibleListSize ) );
+
+ connect( sizeOfFont, SIGNAL( valueChanged(int) ),
+ SLOT(size_value_slot(int)));
+
+ connect( sizeListBox, SIGNAL(highlighted(const QString&)),
+ SLOT(size_chosen_slot(const QString&)) );
+ sizeListBox->setSelected(sizeListBox->findItem(QString::number(10)), true); // default to 10pt.
+
+ row ++;
+
+ row ++;
+ sampleEdit = new QLineEdit( page, "sampleEdit");
+ QFont tmpFont( KGlobalSettings::generalFont().family(), 64, QFont::Black );
+ sampleEdit->setFont(tmpFont);
+ //i18n: This is a classical test phrase. (It contains all letters from A to Z.)
+ sampleEdit->setText(i18n("The Quick Brown Fox Jumps Over The Lazy Dog"));
+ sampleEdit->setMinimumHeight( sampleEdit->fontMetrics().lineSpacing() );
+ sampleEdit->setAlignment(Qt::AlignCenter);
+ gridLayout->addMultiCellWidget(sampleEdit, 4, 4, 0, 2);
+ QString sampleEditWhatsThisText =
+ i18n("This sample text illustrates the current settings. "
+ "You may edit it to test special characters." );
+ QWhatsThis::add( sampleEdit, sampleEditWhatsThisText );
+ connect(this, SIGNAL(fontSelected(const QFont &)),
+ SLOT(displaySample(const QFont &)));
+
+ QVBoxLayout *vbox;
+ if( makeFrame )
+ {
+ page = new QGroupBox( i18n("Actual Font"), this );
+ topLayout->addWidget(page);
+ vbox = new QVBoxLayout( page, KDialog::spacingHint() );
+ vbox->addSpacing( fontMetrics().lineSpacing() );
+ }
+ else
+ {
+ page = new QWidget( this );
+ topLayout->addWidget(page);
+ vbox = new QVBoxLayout( page, 0, KDialog::spacingHint() );
+ QLabel *label = new QLabel( i18n("Actual Font"), page );
+ vbox->addWidget( label );
+ }
+
+ xlfdEdit = new QLineEdit( page, "xlfdEdit" );
+ vbox->addWidget( xlfdEdit );
+
+ // lets initialize the display if possible
+ setFont( KGlobalSettings::generalFont(), usingFixed );
+ // check or uncheck or gray out the "relative" checkbox
+ if( sizeIsRelativeState && sizeIsRelativeCheckBox )
+ setSizeIsRelative( *sizeIsRelativeState );
+
+ KConfig *config = KGlobal::config();
+ KConfigGroupSaver saver(config, QString::fromLatin1("General"));
+ showXLFDArea(config->readBoolEntry(QString::fromLatin1("fontSelectorShowXLFD"), false));
+}
+
+KFontChooser::~KFontChooser()
+{
+ delete d;
+}
+
+void KFontChooser::fillSizeList() {
+ if(! sizeListBox) return; //assertion.
+
+ static const int c[] =
+ {
+ 4, 5, 6, 7,
+ 8, 9, 10, 11,
+ 12, 13, 14, 15,
+ 16, 17, 18, 19,
+ 20, 22, 24, 26,
+ 28, 32, 48, 64,
+ 0
+ };
+ for(int i = 0; c[i]; ++i)
+ {
+ sizeListBox->insertItem(QString::number(c[i]));
+ }
+}
+
+void KFontChooser::setColor( const QColor & col )
+{
+ d->m_palette.setColor( QPalette::Active, QColorGroup::Text, col );
+ QPalette pal = sampleEdit->palette();
+ pal.setColor( QPalette::Active, QColorGroup::Text, col );
+ sampleEdit->setPalette( pal );
+}
+
+QColor KFontChooser::color() const
+{
+ return d->m_palette.color( QPalette::Active, QColorGroup::Text );
+}
+
+void KFontChooser::setBackgroundColor( const QColor & col )
+{
+ d->m_palette.setColor( QPalette::Active, QColorGroup::Base, col );
+ QPalette pal = sampleEdit->palette();
+ pal.setColor( QPalette::Active, QColorGroup::Base, col );
+ sampleEdit->setPalette( pal );
+}
+
+QColor KFontChooser::backgroundColor() const
+{
+ return d->m_palette.color( QPalette::Active, QColorGroup::Base );
+}
+
+void KFontChooser::setSizeIsRelative( QButton::ToggleState relative )
+{
+ // check or uncheck or gray out the "relative" checkbox
+ if( sizeIsRelativeCheckBox ) {
+ if( QButton::NoChange == relative )
+ sizeIsRelativeCheckBox->setNoChange();
+ else
+ sizeIsRelativeCheckBox->setChecked( QButton::On == relative );
+ }
+}
+
+QButton::ToggleState KFontChooser::sizeIsRelative() const
+{
+ return sizeIsRelativeCheckBox
+ ? sizeIsRelativeCheckBox->state()
+ : QButton::NoChange;
+}
+
+QSize KFontChooser::sizeHint( void ) const
+{
+ return minimumSizeHint();
+}
+
+
+void KFontChooser::enableColumn( int column, bool state )
+{
+ if( column & FamilyList )
+ {
+ familyListBox->setEnabled(state);
+ }
+ if( column & StyleList )
+ {
+ styleListBox->setEnabled(state);
+ }
+ if( column & SizeList )
+ {
+ sizeListBox->setEnabled(state);
+ }
+}
+
+
+void KFontChooser::setFont( const QFont& aFont, bool onlyFixed )
+{
+ selFont = aFont;
+ selectedSize=aFont.pointSize();
+ if (selectedSize == -1)
+ selectedSize = QFontInfo(aFont).pointSize();
+
+ if( onlyFixed != usingFixed)
+ {
+ usingFixed = onlyFixed;
+ fillFamilyListBox(usingFixed);
+ }
+ setupDisplay();
+ displaySample(selFont);
+}
+
+
+int KFontChooser::fontDiffFlags() {
+ int diffFlags = 0;
+ if (familyCheckbox && styleCheckbox && sizeCheckbox) {
+ diffFlags = (int)(familyCheckbox->isChecked() ? FontDiffFamily : 0)
+ | (int)( styleCheckbox->isChecked() ? FontDiffStyle : 0)
+ | (int)( sizeCheckbox->isChecked() ? FontDiffSize : 0);
+ }
+ return diffFlags;
+}
+
+void KFontChooser::toggled_checkbox()
+{
+ familyListBox->setEnabled( familyCheckbox->isChecked() );
+ styleListBox->setEnabled( styleCheckbox->isChecked() );
+ sizeListBox->setEnabled( sizeCheckbox->isChecked() );
+ sizeOfFont->setEnabled( sizeCheckbox->isChecked() );
+}
+
+void KFontChooser::family_chosen_slot(const QString& family)
+{
+ QFontDatabase dbase;
+ QStringList styles = QStringList(dbase.styles(family));
+ styleListBox->clear();
+ currentStyles.clear();
+ for ( QStringList::Iterator it = styles.begin(); it != styles.end(); ++it ) {
+ QString style = *it;
+ int pos = style.find("Plain");
+ if(pos >=0) style = style.replace(pos,5,i18n("Regular"));
+ pos = style.find("Normal");
+ if(pos >=0) style = style.replace(pos,6,i18n("Regular"));
+ pos = style.find("Oblique");
+ if(pos >=0) style = style.replace(pos,7,i18n("Italic"));
+ if(!styleListBox->findItem(style)) {
+ styleListBox->insertItem(i18n(style.utf8()));
+ currentStyles.insert(i18n(style.utf8()), *it);
+ }
+ }
+ if(styleListBox->count()==0) {
+ styleListBox->insertItem(i18n("Regular"));
+ currentStyles.insert(i18n("Regular"), "Normal");
+ }
+
+ styleListBox->blockSignals(true);
+ QListBoxItem *item = styleListBox->findItem(selectedStyle);
+ if (item)
+ styleListBox->setSelected(styleListBox->findItem(selectedStyle), true);
+ else
+ styleListBox->setSelected(0, true);
+ styleListBox->blockSignals(false);
+
+ style_chosen_slot(QString::null);
+}
+
+void KFontChooser::size_chosen_slot(const QString& size){
+
+ selectedSize=size.toInt();
+ sizeOfFont->setValue(selectedSize);
+ selFont.setPointSize(selectedSize);
+ emit fontSelected(selFont);
+}
+
+void KFontChooser::size_value_slot(int val) {
+ selFont.setPointSize(val);
+ emit fontSelected(selFont);
+}
+
+void KFontChooser::style_chosen_slot(const QString& style)
+{
+ QString currentStyle;
+ if (style.isEmpty())
+ currentStyle = styleListBox->currentText();
+ else
+ currentStyle = style;
+
+ int diff=0; // the difference between the font size requested and what we can show.
+
+ sizeListBox->clear();
+ QFontDatabase dbase;
+ if(dbase.isSmoothlyScalable(familyListBox->currentText(), currentStyles[currentStyle])) { // is vector font
+ //sampleEdit->setPaletteBackgroundPixmap( VectorPixmap ); // TODO
+ fillSizeList();
+ } else { // is bitmap font.
+ //sampleEdit->setPaletteBackgroundPixmap( BitmapPixmap ); // TODO
+ QValueList<int> sizes = dbase.smoothSizes(familyListBox->currentText(), currentStyles[currentStyle]);
+ if(sizes.count() > 0) {
+ QValueList<int>::iterator it;
+ diff=1000;
+ for ( it = sizes.begin(); it != sizes.end(); ++it ) {
+ if(*it <= selectedSize || diff > *it - selectedSize) diff = selectedSize - *it;
+ sizeListBox->insertItem(QString::number(*it));
+ }
+ } else // there are times QT does not provide the list..
+ fillSizeList();
+ }
+ sizeListBox->blockSignals(true);
+ sizeListBox->setSelected(sizeListBox->findItem(QString::number(selectedSize)), true);
+ sizeListBox->blockSignals(false);
+ sizeListBox->ensureCurrentVisible();
+
+ //kdDebug() << "Showing: " << familyListBox->currentText() << ", " << currentStyles[currentStyle] << ", " << selectedSize-diff << endl;
+ selFont = dbase.font(familyListBox->currentText(), currentStyles[currentStyle], selectedSize-diff);
+ emit fontSelected(selFont);
+ if (!style.isEmpty())
+ selectedStyle = style;
+}
+
+void KFontChooser::displaySample(const QFont& font)
+{
+ sampleEdit->setFont(font);
+ sampleEdit->setCursorPosition(0);
+ xlfdEdit->setText(font.rawName());
+ xlfdEdit->setCursorPosition(0);
+
+ //QFontInfo a = QFontInfo(font);
+ //kdDebug() << "font: " << a.family () << ", " << a.pointSize () << endl;
+ //kdDebug() << " (" << font.toString() << ")\n";
+}
+
+void KFontChooser::setupDisplay()
+{
+ // Calling familyListBox->setCurrentItem() causes the value of selFont
+ // to change, so we save the family, style and size beforehand.
+ QString family = selFont.family().lower();
+ int style = (selFont.bold() ? 2 : 0) + (selFont.italic() ? 1 : 0);
+ int size = selFont.pointSize();
+ if (size == -1)
+ size = QFontInfo(selFont).pointSize();
+ QString sizeStr = QString::number(size);
+
+ int numEntries, i;
+
+ numEntries = familyListBox->count();
+ for (i = 0; i < numEntries; i++) {
+ if (family == familyListBox->text(i).lower()) {
+ familyListBox->setCurrentItem(i);
+ break;
+ }
+ }
+
+ // 1st Fallback
+ if ( (i == numEntries) )
+ {
+ if (family.contains('['))
+ {
+ family = family.left(family.find('[')).stripWhiteSpace();
+ for (i = 0; i < numEntries; i++) {
+ if (family == familyListBox->text(i).lower()) {
+ familyListBox->setCurrentItem(i);
+ break;
+ }
+ }
+ }
+ }
+
+ // 2nd Fallback
+ if ( (i == numEntries) )
+ {
+ QString fallback = family+" [";
+ for (i = 0; i < numEntries; i++) {
+ if (familyListBox->text(i).lower().startsWith(fallback)) {
+ familyListBox->setCurrentItem(i);
+ break;
+ }
+ }
+ }
+
+ // 3rd Fallback
+ if ( (i == numEntries) )
+ {
+ for (i = 0; i < numEntries; i++) {
+ if (familyListBox->text(i).lower().startsWith(family)) {
+ familyListBox->setCurrentItem(i);
+ break;
+ }
+ }
+ }
+
+ // Fall back in case nothing matched. Otherwise, diff doesn't work
+ if ( i == numEntries )
+ familyListBox->setCurrentItem( 0 );
+
+ styleListBox->setCurrentItem(style);
+
+ numEntries = sizeListBox->count();
+ for (i = 0; i < numEntries; i++){
+ if (sizeStr == sizeListBox->text(i)) {
+ sizeListBox->setCurrentItem(i);
+ break;
+ }
+ }
+
+ sizeOfFont->setValue(size);
+}
+
+
+void KFontChooser::getFontList( QStringList &list, uint fontListCriteria)
+{
+ QFontDatabase dbase;
+ QStringList lstSys(dbase.families());
+
+ // if we have criteria; then check fonts before adding
+ if (fontListCriteria)
+ {
+ QStringList lstFonts;
+ for (QStringList::Iterator it = lstSys.begin(); it != lstSys.end(); ++it)
+ {
+ if ((fontListCriteria & FixedWidthFonts) > 0 && !dbase.isFixedPitch(*it)) continue;
+ if (((fontListCriteria & (SmoothScalableFonts | ScalableFonts)) == ScalableFonts) &&
+ !dbase.isBitmapScalable(*it)) continue;
+ if ((fontListCriteria & SmoothScalableFonts) > 0 && !dbase.isSmoothlyScalable(*it)) continue;
+ lstFonts.append(*it);
+ }
+
+ if((fontListCriteria & FixedWidthFonts) > 0) {
+ // Fallback.. if there are no fixed fonts found, it's probably a
+ // bug in the font server or Qt. In this case, just use 'fixed'
+ if (lstFonts.count() == 0)
+ lstFonts.append("fixed");
+ }
+
+ lstSys = lstFonts;
+ }
+
+ lstSys.sort();
+
+ list = lstSys;
+}
+
+void KFontChooser::addFont( QStringList &list, const char *xfont )
+{
+ const char *ptr = strchr( xfont, '-' );
+ if ( !ptr )
+ return;
+
+ ptr = strchr( ptr + 1, '-' );
+ if ( !ptr )
+ return;
+
+ QString font = QString::fromLatin1(ptr + 1);
+
+ int pos;
+ if ( ( pos = font.find( '-' ) ) > 0 ) {
+ font.truncate( pos );
+
+ if ( font.find( QString::fromLatin1("open look"), 0, false ) >= 0 )
+ return;
+
+ QStringList::Iterator it = list.begin();
+
+ for ( ; it != list.end(); ++it )
+ if ( *it == font )
+ return;
+ list.append( font );
+ }
+}
+
+void KFontChooser::fillFamilyListBox(bool onlyFixedFonts)
+{
+ QStringList fontList;
+ getFontList(fontList, onlyFixedFonts?FixedWidthFonts:0);
+ familyListBox->clear();
+ familyListBox->insertStringList(fontList);
+}
+
+void KFontChooser::showXLFDArea(bool show)
+{
+ if( show )
+ {
+ xlfdEdit->parentWidget()->show();
+ }
+ else
+ {
+ xlfdEdit->parentWidget()->hide();
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+KFontDialog::KFontDialog( QWidget *parent, const char* name,
+ bool onlyFixed, bool modal,
+ const QStringList &fontList, bool makeFrame, bool diff,
+ QButton::ToggleState *sizeIsRelativeState )
+ : KDialogBase( parent, name, modal, i18n("Select Font"), Ok|Cancel, Ok )
+{
+ chooser = new KFontChooser( this, "fontChooser",
+ onlyFixed, fontList, makeFrame, 8,
+ diff, sizeIsRelativeState );
+ setMainWidget(chooser);
+}
+
+
+int KFontDialog::getFontDiff( QFont &theFont, int &diffFlags, bool onlyFixed,
+ QWidget *parent, bool makeFrame,
+ QButton::ToggleState *sizeIsRelativeState )
+{
+ KFontDialog dlg( parent, "Font Selector", onlyFixed, true, QStringList(),
+ makeFrame, true, sizeIsRelativeState );
+ dlg.setFont( theFont, onlyFixed );
+
+ int result = dlg.exec();
+ if( result == Accepted )
+ {
+ theFont = dlg.chooser->font();
+ diffFlags = dlg.chooser->fontDiffFlags();
+ if( sizeIsRelativeState )
+ *sizeIsRelativeState = dlg.chooser->sizeIsRelative();
+ }
+ return result;
+}
+
+int KFontDialog::getFont( QFont &theFont, bool onlyFixed,
+ QWidget *parent, bool makeFrame,
+ QButton::ToggleState *sizeIsRelativeState )
+{
+ KFontDialog dlg( parent, "Font Selector", onlyFixed, true, QStringList(),
+ makeFrame, false, sizeIsRelativeState );
+ dlg.setFont( theFont, onlyFixed );
+
+ int result = dlg.exec();
+ if( result == Accepted )
+ {
+ theFont = dlg.chooser->font();
+ if( sizeIsRelativeState )
+ *sizeIsRelativeState = dlg.chooser->sizeIsRelative();
+ }
+ return result;
+}
+
+
+int KFontDialog::getFontAndText( QFont &theFont, QString &theString,
+ bool onlyFixed, QWidget *parent,
+ bool makeFrame,
+ QButton::ToggleState *sizeIsRelativeState )
+{
+ KFontDialog dlg( parent, "Font and Text Selector", onlyFixed, true,
+ QStringList(), makeFrame, false, sizeIsRelativeState );
+ dlg.setFont( theFont, onlyFixed );
+
+ int result = dlg.exec();
+ if( result == Accepted )
+ {
+ theFont = dlg.chooser->font();
+ theString = dlg.chooser->sampleText();
+ if( sizeIsRelativeState )
+ *sizeIsRelativeState = dlg.chooser->sizeIsRelative();
+ }
+ return result;
+}
+
+void KFontChooser::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void KFontDialog::virtual_hook( int id, void* data )
+{ KDialogBase::virtual_hook( id, data ); }
diff --git a/kdeui/kfontdialog.h b/kdeui/kfontdialog.h
new file mode 100644
index 000000000..3452d4869
--- /dev/null
+++ b/kdeui/kfontdialog.h
@@ -0,0 +1,504 @@
+/*
+ $Id$
+
+ Requires the Qt widget libraries, available at no cost at
+ http://www.troll.no
+
+ Copyright (C) 1997 Bernd Johannes Wuebben <wuebben@kde.org>
+ Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+ Copyright (c) 1999 Mario Weilguni <mweilguni@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef _K_FONT_DIALOG_H_
+#define _K_FONT_DIALOG_H_
+
+#include <qlineedit.h>
+#include <qbutton.h>
+#include <kdialogbase.h>
+
+class QComboBox;
+class QCheckBox;
+class QFont;
+class QGroupBox;
+class QLabel;
+class QStringList;
+class KListBox;
+class KIntNumInput;
+/**
+ * @short A font selection widget.
+ *
+ * While KFontChooser as an ordinary widget can be embedded in
+ * custom dialogs and therefore is very flexible, in most cases
+ * it is preferable to use the convenience functions in
+ * KFontDialog.
+ *
+ * \image html kfontchooser.png "KDE Font Chooser"
+ *
+ * @author Preston Brown <pbrown@kde.org>, Bernd Wuebben <wuebben@kde.org>
+ * @version $Id$
+ */
+class KDEUI_EXPORT KFontChooser : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY( QFont font READ font WRITE setFont )
+
+public:
+ /**
+ * @li @p FamilyList - Identifies the family (leftmost) list.
+ * @li @p StyleList - Identifies the style (center) list.
+ * @li @p SizeList - Identifies the size (rightmost) list.
+ */
+ enum FontColumn { FamilyList=0x01, StyleList=0x02, SizeList=0x04};
+
+ /**
+ * @li @p FontDiffFamily - Identifies a requested change in the font family.
+ * @li @p FontDiffStyle - Identifies a requested change in the font style.
+ * @li @p FontDiffSize - Identifies a requested change in the font size.
+ */
+ enum FontDiff { FontDiffFamily=0x01, FontDiffStyle=0x02, FontDiffSize=0x04 };
+
+ /**
+ * Constructs a font picker widget.
+ * It normally comes up with all font families present on the system; the
+ * getFont method below does allow some more fine-tuning of the selection of fonts
+ * that will be displayed in the dialog.
+ * <p>Consider the following code snippet;
+ * \code
+ * QStringList list;
+ * KFontChooser::getFontList(list,SmoothScalableFonts);
+ * KFontChooser chooseFont = new KFontChooser(0, "FontList", false, list);
+ * \endcode
+ * <p>
+ * The above creates a font chooser dialog with only SmoothScaleble fonts.
+ *
+ * @param parent The parent widget.
+ * @param name The widget name.
+ * @param onlyFixed Only display fonts which have fixed-width
+ * character sizes.
+ * @param fontList A list of fonts to display, in XLFD format. If
+ * no list is formatted, the internal KDE font list is used.
+ * If that has not been created, X is queried, and all fonts
+ * available on the system are displayed.
+ * @param diff Display the difference version dialog.
+ * See KFontDialog::getFontDiff().
+ * @param makeFrame Draws a frame with titles around the contents.
+ * @param visibleListSize The minimum number of visible entries in the
+ * fontlists.
+ * @param sizeIsRelativeState If not zero the widget will show a
+ * checkbox where the user may choose whether the font size
+ * is to be interpreted as relative size.
+ * Initial state of this checkbox will be set according to
+ * *sizeIsRelativeState, user choice may be retrieved by
+ * calling sizeIsRelative().
+ */
+ KFontChooser(QWidget *parent = 0L, const char *name = 0L,
+ bool onlyFixed = false,
+ const QStringList &fontList = QStringList(),
+ bool makeFrame = true, int visibleListSize=8,
+ bool diff = false, QButton::ToggleState *sizeIsRelativeState = 0L );
+
+ /**
+ * Destructs the font chooser.
+ */
+ virtual ~KFontChooser();
+
+ /**
+ * Enables or disable a font column in the chooser.
+ *
+ * Use this
+ * function if your application does not need or supports all font
+ * properties.
+ *
+ * @param column Specify the columns. An or'ed combination of
+ * @p FamilyList, @p StyleList and @p SizeList is possible.
+ * @param state If @p false the columns are disabled.
+ */
+ void enableColumn( int column, bool state );
+
+ /**
+ * Sets the currently selected font in the chooser.
+ *
+ * @param font The font to select.
+ * @param onlyFixed Readjust the font list to display only fixed
+ * width fonts if @p true, or vice-versa.
+ */
+ void setFont( const QFont &font, bool onlyFixed = false );
+
+ /**
+ * @return The bitmask corresponding to the attributes the user
+ * wishes to change.
+ */
+ int fontDiffFlags();
+
+ /**
+ * @return The currently selected font in the chooser.
+ */
+ QFont font() const { return selFont; }
+
+ /**
+ * Sets the color to use in the preview.
+ */
+ void setColor( const QColor & col );
+
+ /**
+ * @return The color currently used in the preview (default: the text
+ * color of the active color group)
+ */
+ QColor color() const;
+
+ /**
+ * Sets the background color to use in the preview.
+ */
+ void setBackgroundColor( const QColor & col );
+
+ /**
+ * @return The background color currently used in the preview (default:
+ * the base color of the active colorgroup)
+ */
+ QColor backgroundColor() const;
+
+ /**
+ * Sets the state of the checkbox indicating whether the font size
+ * is to be interpreted as relative size.
+ * NOTE: If parameter sizeIsRelative was not set in the constructor
+ * of the widget this setting will be ignored.
+ */
+ void setSizeIsRelative( QButton::ToggleState relative );
+
+ /**
+ * @return Whether the font size is to be interpreted as relative size
+ * (default: QButton:Off)
+ */
+ QButton::ToggleState sizeIsRelative() const;
+
+
+ /**
+ * @return The current text in the sample text input area.
+ */
+ QString sampleText() const { return sampleEdit->text(); }
+
+ /**
+ * Sets the sample text.
+ *
+ * Normally you should not change this
+ * text, but it can be better to do this if the default text is
+ * too large for the edit area when using the default font of your
+ * application.
+ *
+ * @param text The new sample text. The current will be removed.
+ */
+ void setSampleText( const QString &text )
+ {
+ sampleEdit->setText( text );
+ }
+
+ /**
+ * Shows or hides the sample text box.
+ *
+ * @param visible Set it to true to show the box, to false to hide it.
+ * @since 3.5
+ */
+ void setSampleBoxVisible( bool visible )
+ {
+ sampleEdit->setShown( visible );
+ }
+
+ /**
+ * Converts a QFont into the corresponding X Logical Font
+ * Description (XLFD).
+ *
+ * @param theFont The font to convert.
+ * @return A string representing the given font in XLFD format.
+ */
+ static QString getXLFD( const QFont &theFont )
+ { return theFont.rawName(); }
+
+ /**
+ * The selection criteria for the font families shown in the dialog.
+ * @li @p FixedWidthFont when included only fixed-width fonts are returned.
+ * The fonts where the width of every character is equal.
+ * @li @p ScalableFont when included only scalable fonts are returned;
+ * certain configurations allow bitmap fonts to remain unscaled and
+ * thus these fonts have limited number of sizes.
+ * @li @p SmoothScalableFont when included only return smooth scalable fonts.
+ * this will return only non-bitmap fonts which are scalable to any size requested.
+ * Setting this option to true will mean the "scalable" flag is irrelavant.
+ */
+ enum FontListCriteria { FixedWidthFonts=0x01, ScalableFonts=0x02, SmoothScalableFonts=0x04 };
+
+ /**
+ * Creates a list of font strings.
+ *
+ * @param list The list is returned here.
+ * @param fontListCriteria should contain all the restrictions for font selection as OR-ed values
+ * @see KFontChooser::FontListCriteria for the individual values
+ */
+ static void getFontList( QStringList &list, uint fontListCriteria);
+
+ /**
+ * Reimplemented for internal reasons.
+ */
+ virtual QSize sizeHint( void ) const;
+
+signals:
+ /**
+ * Emitted whenever the selected font changes.
+ */
+ void fontSelected( const QFont &font );
+
+private slots:
+ void toggled_checkbox();
+ void family_chosen_slot(const QString&);
+ void size_chosen_slot(const QString&);
+ void style_chosen_slot(const QString&);
+ void displaySample(const QFont &font);
+ void showXLFDArea(bool);
+ void size_value_slot(int);
+private:
+ void fillFamilyListBox(bool onlyFixedFonts = false);
+ void fillSizeList();
+ // This one must be static since getFontList( QStringList, char*) is so
+ static void addFont( QStringList &list, const char *xfont );
+
+ void setupDisplay();
+
+ // pointer to an optinally supplied list of fonts to
+ // inserted into the fontdialog font-family combo-box
+ QStringList fontList;
+
+ KIntNumInput *sizeOfFont;
+
+ QLineEdit *sampleEdit;
+ QLineEdit *xlfdEdit;
+
+ QLabel *familyLabel;
+ QLabel *styleLabel;
+ QCheckBox *familyCheckbox;
+ QCheckBox *styleCheckbox;
+ QCheckBox *sizeCheckbox;
+ QLabel *sizeLabel;
+ KListBox *familyListBox;
+ KListBox *styleListBox;
+ KListBox *sizeListBox;
+ QComboBox *charsetsCombo; // BIC: remove in KDE4
+ QCheckBox *sizeIsRelativeCheckBox;
+
+ QFont selFont;
+
+ QString selectedStyle;
+ int selectedSize;
+ QMap<QString, QString> currentStyles;
+
+ bool usingFixed;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KFontChooserPrivate;
+ KFontChooserPrivate *d;
+};
+
+/**
+ * @short A font selection dialog.
+ *
+ * The KFontDialog provides a dialog for interactive font selection.
+ * It is basically a thin wrapper around the KFontChooser widget,
+ * which can also be used standalone. In most cases, the simplest
+ * use of this class is the static method KFontDialog::getFont(),
+ * which pops up the dialog, allows the user to select a font, and
+ * returns when the dialog is closed.
+ *
+ * Example:
+ *
+ * \code
+ * QFont myFont;
+ * int result = KFontDialog::getFont( myFont );
+ * if ( result == KFontDialog::Accepted )
+ * ...
+ * \endcode
+ *
+ * \image html kfontdialog.png "KDE Font Dialog"
+ *
+ * @author Preston Brown <pbrown@kde.org>, Bernd Wuebben <wuebben@kde.org>
+ * @version $Id$
+ */
+class KDEUI_EXPORT KFontDialog : public KDialogBase {
+ Q_OBJECT
+
+public:
+ /**
+ * Constructs a font selection dialog.
+ *
+ * @param parent The parent widget of the dialog, if any.
+ * @param name The name of the dialog.
+ * @param modal Specifies whether the dialog is modal or not.
+ * @param onlyFixed only display fonts which have fixed-width
+ * character sizes.
+ * @param fontlist a list of fonts to display, in XLFD format. If
+ * no list is formatted, the internal KDE font list is used.
+ * If that has not been created, X is queried, and all fonts
+ * available on the system are displayed.
+ * @param makeFrame Draws a frame with titles around the contents.
+ * @param diff Display the difference version dialog. See getFontDiff().
+ * @param sizeIsRelativeState If not zero the widget will show a
+ * checkbox where the user may choose whether the font size
+ * is to be interpreted as relative size.
+ * Initial state of this checkbox will be set according to
+ * *sizeIsRelativeState, user choice may be retrieved by
+ * calling sizeIsRelative().
+ *
+ */
+ KFontDialog( QWidget *parent = 0L, const char *name = 0,
+ bool onlyFixed = false, bool modal = false,
+ const QStringList &fontlist = QStringList(),
+ bool makeFrame = true, bool diff = false,
+ QButton::ToggleState *sizeIsRelativeState = 0L );
+
+ /**
+ * Sets the currently selected font in the dialog.
+ *
+ * @param font The font to select.
+ * @param onlyFixed readjust the font list to display only fixed
+ * width fonts if true, or vice-versa
+ */
+ void setFont( const QFont &font, bool onlyFixed = false )
+ { chooser->setFont(font, onlyFixed); }
+
+ /**
+ * @return The currently selected font in the dialog.
+ */
+ QFont font() const { return chooser->font(); }
+
+ /**
+ * Sets the state of the checkbox indicating whether the font size
+ * is to be interpreted as relative size.
+ * NOTE: If parameter sizeIsRelative was not set in the constructor
+ * of the dialog this setting will be ignored.
+ */
+ void setSizeIsRelative( QButton::ToggleState relative )
+ { chooser->setSizeIsRelative( relative ); }
+
+ /**
+ * @return Whether the font size is to be interpreted as relative size
+ * (default: false)
+ */
+ QButton::ToggleState sizeIsRelative() const
+ { return chooser->sizeIsRelative(); }
+
+ /**
+ * Creates a modal font dialog, lets the user choose a font,
+ * and returns when the dialog is closed.
+ *
+ * @param theFont a reference to the font to write the chosen font
+ * into.
+ * @param onlyFixed if true, only select from fixed-width fonts.
+ * @param parent Parent widget of the dialog. Specifying a widget different
+ * from 0 (Null) improves centering (looks better).
+ * @param makeFrame Draws a frame with titles around the contents.
+ * @param sizeIsRelativeState If not zero the widget will show a
+ * checkbox where the user may choose whether the font size
+ * is to be interpreted as relative size.
+ * Initial state of this checkbox will be set according to
+ * *sizeIsRelativeState and user choice will be returned
+ * therein.
+ *
+ * @return QDialog::result().
+ */
+ static int getFont( QFont &theFont, bool onlyFixed = false,
+ QWidget *parent = 0L, bool makeFrame = true,
+ QButton::ToggleState *sizeIsRelativeState = 0L );
+
+ /**
+ * Creates a modal font difference dialog, lets the user choose a selection
+ * of changes that should be made to a set of fonts, and returns when the
+ * dialog is closed. Useful for choosing slight adjustments to the font set
+ * when the user would otherwise have to manually edit a number of fonts.
+ *
+ * @param theFont a reference to the font to write the chosen font
+ * into.
+ * @param diffFlags a reference to the int into which the chosen
+ * difference selection bitmask should be written.
+ * Check the returned bitmask like:
+ * \code
+ * if ( diffFlags & KFontChooser::FontDiffFamily )
+ * [...]
+ * if ( diffFlags & KFontChooser::FontDiffStyle )
+ * [...]
+ * if ( diffFlags & KFontChooser::FontDiffSize )
+ * [...]
+ * \endcode
+ * @param onlyFixed if true, only select from fixed-width fonts.
+ * @param parent Parent widget of the dialog. Specifying a widget different
+ * from 0 (Null) improves centering (looks better).
+ * @param makeFrame Draws a frame with titles around the contents.
+ * @param sizeIsRelativeState If not zero the widget will show a
+ * checkbox where the user may choose whether the font size
+ * is to be interpreted as relative size.
+ * Initial state of this checkbox will be set according to
+ * *sizeIsRelativeState and user choice will be returned
+ * therein.
+ *
+ * @returns QDialog::result().
+ */
+ static int getFontDiff( QFont &theFont, int &diffFlags, bool onlyFixed = false,
+ QWidget *parent = 0L, bool makeFrame = true,
+ QButton::ToggleState *sizeIsRelativeState = 0L );
+
+ /**
+ * When you are not only interested in the font selected, but also
+ * in the example string typed in, you can call this method.
+ *
+ * @param theFont a reference to the font to write the chosen font
+ * into.
+ * @param theString a reference to the example text that was typed.
+ * @param onlyFixed if true, only select from fixed-width fonts.
+ * @param parent Parent widget of the dialog. Specifying a widget different
+ * from 0 (Null) improves centering (looks better).
+ * @param makeFrame Draws a frame with titles around the contents.
+ * @param sizeIsRelativeState If not zero the widget will show a
+ * checkbox where the user may choose whether the font size
+ * is to be interpreted as relative size.
+ * Initial state of this checkbox will be set according to
+ * *sizeIsRelativeState and user choice will be returned
+ * therein.
+ * @return The result of the dialog.
+ */
+ static int getFontAndText( QFont &theFont, QString &theString,
+ bool onlyFixed = false, QWidget *parent = 0L,
+ bool makeFrame = true,
+ QButton::ToggleState *sizeIsRelativeState = 0L );
+
+signals:
+ /**
+ * Emitted whenever the currently selected font changes.
+ * Connect to this to monitor the font as it is selected if you are
+ * not running modal.
+ */
+ void fontSelected( const QFont &font );
+
+protected:
+ KFontChooser *chooser;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KFontDialogPrivate;
+ KFontDialogPrivate *d;
+
+};
+
+#endif
diff --git a/kdeui/kfontrequester.cpp b/kdeui/kfontrequester.cpp
new file mode 100644
index 000000000..d32b9d9d7
--- /dev/null
+++ b/kdeui/kfontrequester.cpp
@@ -0,0 +1,127 @@
+/*
+ Copyright (C) 2003 Nadeem Hasan <nhasan@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kfontrequester.h"
+
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+
+#include <kfontdialog.h>
+#include <klocale.h>
+
+KFontRequester::KFontRequester( QWidget *parent, const char *name,
+ bool onlyFixed ) : QWidget( parent, name ),
+ m_onlyFixed( onlyFixed )
+{
+ QHBoxLayout *layout = new QHBoxLayout( this, 0, KDialog::spacingHint() );
+
+ m_sampleLabel = new QLabel( this, "m_sampleLabel" );
+ m_button = new QPushButton( i18n( "Choose..." ), this, "m_button" );
+
+ m_sampleLabel->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken );
+ setFocusProxy( m_button );
+
+ layout->addWidget( m_sampleLabel, 1 );
+ layout->addWidget( m_button );
+
+ connect( m_button, SIGNAL( clicked() ), SLOT( buttonClicked() ) );
+
+ displaySampleText();
+ setToolTip();
+}
+
+void KFontRequester::setFont( const QFont &font, bool onlyFixed )
+{
+ m_selFont = font;
+ m_onlyFixed = onlyFixed;
+
+ displaySampleText();
+ emit fontSelected( m_selFont );
+}
+
+void KFontRequester::setSampleText( const QString &text )
+{
+ m_sampleText = text;
+ displaySampleText();
+}
+
+void KFontRequester::setTitle( const QString &title )
+{
+ m_title = title;
+ setToolTip();
+}
+
+void KFontRequester::buttonClicked()
+{
+ int result = KFontDialog::getFont( m_selFont, m_onlyFixed, parentWidget() );
+
+ if ( result == KDialog::Accepted )
+ {
+ displaySampleText();
+ emit fontSelected( m_selFont );
+ }
+}
+
+void KFontRequester::displaySampleText()
+{
+ m_sampleLabel->setFont( m_selFont );
+
+ int size = m_selFont.pointSize();
+ if(size == -1)
+ size = m_selFont.pixelSize();
+
+ if ( m_sampleText.isEmpty() )
+ m_sampleLabel->setText( QString( "%1 %2" ).arg( m_selFont.family() )
+ .arg( size ) );
+ else
+ m_sampleLabel->setText( m_sampleText );
+}
+
+void KFontRequester::setToolTip()
+{
+ QToolTip::remove( m_button );
+ QToolTip::add( m_button, i18n( "Click to select a font" ) );
+
+ QToolTip::remove( m_sampleLabel );
+ QWhatsThis::remove( m_sampleLabel );
+
+ if ( m_title.isNull() )
+ {
+ QToolTip::add( m_sampleLabel, i18n( "Preview of the selected font" ) );
+ QWhatsThis::add( m_sampleLabel,
+ i18n( "This is a preview of the selected font. You can change it"
+ " by clicking the \"Choose...\" button." ) );
+ }
+ else
+ {
+ QToolTip::add( m_sampleLabel,
+ i18n( "Preview of the \"%1\" font" ).arg( m_title ) );
+ QWhatsThis::add( m_sampleLabel,
+ i18n( "This is a preview of the \"%1\" font. You can change it"
+ " by clicking the \"Choose...\" button." ).arg( m_title ) );
+ }
+}
+
+#include "kfontrequester.moc"
+
+/* vim: et sw=2 ts=2
+*/
diff --git a/kdeui/kfontrequester.h b/kdeui/kfontrequester.h
new file mode 100644
index 000000000..8435355c5
--- /dev/null
+++ b/kdeui/kfontrequester.h
@@ -0,0 +1,157 @@
+/*
+ Copyright (C) 2003 Nadeem Hasan <nhasan@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KFONTREQUESTER_H
+#define KFONTREQUESTER_H
+
+#include <qwidget.h>
+#include <qfont.h>
+#include <qstring.h>
+
+#include <kdelibs_export.h>
+
+class QLabel;
+class QPushButton;
+
+/**
+ * This class provides a widget with a lineedit and a button, which invokes
+ * a font dialog (KFontDialog).
+ *
+ * The lineedit provides a preview of the selected font. The preview text can
+ * be customized. You can also have the font dialog show only the fixed fonts.
+ *
+ * \image html kfontrequester.png "KDE Font Requester"
+ *
+ * @author Nadeem Hasan <nhasan@kde.org>
+ *
+ */
+class KDEUI_EXPORT KFontRequester : public QWidget
+{
+ Q_OBJECT
+
+ Q_PROPERTY( QString title READ title WRITE setTitle )
+ Q_PROPERTY( QString sampleText READ sampleText WRITE setSampleText )
+ Q_PROPERTY( QFont font READ font WRITE setFont )
+
+ public:
+
+ /**
+ * Constructs a font requester widget.
+ *
+ * @param parent The parent widget.
+ * @param name The widget name.
+ * @param onlyFixed Only display fonts which have fixed-width character
+ * sizes.
+ */
+ KFontRequester( QWidget *parent=0L, const char *name=0L,
+ bool onlyFixed=false );
+
+ /**
+ * @return The currently selected font in the requester.
+ */
+ QFont font() const { return m_selFont; }
+
+ /**
+ * @return Returns true if only fixed fonts are displayed.
+ */
+ bool isFixedOnly() const { return m_onlyFixed; }
+
+ /**
+ * @return The current text in the sample text input area.
+ */
+ QString sampleText() const { return m_sampleText; }
+
+ /**
+ * @return The current title of the widget.
+ */
+ QString title() const { return m_title; }
+
+ /**
+ * @return Pointer to the label used for preview.
+ */
+ QLabel *label() const { return m_sampleLabel; }
+
+ /**
+ * @return Pointer to the pushbutton in the widget.
+ */
+ QPushButton *button() const { return m_button; }
+
+ /**
+ * Sets the currently selected font in the requester.
+ *
+ * @param font The font to select.
+ * @param onlyFixed Display only fixed-width fonts in the font dialog
+ * if @p true, or vice-versa.
+ */
+ virtual void setFont( const QFont &font, bool onlyFixed=false );
+
+ /**
+ * Sets the sample text.
+ *
+ * Normally you should not change this
+ * text, but it can be better to do this if the default text is
+ * too large for the edit area when using the default font of your
+ * application. Default text is current font name and size. Setting
+ * the text to QString::null will restore the default.
+ *
+ * @param text The new sample text. The current will be removed.
+ */
+ virtual void setSampleText( const QString &text );
+
+ /**
+ * Set the title for the widget that will be used in the tooltip and
+ * what's this text.
+ *
+ * @param title The title to be set.
+ */
+ virtual void setTitle( const QString & title );
+
+ signals:
+ /**
+ * Emitted when a new @p font has been selected in the underlying dialog
+ */
+ void fontSelected( const QFont &font );
+
+ protected:
+
+ void displaySampleText();
+ void setToolTip();
+
+ protected slots:
+
+ virtual void buttonClicked();
+
+ protected:
+
+ bool m_onlyFixed;
+ QString m_sampleText, m_title;
+ QLabel *m_sampleLabel;
+ QPushButton *m_button;
+ QFont m_selFont;
+
+ private:
+
+ class KFontRequesterPrivate;
+ KFontRequesterPrivate *d;
+};
+
+#endif // KFONTREQUESTER_H
+
+/* vim: et sw=2 ts=2
+*/
diff --git a/kdeui/kguiitem.cpp b/kdeui/kguiitem.cpp
new file mode 100644
index 000000000..35093019e
--- /dev/null
+++ b/kdeui/kguiitem.cpp
@@ -0,0 +1,229 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2001 Holger Freyther (freyher@yahoo.com)
+ based on ideas from Martijn and Simon
+ many thanks to Simon
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qregexp.h>
+#include <qstring.h>
+#include <qiconset.h>
+#include <qpixmap.h>
+
+#include <assert.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+
+#include "kguiitem.h"
+
+class KGuiItem::KGuiItemPrivate
+{
+public:
+ KGuiItemPrivate()
+ {
+ m_enabled = true;
+ m_hasIcon = false;
+ }
+
+ KGuiItemPrivate( const KGuiItemPrivate &rhs )
+ {
+ ( *this ) = rhs;
+ }
+
+ KGuiItemPrivate &operator=( const KGuiItemPrivate &rhs )
+ {
+ m_text = rhs.m_text;
+ m_iconSet = rhs.m_iconSet;
+ m_iconName = rhs.m_iconName;
+ m_toolTip = rhs.m_toolTip;
+ m_whatsThis = rhs.m_whatsThis;
+ m_statusText = rhs.m_statusText;
+ m_enabled = rhs.m_enabled;
+ m_hasIcon = rhs.m_hasIcon;
+
+ return *this;
+ }
+
+ QString m_text;
+ QString m_toolTip;
+ QString m_whatsThis;
+ QString m_statusText;
+ QString m_iconName;
+ QIconSet m_iconSet;
+ bool m_hasIcon : 1;
+ bool m_enabled : 1;
+};
+
+
+KGuiItem::KGuiItem() {
+ d = new KGuiItemPrivate;
+}
+
+KGuiItem::KGuiItem( const QString &text, const QString &iconName,
+ const QString &toolTip, const QString &whatsThis )
+{
+ d = new KGuiItemPrivate;
+ d->m_text = text;
+ d->m_toolTip = toolTip;
+ d->m_whatsThis = whatsThis;
+ setIconName( iconName );
+}
+
+KGuiItem::KGuiItem( const QString &text, const QIconSet &iconSet,
+ const QString &toolTip, const QString &whatsThis )
+{
+ d = new KGuiItemPrivate;
+ d->m_text = text;
+ d->m_toolTip = toolTip;
+ d->m_whatsThis = whatsThis;
+ setIconSet( iconSet );
+}
+
+KGuiItem::KGuiItem( const KGuiItem &rhs )
+ : d( 0 )
+{
+ ( *this ) = rhs;
+}
+
+KGuiItem &KGuiItem::operator=( const KGuiItem &rhs )
+{
+ if ( d == rhs.d )
+ return *this;
+
+ assert( rhs.d );
+
+ delete d;
+ d = new KGuiItemPrivate( *rhs.d );
+
+ return *this;
+}
+
+KGuiItem::~KGuiItem()
+{
+ delete d;
+}
+
+QString KGuiItem::text() const
+{
+ return d->m_text;
+}
+
+
+QString KGuiItem::plainText() const
+{
+ const int len = d->m_text.length();
+
+ if (len == 0)
+ return d->m_text;
+
+ //Can assume len >= 1 from now on.
+ QString stripped;
+
+ int resultLength = 0;
+ stripped.setLength(len);
+
+ const QChar* data = d->m_text.unicode();
+ for ( int pos = 0; pos < len; ++pos )
+ {
+ if ( data[ pos ] != '&' )
+ stripped[ resultLength++ ] = data[ pos ];
+ else if ( pos + 1 < len && data[ pos + 1 ] == '&' )
+ stripped[ resultLength++ ] = data[ pos++ ];
+ }
+
+ stripped.truncate(resultLength);
+
+ return stripped;
+}
+
+QIconSet KGuiItem::iconSet( KIcon::Group group, int size, KInstance* instance ) const
+{
+ if( d->m_hasIcon )
+ {
+ if( !d->m_iconName.isEmpty())
+ {
+// some caching here would(?) come handy
+ return instance->iconLoader()->loadIconSet( d->m_iconName, group, size, true, false );
+ }
+ else
+ {
+ return d->m_iconSet;
+ }
+ }
+ else
+ return QIconSet();
+}
+
+QString KGuiItem::iconName() const
+{
+ return d->m_iconName;
+}
+
+QString KGuiItem::toolTip() const
+{
+ return d->m_toolTip;
+}
+
+QString KGuiItem::whatsThis() const
+{
+ return d->m_whatsThis;
+}
+
+bool KGuiItem::isEnabled() const
+{
+ return d->m_enabled;
+}
+
+bool KGuiItem::hasIcon() const
+{
+ return d->m_hasIcon;
+}
+
+void KGuiItem::setText( const QString &text ) {
+ d->m_text=text;
+}
+
+void KGuiItem::setIconSet( const QIconSet &iconset )
+{
+ d->m_iconSet = iconset;
+ d->m_iconName = QString::null;
+ d->m_hasIcon = !iconset.isNull();
+}
+
+void KGuiItem::setIconName( const QString &iconName )
+{
+ d->m_iconName = iconName;
+ d->m_iconSet = QIconSet();
+ d->m_hasIcon = !iconName.isEmpty();
+}
+
+void KGuiItem::setToolTip( const QString &toolTip )
+{
+ d->m_toolTip = toolTip;
+}
+
+void KGuiItem::setWhatsThis( const QString &whatsThis )
+{
+ d->m_whatsThis = whatsThis;
+}
+
+void KGuiItem::setEnabled( bool enabled )
+{
+ d->m_enabled = enabled;
+}
+
+// vim: set et sw=4:
+
diff --git a/kdeui/kguiitem.h b/kdeui/kguiitem.h
new file mode 100644
index 000000000..b1c9c1674
--- /dev/null
+++ b/kdeui/kguiitem.h
@@ -0,0 +1,98 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2001 Holger Freyther (freyher@yahoo.com)
+ based on ideas from Martijn and Simon
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+ Many thanks to Simon tronical Hausmann
+*/
+
+#ifndef __kguiitem_h__
+#define __kguiitem_h__
+
+#include <qstring.h>
+#include <qiconset.h>
+#include <qpixmap.h>
+#include <qvaluelist.h>
+#include <kicontheme.h>
+#include <kglobal.h>
+
+/**
+ * @short An abstract class for GUI data such as ToolTip and Icon.
+ *
+ * @author Holger Freyther <freyher@yahoo.com>
+ * @see KStdGuiItem
+ */
+class KDEUI_EXPORT KGuiItem
+{
+public:
+ KGuiItem();
+
+ // ### This should probably be explicit in KDE 4; it's easy to get
+ // subtle bugs otherwise - the icon name, tooltip and whatsthis text
+ // get changed behind your back if you do 'setButtonFoo( "Bar" );'
+ // It gives the wrong impression that you just change the text.
+ KGuiItem( const QString &text,
+ const QString &iconName = QString::null,
+ const QString &toolTip = QString::null,
+ const QString &whatsThis = QString::null );
+
+ KGuiItem( const QString &text, const QIconSet &iconSet,
+ const QString &toolTip = QString::null,
+ const QString &whatsThis = QString::null );
+
+ KGuiItem( const KGuiItem &rhs );
+ KGuiItem &operator=( const KGuiItem &rhs );
+
+ ~KGuiItem();
+
+ QString text() const;
+ QString plainText() const;
+#ifndef KDE_NO_COMPAT
+ QIconSet iconSet( KIcon::Group, int size = 0, KInstance* instance = KGlobal::instance()) const;
+ QIconSet iconSet() const { return iconSet( KIcon::Small ); }
+#else
+ QIconSet iconSet( KIcon::Group=KIcon::Small, int size = 0, KInstance* instance = KGlobal::instance()) const;
+#endif
+
+ QString iconName() const;
+ QString toolTip() const;
+ QString whatsThis() const;
+ bool isEnabled() const;
+ /**
+ * returns whether an icon is defined, doesn't tell if it really exists
+ */
+ bool hasIcon() const;
+#ifndef KDE_NO_COMPAT
+ bool hasIconSet() const { return hasIcon(); }
+#endif
+
+ void setText( const QString &text );
+ void setIconSet( const QIconSet &iconset );
+ void setIconName( const QString &iconName );
+ void setToolTip( const QString &tooltip );
+ void setWhatsThis( const QString &whatsThis );
+ void setEnabled( bool enable );
+
+private:
+ class KGuiItemPrivate;
+ KGuiItemPrivate *d;
+};
+
+/* vim: et sw=4
+ */
+
+#endif
+
diff --git a/kdeui/khelpmenu.cpp b/kdeui/khelpmenu.cpp
new file mode 100644
index 000000000..d5e8eca58
--- /dev/null
+++ b/kdeui/khelpmenu.cpp
@@ -0,0 +1,320 @@
+/*
+ * This file is part of the KDE Libraries
+ * Copyright (C) 1999-2000 Espen Sand (espen@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+// I (espen) prefer that header files are included alphabetically
+#include <qhbox.h>
+#include <qlabel.h>
+#include <qtimer.h>
+#include <qtoolbutton.h>
+#include <qwhatsthis.h>
+#include <qwidget.h>
+
+#include <kaboutapplication.h>
+#include <kaboutdata.h>
+#include <kaboutkde.h>
+#include <kaction.h>
+#include <kapplication.h>
+#include <kbugreport.h>
+#include <kdialogbase.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kpopupmenu.h>
+#include <kstdaccel.h>
+#include <kstdaction.h>
+
+#include "kswitchlanguagedialog.h"
+
+#include "config.h"
+#include <qxembed.h>
+
+class KHelpMenuPrivate
+{
+public:
+ KHelpMenuPrivate():mSwitchApplicationLanguage(NULL)
+ {
+ }
+ ~KHelpMenuPrivate()
+ {
+ delete mSwitchApplicationLanguage;
+ }
+
+ const KAboutData *mAboutData;
+ KSwitchLanguageDialog *mSwitchApplicationLanguage;
+};
+
+KHelpMenu::KHelpMenu( QWidget *parent, const QString &aboutAppText,
+ bool showWhatsThis )
+ : QObject(parent), mMenu(0), mAboutApp(0), mAboutKDE(0), mBugReport(0),
+ d(new KHelpMenuPrivate)
+{
+ mParent = parent;
+ mAboutAppText = aboutAppText;
+ mShowWhatsThis = showWhatsThis;
+ d->mAboutData = 0;
+}
+
+KHelpMenu::KHelpMenu( QWidget *parent, const KAboutData *aboutData,
+ bool showWhatsThis, KActionCollection *actions )
+ : QObject(parent), mMenu(0), mAboutApp(0), mAboutKDE(0), mBugReport(0),
+ d(new KHelpMenuPrivate)
+{
+ mParent = parent;
+ mShowWhatsThis = showWhatsThis;
+
+ d->mAboutData = aboutData;
+
+ if (!aboutData)
+ mAboutAppText = QString::null;
+
+ if (actions)
+ {
+ KStdAction::helpContents(this, SLOT(appHelpActivated()), actions);
+ if (showWhatsThis)
+ KStdAction::whatsThis(this, SLOT(contextHelpActivated()), actions);
+ KStdAction::reportBug(this, SLOT(reportBug()), actions);
+ KStdAction::aboutApp(this, SLOT(aboutApplication()), actions);
+ KStdAction::aboutKDE(this, SLOT(aboutKDE()), actions);
+ KStdAction::switchApplicationLanguage(this, SLOT(switchApplicationLanguage()), actions);
+ }
+}
+
+KHelpMenu::~KHelpMenu()
+{
+ delete mMenu;
+ delete mAboutApp;
+ delete mAboutKDE;
+ delete mBugReport;
+ delete d;
+}
+
+
+KPopupMenu* KHelpMenu::menu()
+{
+ if( !mMenu )
+ {
+ //
+ // 1999-12-02 Espen Sand:
+ // I use hardcoded menu id's here. Reason is to stay backward
+ // compatible.
+ //
+ const KAboutData *aboutData = d->mAboutData ? d->mAboutData : KGlobal::instance()->aboutData();
+ QString appName = (aboutData)? aboutData->programName() : QString::fromLatin1(qApp->name());
+
+ mMenu = new KPopupMenu();
+ connect( mMenu, SIGNAL(destroyed()), this, SLOT(menuDestroyed()));
+
+ bool need_separator = false;
+ if (kapp->authorizeKAction("help_contents"))
+ {
+ mMenu->insertItem( BarIcon( "contents", KIcon::SizeSmall),
+ i18n( "%1 &Handbook" ).arg( appName) ,menuHelpContents );
+ mMenu->connectItem( menuHelpContents, this, SLOT(appHelpActivated()) );
+ mMenu->setAccel( KStdAccel::shortcut(KStdAccel::Help), menuHelpContents );
+ need_separator = true;
+ }
+
+ if( mShowWhatsThis && kapp->authorizeKAction("help_whats_this") )
+ {
+ QToolButton* wtb = QWhatsThis::whatsThisButton(0);
+ mMenu->insertItem( wtb->iconSet(),i18n( "What's &This" ), menuWhatsThis);
+ mMenu->connectItem( menuWhatsThis, this, SLOT(contextHelpActivated()) );
+ delete wtb;
+ mMenu->setAccel( SHIFT + Key_F1, menuWhatsThis );
+ need_separator = true;
+ }
+
+ if (kapp->authorizeKAction("help_report_bug") && aboutData && !aboutData->bugAddress().isEmpty() )
+ {
+ if (need_separator)
+ mMenu->insertSeparator();
+ mMenu->insertItem( i18n( "&Report Bug..." ), menuReportBug );
+ mMenu->connectItem( menuReportBug, this, SLOT(reportBug()) );
+ need_separator = true;
+ }
+
+ if (kapp->authorizeKAction("switch_application_language"))
+ {
+ if (need_separator)
+ mMenu->insertSeparator();
+ mMenu->insertItem( i18n( "Switch application &language..." ), menuSwitchLanguage );
+ mMenu->connectItem( menuSwitchLanguage, this, SLOT(switchApplicationLanguage()) );
+ need_separator = true;
+ }
+
+ if (need_separator)
+ mMenu->insertSeparator();
+
+ if (kapp->authorizeKAction("help_about_app"))
+ {
+ mMenu->insertItem( kapp->miniIcon(),
+ i18n( "&About %1" ).arg(appName), menuAboutApp );
+ mMenu->connectItem( menuAboutApp, this, SLOT( aboutApplication() ) );
+ }
+
+ if (kapp->authorizeKAction("help_about_kde"))
+ {
+ mMenu->insertItem( SmallIcon("about_kde"), i18n( "About &KDE" ), menuAboutKDE );
+ mMenu->connectItem( menuAboutKDE, this, SLOT( aboutKDE() ) );
+ }
+ }
+
+ return mMenu;
+}
+
+
+
+void KHelpMenu::appHelpActivated()
+{
+ kapp->invokeHelp();
+}
+
+
+void KHelpMenu::aboutApplication()
+{
+ if (d->mAboutData)
+ {
+ if( !mAboutApp )
+ {
+ mAboutApp = new KAboutApplication( d->mAboutData, mParent, "about", false );
+ connect( mAboutApp, SIGNAL(finished()), this, SLOT( dialogFinished()) );
+ }
+ mAboutApp->show();
+ }
+ else if( mAboutAppText.isEmpty() )
+ {
+ emit showAboutApplication();
+ }
+ else
+ {
+ if( !mAboutApp )
+ {
+ mAboutApp = new KDialogBase( QString::null, // Caption is defined below
+ KDialogBase::Yes, KDialogBase::Yes,
+ KDialogBase::Yes, mParent, "about",
+ false, true, KStdGuiItem::ok() );
+ connect( mAboutApp, SIGNAL(finished()), this, SLOT( dialogFinished()) );
+
+ QHBox *hbox = new QHBox( mAboutApp );
+ mAboutApp->setMainWidget( hbox );
+ hbox->setSpacing(KDialog::spacingHint()*3);
+ hbox->setMargin(KDialog::marginHint()*1);
+
+ QLabel *label1 = new QLabel(hbox);
+ label1->setPixmap( kapp->icon() );
+ QLabel *label2 = new QLabel(hbox);
+ label2->setText( mAboutAppText );
+
+ mAboutApp->setPlainCaption( i18n("About %1").arg(kapp->caption()) );
+ mAboutApp->disableResize();
+ }
+
+ mAboutApp->show();
+ }
+}
+
+
+void KHelpMenu::aboutKDE()
+{
+ if( !mAboutKDE )
+ {
+ mAboutKDE = new KAboutKDE( mParent, "aboutkde", false );
+ connect( mAboutKDE, SIGNAL(finished()), this, SLOT( dialogFinished()) );
+ }
+ mAboutKDE->show();
+}
+
+
+void KHelpMenu::reportBug()
+{
+ if( !mBugReport )
+ {
+ mBugReport = new KBugReport( mParent, false, d->mAboutData );
+ connect( mBugReport, SIGNAL(finished()),this,SLOT( dialogFinished()) );
+ }
+ mBugReport->show();
+}
+
+void KHelpMenu::switchApplicationLanguage()
+{
+ if ( !d->mSwitchApplicationLanguage )
+ {
+ d->mSwitchApplicationLanguage = new KSwitchLanguageDialog( mParent, "switchlanguagedialog", false );
+ connect( d->mSwitchApplicationLanguage, SIGNAL(finished()), this, SLOT( dialogFinished()) );
+ }
+ d->mSwitchApplicationLanguage->show();
+}
+
+
+void KHelpMenu::dialogFinished()
+{
+ QTimer::singleShot( 0, this, SLOT(timerExpired()) );
+}
+
+
+void KHelpMenu::timerExpired()
+{
+ if( mAboutKDE && !mAboutKDE->isVisible() )
+ {
+ delete mAboutKDE; mAboutKDE = 0;
+ }
+
+ if( mBugReport && !mBugReport->isVisible() )
+ {
+ delete mBugReport; mBugReport = 0;
+ }
+
+ if( mAboutApp && !mAboutApp->isVisible() )
+ {
+ delete mAboutApp; mAboutApp = 0;
+ }
+
+ if (d->mSwitchApplicationLanguage && !d->mSwitchApplicationLanguage->isVisible())
+ {
+ delete d->mSwitchApplicationLanguage; d->mSwitchApplicationLanguage = 0;
+ }
+}
+
+
+void KHelpMenu::menuDestroyed()
+{
+ mMenu = 0;
+}
+
+
+void KHelpMenu::contextHelpActivated()
+{
+ QWhatsThis::enterWhatsThisMode();
+ QWidget* w = QApplication::widgetAt( QCursor::pos(), true );
+ while ( w && !w->isTopLevel() && !w->inherits("QXEmbed") )
+ w = w->parentWidget();
+#ifdef Q_WS_X11
+ if ( w && w->inherits("QXEmbed") )
+ (( QXEmbed*) w )->enterWhatsThisMode();
+#endif
+}
+
+void KHelpMenu::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+
+#include "khelpmenu.moc"
diff --git a/kdeui/khelpmenu.h b/kdeui/khelpmenu.h
new file mode 100644
index 000000000..052f7e394
--- /dev/null
+++ b/kdeui/khelpmenu.h
@@ -0,0 +1,281 @@
+/*
+ * This file is part of the KDE Libraries
+ * Copyright (C) 1999-2000 Espen Sand (espen@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef _KHELPMENU_H_
+#define _KHELPMENU_H_
+
+#include <qobject.h>
+#include <qstring.h>
+
+#include <kdelibs_export.h>
+
+class KActionCollection;
+class KPopupMenu;
+class QWidget;
+
+class KAboutData;
+class KAboutKDE;
+class KBugReport;
+class KDialogBase;
+class KHelpMenuPrivate;
+
+
+/**
+ * @short Standard %KDE help menu with dialog boxes.
+ *
+ * This class provides the standard %KDE help menu with the default "about"
+ * dialog boxes and help entry.
+ *
+ * This class is used in KMainWindow so
+ * normally you don't need to use this class yourself. However, if you
+ * need the help menu or any of its dialog boxes in your code that is
+ * not subclassed from KMainWindow you should use this class.
+ *
+ * The usage is simple:
+ *
+ * \code
+ * mHelpMenu = new KHelpMenu( this, <someText> );
+ * kmenubar->insertItem(i18n("&Help"), mHelpMenu->menu() );
+ * \endcode
+ *
+ * or if you just want to open a dialog box:
+ *
+ * \code
+ * mHelpMenu = new KHelpMenu( this, <someText> );
+ * connect( this, SIGNAL(someSignal()), mHelpMenu,SLOT(mHelpMenu->aboutKDE()));
+ * \endcode
+ *
+ * IMPORTANT:
+ * The first time you use KHelpMenu::menu(), a KPopupMenu object is
+ * allocated. Only one object is created by the class so if you call
+ * KHelpMenu::menu() twice or more, the same pointer is returned. The class
+ * will destroy the popupmenu in the destructor so do not delete this
+ * pointer yourself.
+ *
+ * The KHelpMenu object will be deleted when its parent is destroyed but you
+ * can delete it yourself if you want. The code below will always work.
+ *
+ * \code
+ * MyClass::~MyClass()
+ * {
+ * delete mHelpMenu;
+ * }
+ * \endcode
+ *
+ *
+ * Using your own "about application" dialog box:
+ *
+ * The standard "about application" dialog box is quite simple. If you
+ * need a dialog box with more functionality you must design that one
+ * yourself. When you want to display the dialog you can choose one of
+ * two methods. Common for both is that you must make a help menu object
+ * with no text argument If the text is missing the default dialog box
+ * will not be displayed:
+ *
+ * Example 1 Using showAboutApplication signal (preferred)
+ * \code
+ *
+ * void MyClass::myFunc()
+ * {
+ * ..
+ * KHelpMenu *helpMenu = new KHelpMenu( this );
+ * connect( helpMenu, SIGNAL(showAboutApplication()),
+ * this, SLOT(myDialogSlot()));
+ * ..
+ * }
+ *
+ * void MyClass::myDialogSlot()
+ * {
+ * <activate your custom dialog>
+ * }
+ * \endcode
+ *
+ *
+ * Example 2 Old style - connecting directly to the menu entry.
+ * \code
+ *
+ * void MyClass::myFunc()
+ * {
+ * KHelpMenu *helpMenu = new KHelpMenu( this );
+ * KPopupMenu *help = mHelpMenu->menu();
+ * help->connectItem( KHelpMenu::menuAboutApp, this, SLOT(myDialogSlot()) );
+ * }
+ *
+ * void MyClass::myDialogSlot()
+ * {
+ * <activate your custom dialog>
+ * }
+ * \endcode
+ *
+ * @author Espen Sand (espen@kde.org)
+ */
+
+class KDEUI_EXPORT KHelpMenu : public QObject
+{
+ Q_OBJECT
+
+ public:
+ enum MenuId
+ {
+ menuHelpContents = 0,
+ menuWhatsThis = 1,
+ menuAboutApp = 2,
+ menuAboutKDE = 3,
+ menuReportBug = 4,
+ menuSwitchLanguage = 5
+ };
+
+ /**
+ * Constructor.
+ *
+ * @param parent The parent of the dialog boxes. The boxes are modeless
+ * and will be centered with respect to the parent.
+ * @param aboutAppText User definable string that is used in the
+ * application specific dialog box. Note: The help menu will
+ * not open this dialog box if you don't define a string. See
+ * showAboutApplication() for more information.
+ * @param showWhatsThis Decides whether a "Whats this" entry will be
+ * added to the dialog.
+ *
+ */
+ KHelpMenu( QWidget *parent=0, const QString &aboutAppText=QString::null,
+ bool showWhatsThis=true );
+
+ /**
+ * Constructor.
+ *
+ * This alternative constructor is mainly useful if you want to
+ * overide the standard actions (aboutApplication(), aboutKDE(),
+ * helpContents(), reportBug, and optionally whatsThis).
+ *
+ * @param parent The parent of the dialog boxes. The boxes are modeless
+ * and will be centered with respect to the parent.
+ * @param aboutData User and app data used in the About app dialog
+ * @param showWhatsThis Decides whether a "Whats this" entry will be
+ * added to the dialog.
+ * @param actions KActionCollection that is used instead of the
+ * standard actions.
+ *
+ */
+ KHelpMenu( QWidget *parent, const KAboutData *aboutData,
+ bool showWhatsThis=true, KActionCollection *actions = 0 );
+
+ /**
+ * Destructor
+ *
+ * Destroys dialogs and the menu pointer retuned by menu
+ */
+ ~KHelpMenu();
+
+ /**
+ * Returns a popup menu you can use in the menu bar or where you
+ * need it.
+ *
+ * Note: This method will only create one instance of the menu. If
+ * you call this method twice or more the same pointer is returned
+ */
+ KPopupMenu *menu();
+
+ public slots:
+ /**
+ * Opens the help page for the application. The application name is
+ * used as a key to determine what to display and the system will attempt
+ * to open \<appName\>/index.html.
+ */
+ void appHelpActivated();
+
+ /**
+ * Activates What's This help for the application.
+ */
+ void contextHelpActivated();
+
+ /**
+ * Opens an application specific dialog box. The dialog box will display
+ * the string that was defined in the constructor. If that string was
+ * empty the showAboutApplication() is emitted instead.
+ */
+ void aboutApplication();
+
+ /**
+ * Opens the standard "About KDE" dialog box.
+ */
+ void aboutKDE();
+
+ /**
+ * Opens the standard "Report Bugs" dialog box.
+ */
+ void reportBug();
+
+ /**
+ * Opens changing default application language dialog box.
+ */
+ void switchApplicationLanguage();
+
+ private slots:
+ /**
+ * Connected to the menu pointer (if created) to detect a delete
+ * operation on the pointer. You should not delete the pointer in your
+ * code yourself. Let the KHelpMenu destructor do the job.
+ */
+ void menuDestroyed();
+
+ /**
+ * Connected to the dialogs (about kde and bug report) to detect
+ * when they are finished.
+ */
+ void dialogFinished();
+
+ /**
+ * This slot will delete a dialog (about kde or bug report) if the
+ * dialog pointer is not zero and the the dialog is not visible. This
+ * slot is activated by a one shot timer started in dialogHidden
+ */
+ void timerExpired();
+
+ signals:
+ /**
+ * This signal is emitted from aboutApplication() if no
+ * "about application" string has been defined. The standard
+ * application specific dialog box that is normally activated in
+ * aboutApplication() will not be displayed when this signal
+ * is emitted.
+ */
+ void showAboutApplication();
+
+ private:
+ KPopupMenu *mMenu;
+ KDialogBase *mAboutApp;
+ KAboutKDE *mAboutKDE;
+ KBugReport *mBugReport;
+
+ QString mAboutAppText;
+ QWidget *mParent;
+
+ bool mShowWhatsThis;
+
+ protected:
+ virtual void virtual_hook( int id, void* data );
+ private:
+ KHelpMenuPrivate *d;
+};
+
+
+#endif
diff --git a/kdeui/kiconview.cpp b/kdeui/kiconview.cpp
new file mode 100644
index 000000000..4d220c331
--- /dev/null
+++ b/kdeui/kiconview.cpp
@@ -0,0 +1,734 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Torben Weis <weis@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+
+#include <qtimer.h>
+#include <qpainter.h>
+#include <qpixmapcache.h>
+#include <qcleanuphandler.h>
+
+#include "kiconview.h"
+#include "kwordwrap.h"
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+#include <kapplication.h>
+#include <kipc.h>
+
+#include <kcursor.h>
+#include <kpixmap.h>
+#include <kpixmapeffect.h>
+
+class KIconView::KIconViewPrivate
+{
+public:
+ KIconViewPrivate() {
+ mode = KIconView::Execute;
+ fm = 0L;
+ doAutoSelect = true;
+ textHeight = 0;
+ dragHoldItem = 0L;
+ }
+ KIconView::Mode mode;
+ bool doAutoSelect;
+ QFontMetrics *fm;
+ QPixmapCache maskCache;
+ int textHeight;
+ QIconViewItem *dragHoldItem;
+ QTimer dragHoldTimer;
+ QTimer doubleClickIgnoreTimer;
+};
+
+KIconView::KIconView( QWidget *parent, const char *name, WFlags f )
+ : QIconView( parent, name, f )
+{
+ d = new KIconViewPrivate;
+
+ connect( this, SIGNAL( onViewport() ),
+ this, SLOT( slotOnViewport() ) );
+ connect( this, SIGNAL( onItem( QIconViewItem * ) ),
+ this, SLOT( slotOnItem( QIconViewItem * ) ) );
+ slotSettingsChanged( KApplication::SETTINGS_MOUSE );
+ if ( kapp ) { // maybe null when used inside designer
+ connect( kapp, SIGNAL( settingsChanged(int) ), SLOT( slotSettingsChanged(int) ) );
+ kapp->addKipcEventMask( KIPC::SettingsChanged );
+ }
+
+ m_pCurrentItem = 0L;
+
+ m_pAutoSelect = new QTimer( this );
+ connect( m_pAutoSelect, SIGNAL( timeout() ),
+ this, SLOT( slotAutoSelect() ) );
+
+ connect( &d->dragHoldTimer, SIGNAL(timeout()), this, SLOT(slotDragHoldTimeout()) );
+}
+
+KIconView::~KIconView()
+{
+ delete d->fm;
+ delete d;
+}
+
+
+void KIconView::setMode( KIconView::Mode mode )
+{
+ d->mode = mode;
+}
+
+KIconView::Mode KIconView::mode() const
+{
+ return d->mode;
+}
+
+void KIconView::slotOnItem( QIconViewItem *item )
+{
+ if ( item ) {
+ if ( m_bUseSingle ) {
+ if ( m_bChangeCursorOverItem )
+ viewport()->setCursor( KCursor().handCursor() );
+
+ if ( (m_autoSelectDelay > -1) ) {
+ m_pAutoSelect->start( m_autoSelectDelay, true );
+ }
+ }
+ m_pCurrentItem = item;
+ }
+}
+
+void KIconView::slotOnViewport()
+{
+ if ( m_bUseSingle && m_bChangeCursorOverItem )
+ viewport()->unsetCursor();
+
+ m_pAutoSelect->stop();
+ m_pCurrentItem = 0L;
+}
+
+void KIconView::slotSettingsChanged(int category)
+{
+ if ( category != KApplication::SETTINGS_MOUSE )
+ return;
+ m_bUseSingle = KGlobalSettings::singleClick();
+ //kdDebug() << "KIconView::slotSettingsChanged for mouse, usesingle=" << m_bUseSingle << endl;
+
+ disconnect( this, SIGNAL( mouseButtonClicked( int, QIconViewItem *,
+ const QPoint & ) ),
+ this, SLOT( slotMouseButtonClicked( int, QIconViewItem *,
+ const QPoint & ) ) );
+// disconnect( this, SIGNAL( doubleClicked( QIconViewItem *,
+// const QPoint & ) ),
+// this, SLOT( slotExecute( QIconViewItem *,
+// const QPoint & ) ) );
+
+ if( m_bUseSingle ) {
+ connect( this, SIGNAL( mouseButtonClicked( int, QIconViewItem *,
+ const QPoint & ) ),
+ this, SLOT( slotMouseButtonClicked( int, QIconViewItem *,
+ const QPoint & ) ) );
+ }
+ else {
+// connect( this, SIGNAL( doubleClicked( QIconViewItem *,
+// const QPoint & ) ),
+// this, SLOT( slotExecute( QIconViewItem *,
+// const QPoint & ) ) );
+ }
+
+ m_bChangeCursorOverItem = KGlobalSettings::changeCursorOverIcon();
+ m_autoSelectDelay = m_bUseSingle ? KGlobalSettings::autoSelectDelay() : -1;
+
+ if( !m_bUseSingle || !m_bChangeCursorOverItem )
+ viewport()->unsetCursor();
+}
+
+void KIconView::slotAutoSelect()
+{
+ // check that the item still exists
+ if( index( m_pCurrentItem ) == -1 || !d->doAutoSelect )
+ return;
+
+ //Give this widget the keyboard focus.
+ if( !hasFocus() )
+ setFocus();
+
+ ButtonState keybstate = KApplication::keyboardMouseState();
+ QIconViewItem* previousItem = currentItem();
+ setCurrentItem( m_pCurrentItem );
+
+ if( m_pCurrentItem ) {
+ //Shift pressed?
+ if( (keybstate & ShiftButton) ) {
+ //Temporary implementation of the selection until QIconView supports it
+ bool block = signalsBlocked();
+ blockSignals( true );
+
+ //No Ctrl? Then clear before!
+ if( !(keybstate & ControlButton) )
+ clearSelection();
+
+ bool select = !m_pCurrentItem->isSelected();
+ bool update = viewport()->isUpdatesEnabled();
+ viewport()->setUpdatesEnabled( false );
+
+ //Calculate the smallest rectangle that contains the current Item
+ //and the one that got the autoselect event
+ QRect r;
+ QRect redraw;
+ if ( previousItem )
+ r = QRect( QMIN( previousItem->x(), m_pCurrentItem->x() ),
+ QMIN( previousItem->y(), m_pCurrentItem->y() ),
+ 0, 0 );
+ else
+ r = QRect( 0, 0, 0, 0 );
+ if ( previousItem->x() < m_pCurrentItem->x() )
+ r.setWidth( m_pCurrentItem->x() - previousItem->x() + m_pCurrentItem->width() );
+ else
+ r.setWidth( previousItem->x() - m_pCurrentItem->x() + previousItem->width() );
+ if ( previousItem->y() < m_pCurrentItem->y() )
+ r.setHeight( m_pCurrentItem->y() - previousItem->y() + m_pCurrentItem->height() );
+ else
+ r.setHeight( previousItem->y() - m_pCurrentItem->y() + previousItem->height() );
+ r = r.normalize();
+
+ //Check for each item whether it is within the rectangle.
+ //If yes, select it
+ for( QIconViewItem* i = firstItem(); i; i = i->nextItem() ) {
+ if( i->intersects( r ) ) {
+ redraw = redraw.unite( i->rect() );
+ setSelected( i, select, true );
+ }
+ }
+
+ blockSignals( block );
+ viewport()->setUpdatesEnabled( update );
+ repaintContents( redraw, false );
+
+ emit selectionChanged();
+
+ if( selectionMode() == QIconView::Single )
+ emit selectionChanged( m_pCurrentItem );
+
+ //setSelected( m_pCurrentItem, true, (keybstate & ControlButton), (keybstate & ShiftButton) );
+ }
+ else if( (keybstate & ControlButton) )
+ setSelected( m_pCurrentItem, !m_pCurrentItem->isSelected(), true );
+ else
+ setSelected( m_pCurrentItem, true );
+ }
+ else
+ kdDebug() << "KIconView: That's not supposed to happen!!!!" << endl;
+}
+
+void KIconView::emitExecute( QIconViewItem *item, const QPoint &pos )
+{
+ if ( d->mode != Execute )
+ {
+ // kdDebug() << "KIconView::emitExecute : not in execute mode !" << endl;
+ return;
+ }
+
+ ButtonState keybstate = KApplication::keyboardMouseState();
+
+ m_pAutoSelect->stop();
+
+ //Don´t emit executed if in SC mode and Shift or Ctrl are pressed
+ if( !( m_bUseSingle && ((keybstate & ShiftButton) || (keybstate & ControlButton)) ) ) {
+ setSelected( item, false );
+ viewport()->unsetCursor();
+ emit executed( item );
+ emit executed( item, pos );
+ }
+}
+
+void KIconView::updateDragHoldItem( QDropEvent *e )
+{
+ QIconViewItem *item = findItem( e->pos() );
+
+ if ( d->dragHoldItem != item)
+ {
+ d->dragHoldItem = item;
+ if( item )
+ {
+ d->dragHoldTimer.start( 1000, true );
+ }
+ else
+ {
+ d->dragHoldTimer.stop();
+ }
+ }
+}
+
+void KIconView::focusOutEvent( QFocusEvent *fe )
+{
+ m_pAutoSelect->stop();
+
+ QIconView::focusOutEvent( fe );
+}
+
+void KIconView::leaveEvent( QEvent *e )
+{
+ m_pAutoSelect->stop();
+
+ QIconView::leaveEvent( e );
+}
+
+void KIconView::contentsMousePressEvent( QMouseEvent *e )
+{
+ if( (selectionMode() == Extended) && (e->state() & ShiftButton) && !(e->state() & ControlButton) ) {
+ bool block = signalsBlocked();
+ blockSignals( true );
+
+ clearSelection();
+
+ blockSignals( block );
+ }
+
+ QIconView::contentsMousePressEvent( e );
+ d->doAutoSelect = false;
+}
+
+void KIconView::contentsMouseDoubleClickEvent ( QMouseEvent * e )
+{
+ QIconView::contentsMouseDoubleClickEvent( e );
+
+ QIconViewItem* item = findItem( e->pos() );
+
+ if( item ) {
+ if( (e->button() == LeftButton) && !m_bUseSingle )
+ emitExecute( item, e->globalPos() );
+
+ emit doubleClicked( item, e->globalPos() );
+ }
+ d->doubleClickIgnoreTimer.start(0, true);
+}
+
+void KIconView::slotMouseButtonClicked( int btn, QIconViewItem *item, const QPoint &pos )
+{
+ //kdDebug() << " KIconView::slotMouseButtonClicked() item=" << item << endl;
+ if( d->doubleClickIgnoreTimer.isActive() )
+ return; // Ignore double click
+
+ if( (btn == LeftButton) && item )
+ emitExecute( item, pos );
+}
+
+void KIconView::contentsMouseReleaseEvent( QMouseEvent *e )
+{
+ d->doAutoSelect = true;
+ QIconView::contentsMouseReleaseEvent( e );
+}
+
+void KIconView::contentsDragEnterEvent( QDragEnterEvent *e )
+{
+ updateDragHoldItem( e );
+ QIconView::contentsDragEnterEvent( e );
+}
+
+void KIconView::contentsDragLeaveEvent( QDragLeaveEvent *e )
+{
+ d->dragHoldTimer.stop();
+ d->dragHoldItem = 0L;
+ QIconView::contentsDragLeaveEvent( e );
+}
+
+
+void KIconView::contentsDragMoveEvent( QDragMoveEvent *e )
+{
+ updateDragHoldItem( e );
+ QIconView::contentsDragMoveEvent( e );
+}
+
+void KIconView::contentsDropEvent( QDropEvent* e )
+{
+ d->dragHoldTimer.stop();
+ QIconView::contentsDropEvent( e );
+}
+
+void KIconView::slotDragHoldTimeout()
+{
+ QIconViewItem *tmp = d->dragHoldItem;
+ d->dragHoldItem = 0L;
+
+ emit held( tmp );
+}
+
+void KIconView::takeItem( QIconViewItem * item )
+{
+ if ( item == d->dragHoldItem )
+ {
+ d->dragHoldTimer.stop();
+ d->dragHoldItem = 0L;
+ }
+
+ QIconView::takeItem( item );
+}
+
+void KIconView::cancelPendingHeldSignal()
+{
+ d->dragHoldTimer.stop();
+ d->dragHoldItem = 0L;
+}
+
+void KIconView::wheelEvent( QWheelEvent *e )
+{
+ if (horizontalScrollBar() && (arrangement() == QIconView::TopToBottom)) {
+ QWheelEvent ce(e->pos(), e->delta(), e->state(), Qt::Horizontal);
+ QApplication::sendEvent( horizontalScrollBar(), &ce);
+ if (ce.isAccepted()) {
+ e->accept();
+ return;
+ }
+ }
+ QIconView::wheelEvent(e);
+}
+
+void KIconView::setFont( const QFont &font )
+{
+ delete d->fm;
+ d->fm = 0L;
+ QIconView::setFont( font );
+}
+
+QFontMetrics *KIconView::itemFontMetrics() const
+{
+ if (!d->fm) {
+ // QIconView creates one too, but we can't access it
+ d->fm = new QFontMetrics( font() );
+ }
+ return d->fm;
+}
+
+QPixmap KIconView::selectedIconPixmap( QPixmap *pix, const QColor &col ) const
+{
+ QPixmap m;
+ if ( d->maskCache.find( QString::number( pix->serialNumber() ), m ) )
+ return m;
+ m = KPixmapEffect::selectedPixmap( KPixmap(*pix), col );
+ d->maskCache.insert( QString::number( pix->serialNumber() ), m );
+ return m;
+}
+
+int KIconView::iconTextHeight() const
+{
+ return d->textHeight > 0 ? d->textHeight : ( wordWrapIconText() ? 99 : 1 );
+}
+
+void KIconView::setIconTextHeight( int n )
+{
+ int oldHeight = iconTextHeight();
+ if ( n > 1 )
+ d->textHeight = n;
+ else
+ d->textHeight = 1;
+
+ // so that Qt still shows the tooltip when even a wrapped text is too long
+ setWordWrapIconText( false );
+
+ // update view if needed
+ if ( iconTextHeight() != oldHeight )
+ setFont( font() ); // hack to recalc items
+}
+
+/////////////
+
+struct KIconViewItem::KIconViewItemPrivate
+{
+ QSize m_pixmapSize;
+};
+
+void KIconViewItem::init()
+{
+ m_wordWrap = 0L;
+ d = 0L;
+ calcRect();
+}
+
+KIconViewItem::~KIconViewItem()
+{
+ delete m_wordWrap;
+ delete d;
+}
+
+void KIconViewItem::calcRect( const QString& text_ )
+{
+ Q_ASSERT( iconView() );
+ if ( !iconView() )
+ return;
+ delete m_wordWrap;
+ m_wordWrap = 0L;
+#ifndef NDEBUG // be faster for the end-user, such a bug will have been fixed before hand :)
+ if ( !iconView()->inherits("KIconView") )
+ {
+ kdWarning() << "KIconViewItem used in a " << iconView()->className() << " !!" << endl;
+ return;
+ }
+#endif
+ //kdDebug() << "KIconViewItem::calcRect - " << text() << endl;
+ KIconView *view = static_cast<KIconView *>(iconView());
+ QRect itemIconRect = pixmapRect();
+ QRect itemTextRect = textRect();
+ QRect itemRect = rect();
+
+ int pw = 0;
+ int ph = 0;
+
+#ifndef QT_NO_PICTURE
+ if ( picture() ) {
+ QRect br = picture()->boundingRect();
+ pw = br.width() + 2;
+ ph = br.height() + 2;
+ } else
+#endif
+ {
+ // Qt uses unknown_icon if no pixmap. Let's see if we need that - I doubt it
+ if (!pixmap())
+ return;
+ pw = pixmap()->width() + 2;
+ ph = pixmap()->height() + 2;
+ }
+ itemIconRect.setWidth( pw );
+#if 1 // FIXME
+ // There is a bug in Qt which prevents the item from being placed
+ // properly when the pixmapRect is not at the top of the itemRect, so we
+ // have to increase the height of the pixmapRect and leave it at the top
+ // of the itemRect...
+ if ( d && !d->m_pixmapSize.isNull() )
+ itemIconRect.setHeight( d->m_pixmapSize.height() + 2 );
+ else
+#endif
+ itemIconRect.setHeight( ph );
+
+ int tw = 0;
+ if ( d && !d->m_pixmapSize.isNull() )
+ tw = view->maxItemWidth() - ( view->itemTextPos() == QIconView::Bottom ? 0 :
+ d->m_pixmapSize.width() + 2 );
+ else
+ tw = view->maxItemWidth() - ( view->itemTextPos() == QIconView::Bottom ? 0 :
+ itemIconRect.width() );
+
+ QFontMetrics *fm = view->itemFontMetrics();
+ QString t;
+ QRect r;
+
+ // When is text_ set ? Doesn't look like it's ever set.
+ t = text_.isEmpty() ? text() : text_;
+
+ // Max text height
+ int nbLines = static_cast<KIconView*>( iconView() )->iconTextHeight();
+ int height = nbLines > 0 ? fm->height() * nbLines : 0xFFFFFFFF;
+
+ // Should not be higher than pixmap if text is alongside icons
+ if ( view->itemTextPos() != QIconView::Bottom ) {
+ if ( d && !d->m_pixmapSize.isNull() )
+ height = QMIN( d->m_pixmapSize.height() + 2, height );
+ else
+ height = QMIN( itemIconRect.height(), height );
+ height = QMAX( height, fm->height() );
+ }
+
+ // Calculate the word-wrap
+ QRect outerRect( 0, 0, tw - 6, height );
+ m_wordWrap = KWordWrap::formatText( *fm, outerRect, 0, t );
+ r = m_wordWrap->boundingRect();
+
+ int realWidth = QMAX( QMIN( r.width() + 4, tw ), fm->width( "X" ) );
+ itemTextRect.setWidth( realWidth );
+ itemTextRect.setHeight( r.height() );
+
+ int w = 0; int h = 0; int y = 0;
+ if ( view->itemTextPos() == QIconView::Bottom ) {
+ // If the pixmap size has been specified, use it
+ if ( d && !d->m_pixmapSize.isNull() )
+ {
+ w = QMAX( itemTextRect.width(), d->m_pixmapSize.width() + 2 );
+ h = itemTextRect.height() + d->m_pixmapSize.height() + 2 + 1;
+#if 0 // FIXME
+ // Waiting for the qt bug to be solved, the pixmapRect must
+ // stay on the top...
+ y = d->m_pixmapSize.height() + 2 - itemIconRect.height();
+#endif
+ }
+ else {
+ w = QMAX( itemTextRect.width(), itemIconRect.width() );
+ h = itemTextRect.height() + itemIconRect.height() + 1;
+ }
+
+ itemRect.setWidth( w );
+ itemRect.setHeight( h );
+ int width = QMAX( w, QApplication::globalStrut().width() ); // see QIconViewItem::width()
+ int height = QMAX( h, QApplication::globalStrut().height() ); // see QIconViewItem::height()
+ itemTextRect = QRect( ( width - itemTextRect.width() ) / 2, height - itemTextRect.height(),
+ itemTextRect.width(), itemTextRect.height() );
+ itemIconRect = QRect( ( width - itemIconRect.width() ) / 2, y,
+ itemIconRect.width(), itemIconRect.height() );
+ } else {
+ // If the pixmap size has been specified, use it
+ if ( d && !d->m_pixmapSize.isNull() )
+ {
+ h = QMAX( itemTextRect.height(), d->m_pixmapSize.height() + 2 );
+#if 0 // FIXME
+ // Waiting for the qt bug to be solved, the pixmapRect must
+ // stay on the top...
+ y = ( d->m_pixmapSize.height() + 2 - itemIconRect.height() ) / 2;
+#endif
+ }
+ else
+ h = QMAX( itemTextRect.height(), itemIconRect.height() );
+ w = itemTextRect.width() + itemIconRect.width() + 1;
+
+ itemRect.setWidth( w );
+ itemRect.setHeight( h );
+ int width = QMAX( w, QApplication::globalStrut().width() ); // see QIconViewItem::width()
+ int height = QMAX( h, QApplication::globalStrut().height() ); // see QIconViewItem::height()
+
+ itemTextRect = QRect( width - itemTextRect.width(), ( height - itemTextRect.height() ) / 2,
+ itemTextRect.width(), itemTextRect.height() );
+ if ( itemIconRect.height() > itemTextRect.height() ) // icon bigger than text -> center vertically
+ itemIconRect = QRect( 0, ( height - itemIconRect.height() ) / 2,
+ itemIconRect.width(), itemIconRect.height() );
+ else // icon smaller than text -> place in top or center with first line
+ itemIconRect = QRect( 0, QMAX(( fm->height() - itemIconRect.height() ) / 2 + y, 0),
+ itemIconRect.width(), itemIconRect.height() );
+ if ( ( itemIconRect.height() <= 20 ) && ( itemTextRect.height() < itemIconRect.height() ) )
+ {
+ itemTextRect.setHeight( itemIconRect.height() - 2 );
+ itemTextRect.setY( itemIconRect.y() );
+ }
+ }
+
+ if ( itemIconRect != pixmapRect() )
+ setPixmapRect( itemIconRect );
+ if ( itemTextRect != textRect() )
+ setTextRect( itemTextRect );
+ if ( itemRect != rect() )
+ setItemRect( itemRect );
+
+ // Done by setPixmapRect, setTextRect and setItemRect ! [and useless if no rect changed]
+ //view->updateItemContainer( this );
+
+}
+
+void KIconViewItem::paintItem( QPainter *p, const QColorGroup &cg )
+{
+ QIconView* view = iconView();
+ Q_ASSERT( view );
+ if ( !view )
+ return;
+#ifndef NDEBUG // be faster for the end-user, such a bug will have been fixed before hand :)
+ if ( !view->inherits("KIconView") )
+ {
+ kdWarning() << "KIconViewItem used in a " << view->className() << " !!" << endl;
+ return;
+ }
+#endif
+
+ p->save();
+
+ paintPixmap(p, cg);
+ paintText(p, cg);
+
+ p->restore();
+}
+
+KWordWrap * KIconViewItem::wordWrap()
+{
+ return m_wordWrap;
+}
+
+void KIconViewItem::paintPixmap( QPainter *p, const QColorGroup &cg )
+{
+ KIconView *kview = static_cast<KIconView *>(iconView());
+
+#ifndef QT_NO_PICTURE
+ if ( picture() ) {
+ QPicture *pic = picture();
+ if ( isSelected() ) {
+ // TODO something as nice as selectedIconPixmap if possible ;)
+ p->fillRect( pixmapRect( false ), QBrush( cg.highlight(), QBrush::Dense4Pattern) );
+ }
+ p->drawPicture( x()-pic->boundingRect().x(), y()-pic->boundingRect().y(), *pic );
+ } else
+#endif
+ {
+ int iconX = pixmapRect( false ).x();
+ int iconY = pixmapRect( false ).y();
+
+ QPixmap *pix = pixmap();
+ if ( !pix || pix->isNull() )
+ return;
+
+#if 1 // FIXME
+ // Move the pixmap manually because the pixmapRect is at the
+ // top of the itemRect
+ // (won't be needed anymore in future versions of qt)
+ if ( d && !d->m_pixmapSize.isNull() )
+ {
+ int offset = 0;
+ if ( kview->itemTextPos() == QIconView::Bottom )
+ offset = d->m_pixmapSize.height() - pix->height();
+ else
+ offset = ( d->m_pixmapSize.height() - pix->height() ) / 2;
+ if ( offset > 0 )
+ iconY += offset;
+ }
+#endif
+ if ( isSelected() ) {
+ QPixmap selectedPix = kview->selectedIconPixmap( pix, cg.highlight() );
+ p->drawPixmap( iconX, iconY, selectedPix );
+ } else {
+ p->drawPixmap( iconX, iconY, *pix );
+ }
+ }
+}
+
+void KIconViewItem::paintText( QPainter *p, const QColorGroup &cg )
+{
+ int textX = textRect( false ).x() + 2;
+ int textY = textRect( false ).y();
+
+ if ( isSelected() ) {
+ p->fillRect( textRect( false ), cg.highlight() );
+ p->setPen( QPen( cg.highlightedText() ) );
+ } else {
+ if ( iconView()->itemTextBackground() != NoBrush )
+ p->fillRect( textRect( false ), iconView()->itemTextBackground() );
+ p->setPen( cg.text() );
+ }
+
+ int align = iconView()->itemTextPos() == QIconView::Bottom ? AlignHCenter : AlignAuto;
+ m_wordWrap->drawText( p, textX, textY, align | KWordWrap::Truncate );
+}
+
+QSize KIconViewItem::pixmapSize() const
+{
+ return d ? d->m_pixmapSize : QSize( 0, 0 );
+}
+
+void KIconViewItem::setPixmapSize( const QSize& size )
+{
+ if ( !d )
+ d = new KIconViewItemPrivate;
+
+ d->m_pixmapSize = size;
+}
+
+void KIconView::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "kiconview.moc"
diff --git a/kdeui/kiconview.h b/kdeui/kiconview.h
new file mode 100644
index 000000000..9228b89d7
--- /dev/null
+++ b/kdeui/kiconview.h
@@ -0,0 +1,281 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Torben Weis <weis@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef KICONVIEW_H
+#define KICONVIEW_H
+
+#include <qcursor.h>
+#include <qiconview.h>
+
+#include <kdelibs_export.h>
+
+/**
+ * @short A variant of QIconView that honors KDE's system-wide settings.
+ *
+ * This Widget extends the functionality of QIconView to honor the system
+ * wide settings for Single Click/Double Click mode, Auto Selection and
+ * Change Cursor over Link.
+ *
+ * There is a new signal executed(). It gets connected to either
+ * QIconView::clicked() or QIconView::doubleClicked() depending on the KDE
+ * wide Single Click/Double Click settings. It is strongly recommended that
+ * you use this signal instead of the above mentioned. This way you don´t
+ * need to care about the current settings.
+ * If you want to get informed when the user selects something connect to the
+ * QIconView::selectionChanged() signal.
+ *
+ **/
+class KDEUI_EXPORT KIconView : public QIconView
+{
+ friend class KIconViewItem;
+ Q_OBJECT
+ Q_ENUMS( Mode )
+ Q_PROPERTY( Mode mode READ mode WRITE setMode )
+
+public:
+ KIconView( QWidget *parent = 0, const char *name = 0, WFlags f = 0 );
+
+ ~KIconView();
+
+ /**
+ * KIconView has two different operating modes. Execute mode is depending
+ * on the configuration of single-click or double-click where the signal
+ * executed() will be emitted upon click/double-click.
+ * In Select mode, this signal will not be emitted.
+ *
+ * Default is Execute mode.
+ */
+ enum Mode { Execute, Select };
+
+ /**
+ * Sets the mode to Execute or Select.
+ * @li In Execute mode, the signal executed()
+ * will be emitted when the user clicks/double-clicks an item.
+ * @li Select mode is
+ * the normal QIconView mode.
+ *
+ * Default is Execute.
+ */
+ void setMode( Mode m );
+
+ /**
+ * @returns the current Mode, either Execute or Select.
+ */
+ Mode mode() const;
+
+ /**
+ * Reimplemented for internal purposes
+ */
+ virtual void setFont( const QFont & );
+
+ /**
+ * Set the maximum number of lines that will be used to display icon text.
+ * Setting this value will enable word-wrap, too.
+ * @since 3.3
+ *
+ * @param n Number of lines
+ */
+ void setIconTextHeight( int n );
+
+ /**
+ * @return The height of icon text in lines
+ * @since 3.3
+ */
+ int iconTextHeight() const;
+
+ /**
+ * Reimplemented for held() signal behavior internal purposes
+ */
+ virtual void takeItem( QIconViewItem * item );
+
+signals:
+
+ /**
+ * This signal is emitted whenever the user executes an iconview item.
+ * That means depending on the KDE wide Single Click/Double Click
+ * setting the user clicked or double clicked on that item.
+ * @param item is the pointer to the executed iconview item.
+ *
+ * Note that you may not delete any QIconViewItem objects in slots
+ * connected to this signal.
+ */
+ void executed( QIconViewItem *item );
+
+ /**
+ * This signal is emitted whenever the user executes an iconview item.
+ * That means depending on the KDE wide Single Click/Double Click
+ * setting the user clicked or double clicked on that item.
+ * @param item is the pointer to the executed iconview item.
+ * @param pos is the position where the user has clicked
+ *
+ * Note that you may not delete any QIconViewItem objects in slots
+ * connected to this signal.
+ */
+ void executed( QIconViewItem *item, const QPoint &pos );
+
+ /**
+ * This signal is emitted whenever the user hold something on an iconview
+ * during a drag'n'drop.
+ * @param item is the pointer to the iconview item the hold event occur.
+ *
+ * Note that you may not delete any QIconViewItem objects in slots
+ * connected to this signal.
+ */
+ void held( QIconViewItem *item );
+
+ /**
+ * This signal gets emitted whenever the user double clicks into the
+ * iconview.
+ * @param item is the pointer to the clicked iconview item.
+ * @param pos is the position where the user has clicked, and
+ *
+ * Note that you may not delete any QIconViewItem objects in slots
+ * connected to this signal.
+ *
+ * This signal is more or less here for the sake of completeness.
+ * You should normally not need to use this. In most cases it's better
+ * to use executed() instead.
+ */
+ void doubleClicked( QIconViewItem *item, const QPoint &pos );
+
+protected slots:
+ void slotOnItem( QIconViewItem *item );
+ void slotOnViewport();
+ void slotSettingsChanged(int);
+
+ /**
+ * Auto selection happend.
+ */
+ void slotAutoSelect();
+
+protected:
+ void emitExecute( QIconViewItem *item, const QPoint &pos );
+ void updateDragHoldItem( QDropEvent *e );
+
+ virtual void focusOutEvent( QFocusEvent *fe );
+ virtual void leaveEvent( QEvent *e );
+ virtual void contentsMousePressEvent( QMouseEvent *e );
+ virtual void contentsMouseDoubleClickEvent ( QMouseEvent * e );
+ virtual void contentsMouseReleaseEvent( QMouseEvent *e );
+ virtual void contentsDragEnterEvent( QDragEnterEvent *e );
+ virtual void contentsDragLeaveEvent( QDragLeaveEvent *e );
+ virtual void contentsDragMoveEvent( QDragMoveEvent *e );
+ virtual void contentsDropEvent( QDropEvent* e );
+ virtual void wheelEvent( QWheelEvent *e );
+
+ /**
+ * This method allows to handle correctly cases where a subclass
+ * needs the held() signal to not be triggered without calling
+ * a KIconView::contentsDrag*Event() method (which have side effects
+ * because they forward to QIconView).
+ */
+ void cancelPendingHeldSignal();
+
+private slots:
+ void slotMouseButtonClicked( int btn, QIconViewItem *item, const QPoint &pos );
+ void slotDragHoldTimeout();
+
+private:
+ /**
+ * @internal. For use by KIconViewItem.
+ */
+ QFontMetrics *itemFontMetrics() const;
+ /**
+ * @internal. For use by KIconViewItem.
+ */
+ QPixmap selectedIconPixmap( QPixmap *pix, const QColor &col ) const;
+
+ bool m_bUseSingle;
+ bool m_bChangeCursorOverItem;
+
+ QIconViewItem* m_pCurrentItem;
+
+ QTimer* m_pAutoSelect;
+ int m_autoSelectDelay;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KIconViewPrivate;
+ KIconViewPrivate *d;
+};
+
+class KWordWrap;
+/**
+ * @short A variant of QIconViewItem that wraps words better.
+ *
+ * KIconViewItem exists to improve the word-wrap functionality of QIconViewItem
+ * Use KIconViewItem instead of QIconViewItem for any iconview item you might have :)
+ *
+ * @author David Faure <david@mandrakesoft.com>
+ */
+class KDEUI_EXPORT KIconViewItem : public QIconViewItem
+{
+public:
+ // Need to redefine all the constructors - I want Java !
+ KIconViewItem( QIconView *parent )
+ : QIconViewItem( parent ) { init(); } // We need to call it because the parent ctor won't call our reimplementation :(((
+ KIconViewItem( QIconView *parent, QIconViewItem *after )
+ : QIconViewItem( parent, after ) { init(); }
+ KIconViewItem( QIconView *parent, const QString &text )
+ : QIconViewItem( parent, text ) { init(); }
+ KIconViewItem( QIconView *parent, QIconViewItem *after, const QString &text )
+ : QIconViewItem( parent, after, text ) { init(); }
+ KIconViewItem( QIconView *parent, const QString &text, const QPixmap &icon )
+ : QIconViewItem( parent, text, icon ) { init(); }
+ KIconViewItem( QIconView *parent, QIconViewItem *after, const QString &text, const QPixmap &icon )
+ : QIconViewItem( parent, after, text, icon ) { init(); }
+ KIconViewItem( QIconView *parent, const QString &text, const QPicture &picture )
+ : QIconViewItem( parent, text, picture ) { init(); }
+ KIconViewItem( QIconView *parent, QIconViewItem *after, const QString &text, const QPicture &picture )
+ : QIconViewItem( parent, after, text, picture ) { init(); }
+ virtual ~KIconViewItem();
+
+ /**
+ * Using this function, you can specify a custom size for the pixmap. The
+ * geometry of the item will be calculated to let a pixmap of the given size
+ * fit in the iconView without needing an update.
+ * This may be useful if you want to change the pixmap later without breaking
+ * the layout. A possible use of this function is to replace a fileItem icon
+ * by a larger pixmap (preview).
+ * @since 3.3
+ *
+ * @param size The size to use
+ */
+ void setPixmapSize( const QSize& size );
+
+ /**
+ * @return The size set by setPixmapSize() or QSize( 0, 0 )
+ * @since 3.3
+ */
+ QSize pixmapSize() const;
+
+protected:
+ void init();
+ virtual void calcRect( const QString& text_ = QString::null );
+ virtual void paintItem( QPainter *p, const QColorGroup &c );
+ KWordWrap *wordWrap();
+ void paintPixmap( QPainter *p, const QColorGroup &c );
+ void paintText( QPainter *p, const QColorGroup &c );
+
+private:
+ KWordWrap* m_wordWrap;
+ struct KIconViewItemPrivate;
+ KIconViewItemPrivate *d;
+};
+
+#endif
diff --git a/kdeui/kiconviewsearchline.cpp b/kdeui/kiconviewsearchline.cpp
new file mode 100644
index 000000000..b0f26c03d
--- /dev/null
+++ b/kdeui/kiconviewsearchline.cpp
@@ -0,0 +1,274 @@
+/* This file is part of the KDE libraries
+ Copyright (c) 2004 Gustavo Sverzut Barbieri <gsbarbieri@users.sourceforge.net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * \todo
+ * Maybe we should have a common interface for SearchLines, this file
+ * is so close (it's actually based on) klistviewsearchline! Only few methods
+ * would be reimplemented.
+ */
+
+#include "kiconviewsearchline.h"
+
+#include <qiconview.h>
+#include <klocale.h>
+#include <qtimer.h>
+#include <kdebug.h>
+
+#define DEFAULT_CASESENSITIVE false
+
+typedef QValueList <QIconViewItem *> QIconViewItemList;
+
+class KIconViewSearchLine::KIconViewSearchLinePrivate
+{
+public:
+ KIconViewSearchLinePrivate() :
+ iconView( 0 ),
+ caseSensitive( DEFAULT_CASESENSITIVE ),
+ activeSearch( false ),
+ queuedSearches( 0 ) {}
+
+ QIconView *iconView;
+ bool caseSensitive;
+ bool activeSearch;
+ QString search;
+ int queuedSearches;
+ QIconViewItemList hiddenItems;
+};
+
+/******************************************************************************
+ * Public Methods *
+ *****************************************************************************/
+KIconViewSearchLine::KIconViewSearchLine( QWidget *parent,
+ QIconView *iconView,
+ const char *name ) :
+ KLineEdit( parent, name )
+{
+ d = NULL;
+ init( iconView );
+}
+
+KIconViewSearchLine::KIconViewSearchLine( QWidget *parent, const char *name ) :
+ KLineEdit( parent, name )
+{
+ d = NULL;
+ init( NULL );
+}
+
+KIconViewSearchLine::~KIconViewSearchLine()
+{
+ clear(); // empty hiddenItems, returning items back to iconView
+ delete d;
+}
+
+bool KIconViewSearchLine::caseSensitive() const
+{
+ return d->caseSensitive;
+}
+
+QIconView *KIconViewSearchLine::iconView() const
+{
+ return d->iconView;
+}
+
+/******************************************************************************
+ * Public Slots *
+ *****************************************************************************/
+void KIconViewSearchLine::updateSearch( const QString &s )
+{
+ QIconView *iv = d->iconView;
+ if( ! iv )
+ return; // disabled
+
+ QString search = d->search = s.isNull() ? text() : s;
+
+ QIconViewItemList *hi = &(d->hiddenItems);
+
+ QIconViewItem *currentItem = iv->currentItem();
+
+ QIconViewItem *item = NULL;
+
+ // Remove Non-Matching items, add them them to hidden list
+ QIconViewItem *i = iv->firstItem();
+ while ( i != NULL )
+ {
+ item = i;
+ i = i->nextItem(); // Point to next, otherwise will loose it.
+ if ( ! itemMatches( item, search ) )
+ {
+ hideItem( item );
+
+ if ( item == currentItem )
+ currentItem = NULL; // It's not in iconView anymore.
+ }
+ }
+
+ // Add Matching items, remove from hidden list
+ QIconViewItemList::iterator it = hi->begin();
+ while ( it != hi->end() )
+ {
+ item = *it;
+ ++it;
+ if ( itemMatches( item, search ) )
+ showItem( item );
+ }
+
+ iv->sort();
+
+ if ( currentItem != NULL )
+ iv->ensureItemVisible( currentItem );
+}
+
+void KIconViewSearchLine::clear()
+{
+ // Clear hidden list, give items back to QIconView, if it still exists
+ QIconViewItem *item = NULL;
+ QIconViewItemList::iterator it = d->hiddenItems.begin();
+ while ( it != d->hiddenItems.end() )
+ {
+ item = *it;
+ ++it;
+ if ( item != NULL )
+ {
+ if ( d->iconView != NULL )
+ showItem( item );
+ else
+ delete item;
+ }
+ }
+ if ( ! d->hiddenItems.isEmpty() )
+ kdDebug() << __FILE__ << ":" << __LINE__ <<
+ "hiddenItems is not empty as it should be. " <<
+ d->hiddenItems.count() << " items are still there.\n" << endl;
+
+ d->search = "";
+ d->queuedSearches = 0;
+ KLineEdit::clear();
+}
+
+void KIconViewSearchLine::setCaseSensitive( bool cs )
+{
+ d->caseSensitive = cs;
+}
+
+void KIconViewSearchLine::setIconView( QIconView *iv )
+{
+ if ( d->iconView != NULL )
+ disconnect( d->iconView, SIGNAL( destroyed() ),
+ this, SLOT( iconViewDeleted() ) );
+
+ d->iconView = iv;
+
+ if ( iv != NULL )
+ {
+ connect( d->iconView, SIGNAL( destroyed() ),
+ this, SLOT( iconViewDeleted() ) );
+ setEnabled( true );
+ }
+ else
+ setEnabled( false );
+}
+
+/******************************************************************************
+ * Protected Methods *
+ *****************************************************************************/
+bool KIconViewSearchLine::itemMatches( const QIconViewItem *item,
+ const QString &s ) const
+{
+ if ( s.isEmpty() )
+ return true;
+
+ if ( item == NULL )
+ return false;
+
+ return ( item->text().find( s, 0, caseSensitive() ) >= 0 );
+}
+
+void KIconViewSearchLine::init( QIconView *iconView )
+{
+ delete d;
+ d = new KIconViewSearchLinePrivate;
+
+ d->iconView = iconView;
+
+ connect( this, SIGNAL( textChanged( const QString & ) ),
+ this, SLOT( queueSearch( const QString & ) ) );
+
+ if ( iconView != NULL )
+ {
+ connect( iconView, SIGNAL( destroyed() ),
+ this, SLOT( iconViewDeleted() ) );
+ setEnabled( true );
+ }
+ else
+ setEnabled( false );
+}
+
+void KIconViewSearchLine::hideItem( QIconViewItem *item )
+{
+ if ( ( item == NULL ) || ( d->iconView == NULL ) )
+ return;
+
+ d->hiddenItems.append( item );
+ d->iconView->takeItem( item );
+}
+
+void KIconViewSearchLine::showItem( QIconViewItem *item )
+{
+ if ( d->iconView == NULL )
+ {
+ kdDebug() << __FILE__ << ":" << __LINE__ <<
+ "showItem() could not be called while there's no iconView set." <<
+ endl;
+ return;
+ }
+ d->iconView->insertItem( item );
+ d->hiddenItems.remove( item );
+}
+
+/******************************************************************************
+ * Protected Slots *
+ *****************************************************************************/
+void KIconViewSearchLine::queueSearch( const QString &s )
+{
+ d->queuedSearches++;
+ d->search = s;
+ QTimer::singleShot( 200, this, SLOT( activateSearch() ) );
+}
+
+void KIconViewSearchLine::activateSearch()
+{
+ d->queuedSearches--;
+
+ if ( d->queuedSearches <= 0 )
+ {
+ updateSearch( d->search );
+ d->queuedSearches = 0;
+ }
+}
+
+/******************************************************************************
+ * Private Slots *
+ *****************************************************************************/
+void KIconViewSearchLine::iconViewDeleted()
+{
+ d->iconView = NULL;
+ setEnabled( false );
+}
+
+#include "kiconviewsearchline.moc"
diff --git a/kdeui/kiconviewsearchline.h b/kdeui/kiconviewsearchline.h
new file mode 100644
index 000000000..3eca6bd23
--- /dev/null
+++ b/kdeui/kiconviewsearchline.h
@@ -0,0 +1,179 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 2004 Gustavo Sverzut Barbieri <gsbarbieri@users.sourceforge.net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KICONVIEWSEARCHLINE_H
+#define KICONVIEWSEARCHLINE_H
+
+#include <klineedit.h>
+#include <qvaluelist.h>
+
+class QIconView;
+class QIconViewItem;
+
+/**
+ * This class makes it easy to add a search line for filtering the items in a
+ * iconview based on a simple text search.
+ *
+ * No changes to the application other than instantiating this class with an
+ * appropriate QIconView should be needed.
+ *
+ * @since 3.3
+ */
+class KDEUI_EXPORT KIconViewSearchLine : public KLineEdit
+{
+ Q_OBJECT
+
+public:
+
+ /**
+ * Constructs a KIconViewSearchLine with \a iconView being the QIconView to
+ * be filtered.
+ *
+ * If \a iconView is null then the widget will be disabled until a iconview
+ * is set with setIconView().
+ */
+ KIconViewSearchLine( QWidget *parent = 0,
+ QIconView *iconView = 0,
+ const char *name = 0 );
+
+ /**
+ * Constructs a KIconViewSearchLine without any QIconView to filter. The
+ * QIconView object has to be set later with setIconView().
+ */
+ KIconViewSearchLine( QWidget *parent, const char *name );
+
+ /**
+ * Destroys the KIconViewSearchLine.
+ */
+ virtual ~KIconViewSearchLine();
+
+ /**
+ * Returns true if the search is case sensitive. This defaults to false.
+ *
+ * @see setCaseSensitive()
+ */
+ bool caseSensitive() const;
+
+ /**
+ * Returns the iconview that is currently filtered by the search.
+ *
+ * @see setIconView()
+ */
+ QIconView *iconView() const;
+
+
+public slots:
+ /**
+ * Updates search to only make visible the items that match \a s. If
+ * \a s is null then the line edit's text will be used.
+ */
+ virtual void updateSearch( const QString &s = QString::null );
+
+ /**
+ * Make the search case sensitive or case insensitive.
+ *
+ * @see caseSenstive()
+ */
+ void setCaseSensitive( bool cs );
+
+ /**
+ * Sets the QIconView that is filtered by this search line. If \a lv is null
+ * then the widget will be disabled.
+ *
+ * @see iconView()
+ */
+ void setIconView( QIconView *iv );
+
+
+ /**
+ * Clear line edit and empty hiddenItems, returning elements to iconView.
+ */
+ void clear();
+
+
+protected:
+ /**
+ * Returns true if \a item matches the search \a s. This will be evaluated
+ * based on the value of caseSensitive(). This can be overridden in
+ * subclasses to implement more complicated matching schemes.
+ */
+ virtual bool itemMatches( const QIconViewItem *item,
+ const QString &s ) const;
+
+
+ /**
+ * Do initialization common to both constructors.
+ */
+ void init( QIconView *iconView = 0 );
+
+ /**
+ * Hide item.
+ */
+ void hideItem( QIconViewItem *item );
+
+ /**
+ * Show item.
+ *
+ * Just unhide it, doesn't necessary show it on screen, for that use
+ * iconView->ensureItemVisible()
+ */
+ void showItem( QIconViewItem *item );
+
+
+protected slots:
+ /**
+ * When keys are pressed a new search string is created and a timer is
+ * activated. The most recent search is activated when this timer runs out
+ * if another key has not yet been pressed.
+ *
+ * This method makes @param s the most recent search and starts the
+ * timer.
+ *
+ * Together with activateSearch() this makes it such that searches are not
+ * started until there is a short break in the users typing.
+ *
+ * @see activateSearch()
+ */
+ void queueSearch( const QString &s );
+
+ /**
+ * When the timer started with queueSearch() expires this slot is called.
+ * If there has been another timer started then this slot does nothing.
+ * However if there are no other pending searches this starts the icon view
+ * search.
+ *
+ * @see queueSearch()
+ */
+ void activateSearch();
+
+
+private slots:
+ /**
+ * Take action need when iconView is deleted.
+ */
+ void iconViewDeleted();
+
+
+private:
+ class KIconViewSearchLinePrivate;
+ KIconViewSearchLinePrivate *d;
+};
+
+
+#endif /* KICONVIEWSEARCHLINE_H */
diff --git a/kdeui/kinputdialog.cpp b/kdeui/kinputdialog.cpp
new file mode 100644
index 000000000..d2d5e56a3
--- /dev/null
+++ b/kdeui/kinputdialog.cpp
@@ -0,0 +1,468 @@
+/*
+ Copyright (C) 2003 Nadeem Hasan <nhasan@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qvalidator.h>
+#include <qwhatsthis.h>
+
+#include <klineedit.h>
+#include <knuminput.h>
+#include <kcombobox.h>
+#include <klistbox.h>
+#include <ktextedit.h>
+
+#include "kinputdialog.h"
+
+class KInputDialogPrivate
+{
+ public:
+ KInputDialogPrivate();
+
+ QLabel *m_label;
+ KLineEdit *m_lineEdit;
+ KIntSpinBox *m_intSpinBox;
+ KDoubleSpinBox *m_doubleSpinBox;
+ KComboBox *m_comboBox;
+ KListBox *m_listBox;
+ KTextEdit *m_textEdit;
+};
+
+KInputDialogPrivate::KInputDialogPrivate()
+ : m_label( 0L ), m_lineEdit( 0L ), m_intSpinBox( 0L ),
+ m_doubleSpinBox( 0L ), m_comboBox( 0L )
+{
+}
+
+KInputDialog::KInputDialog( const QString &caption, const QString &label,
+ const QString &value, QWidget *parent, const char *name,
+ QValidator *validator, const QString &mask )
+ : KDialogBase( parent, name, true, caption, Ok|Cancel|User1, Ok, true,
+ KStdGuiItem::clear() ),
+ d( new KInputDialogPrivate() )
+{
+ QFrame *frame = makeMainWidget();
+ QVBoxLayout *layout = new QVBoxLayout( frame, 0, spacingHint() );
+
+ d->m_label = new QLabel( label, frame );
+ layout->addWidget( d->m_label );
+
+ d->m_lineEdit = new KLineEdit( value, frame );
+ layout->addWidget( d->m_lineEdit );
+
+ d->m_lineEdit->setFocus();
+ d->m_label->setBuddy( d->m_lineEdit );
+
+ layout->addStretch();
+
+ if ( validator )
+ d->m_lineEdit->setValidator( validator );
+
+ if ( !mask.isEmpty() )
+ d->m_lineEdit->setInputMask( mask );
+
+ connect( d->m_lineEdit, SIGNAL( textChanged( const QString & ) ),
+ SLOT( slotEditTextChanged( const QString & ) ) );
+ connect( this, SIGNAL( user1Clicked() ), d->m_lineEdit, SLOT( clear() ) );
+
+ slotEditTextChanged( value );
+ setMinimumWidth( 350 );
+}
+
+KInputDialog::KInputDialog( const QString &caption, const QString &label,
+ const QString &value, QWidget *parent, const char *name )
+ : KDialogBase( parent, name, true, caption, Ok|Cancel|User1, Ok, false,
+ KStdGuiItem::clear() ),
+ d( new KInputDialogPrivate() )
+{
+ QFrame *frame = makeMainWidget();
+ QVBoxLayout *layout = new QVBoxLayout( frame, 0, spacingHint() );
+
+ d->m_label = new QLabel( label, frame );
+ layout->addWidget( d->m_label );
+
+ d->m_textEdit = new KTextEdit( frame );
+ d->m_textEdit->setTextFormat( PlainText );
+ d->m_textEdit->setText( value );
+ layout->addWidget( d->m_textEdit, 10 );
+
+ d->m_textEdit->setFocus();
+ d->m_label->setBuddy( d->m_textEdit );
+
+ connect( this, SIGNAL( user1Clicked() ), d->m_textEdit, SLOT( clear() ) );
+
+ setMinimumWidth( 400 );
+}
+
+KInputDialog::KInputDialog( const QString &caption, const QString &label,
+ int value, int minValue, int maxValue, int step, int base,
+ QWidget *parent, const char *name )
+ : KDialogBase( parent, name, true, caption, Ok|Cancel, Ok, true ),
+ d( new KInputDialogPrivate() )
+{
+ QFrame *frame = makeMainWidget();
+ QVBoxLayout *layout = new QVBoxLayout( frame, 0, spacingHint() );
+
+ d->m_label = new QLabel( label, frame );
+ layout->addWidget( d->m_label );
+
+ d->m_intSpinBox = new KIntSpinBox( minValue, maxValue, step, value,
+ base, frame );
+ layout->addWidget( d->m_intSpinBox );
+
+ layout->addStretch();
+
+ d->m_intSpinBox->setFocus();
+ setMinimumWidth( 300 );
+}
+
+KInputDialog::KInputDialog( const QString &caption, const QString &label,
+ double value, double minValue, double maxValue, double step, int decimals,
+ QWidget *parent, const char *name )
+ : KDialogBase( parent, name, true, caption, Ok|Cancel, Ok, true ),
+ d( new KInputDialogPrivate() )
+{
+ QFrame *frame = makeMainWidget();
+ QVBoxLayout *layout = new QVBoxLayout( frame, 0, spacingHint() );
+
+ d->m_label = new QLabel( label, frame );
+ layout->addWidget( d->m_label );
+
+ d->m_doubleSpinBox = new KDoubleSpinBox( minValue, maxValue, step, value,
+ decimals, frame );
+ layout->addWidget( d->m_doubleSpinBox );
+
+ layout->addStretch();
+
+ d->m_doubleSpinBox->setFocus();
+ setMinimumWidth( 300 );
+}
+
+KInputDialog::KInputDialog( const QString &caption, const QString &label,
+ const QStringList &list, int current, bool editable, QWidget *parent,
+ const char *name )
+ : KDialogBase( parent, name, true, caption, Ok|Cancel|User1, Ok, true,
+ KStdGuiItem::clear() ),
+ d( new KInputDialogPrivate() )
+{
+ showButton( User1, editable );
+
+ QFrame *frame = makeMainWidget();
+ QVBoxLayout *layout = new QVBoxLayout( frame, 0, spacingHint() );
+
+ d->m_label = new QLabel( label, frame );
+ layout->addWidget( d->m_label );
+
+ if ( editable )
+ {
+ d->m_comboBox = new KComboBox( editable, frame );
+ d->m_comboBox->insertStringList( list );
+ d->m_comboBox->setCurrentItem( current );
+ layout->addWidget( d->m_comboBox );
+
+ connect( d->m_comboBox, SIGNAL( textChanged( const QString & ) ),
+ SLOT( slotUpdateButtons( const QString & ) ) );
+ connect( this, SIGNAL( user1Clicked() ),
+ d->m_comboBox, SLOT( clearEdit() ) );
+ slotUpdateButtons( d->m_comboBox->currentText() );
+ d->m_comboBox->setFocus();
+ } else {
+ d->m_listBox = new KListBox( frame );
+ d->m_listBox->insertStringList( list );
+ d->m_listBox->setSelected( current, true );
+ d->m_listBox->ensureCurrentVisible();
+ layout->addWidget( d->m_listBox, 10 );
+ connect( d->m_listBox, SIGNAL( doubleClicked( QListBoxItem * ) ),
+ SLOT( slotOk() ) );
+ connect( d->m_listBox, SIGNAL( returnPressed( QListBoxItem * ) ),
+ SLOT( slotOk() ) );
+
+ d->m_listBox->setFocus();
+ }
+
+ layout->addStretch();
+
+ setMinimumWidth( 320 );
+}
+
+KInputDialog::KInputDialog( const QString &caption, const QString &label,
+ const QStringList &list, const QStringList &select, bool multiple,
+ QWidget *parent, const char *name )
+ : KDialogBase( parent, name, true, caption, Ok|Cancel, Ok, true ),
+ d( new KInputDialogPrivate() )
+{
+ QFrame *frame = makeMainWidget();
+ QVBoxLayout *layout = new QVBoxLayout( frame, 0, spacingHint() );
+
+ d->m_label = new QLabel( label, frame );
+ layout->addWidget( d->m_label );
+
+ d->m_listBox = new KListBox( frame );
+ d->m_listBox->insertStringList( list );
+ layout->addWidget( d->m_listBox );
+
+ QListBoxItem *item;
+
+ if ( multiple )
+ {
+ d->m_listBox->setSelectionMode( QListBox::Extended );
+
+ for ( QStringList::ConstIterator it=select.begin(); it!=select.end(); ++it )
+ {
+ item = d->m_listBox->findItem( *it, CaseSensitive|ExactMatch );
+ if ( item )
+ d->m_listBox->setSelected( item, true );
+ }
+ }
+ else
+ {
+ connect( d->m_listBox, SIGNAL( doubleClicked( QListBoxItem * ) ),
+ SLOT( slotOk() ) );
+ connect( d->m_listBox, SIGNAL( returnPressed( QListBoxItem * ) ),
+ SLOT( slotOk() ) );
+
+ QString text = select.first();
+ item = d->m_listBox->findItem( text, CaseSensitive|ExactMatch );
+ if ( item )
+ d->m_listBox->setSelected( item, true );
+ }
+
+ d->m_listBox->ensureCurrentVisible();
+ d->m_listBox->setFocus();
+
+ layout->addStretch();
+
+ setMinimumWidth( 320 );
+}
+
+KInputDialog::~KInputDialog()
+{
+ delete d;
+}
+
+QString KInputDialog::getText( const QString &caption, const QString &label,
+ const QString &value, bool *ok, QWidget *parent, const char *name,
+ QValidator *validator, const QString &mask )
+{
+ return text( caption, label, value, ok, parent, name, validator, mask,
+ QString::null );
+}
+
+QString KInputDialog::text( const QString &caption,
+ const QString &label, const QString &value, bool *ok, QWidget *parent,
+ const char *name, QValidator *validator, const QString &mask,
+ const QString &whatsThis )
+{
+ KInputDialog dlg( caption, label, value, parent, name, validator, mask );
+
+ if( !whatsThis.isEmpty() )
+ QWhatsThis::add( dlg.lineEdit(), whatsThis );
+
+ bool _ok = ( dlg.exec() == Accepted );
+
+ if ( ok )
+ *ok = _ok;
+
+ QString result;
+ if ( _ok )
+ result = dlg.lineEdit()->text();
+
+ // A validator may explicitly allow leading and trailing whitespace
+ if ( !validator )
+ result = result.stripWhiteSpace();
+
+ return result;
+}
+
+QString KInputDialog::getMultiLineText( const QString &caption,
+ const QString &label, const QString &value, bool *ok,
+ QWidget *parent, const char *name )
+{
+ KInputDialog dlg( caption, label, value, parent, name );
+
+ bool _ok = ( dlg.exec() == Accepted );
+
+ if ( ok )
+ *ok = _ok;
+
+ QString result;
+ if ( _ok )
+ result = dlg.textEdit()->text();
+
+ return result;
+}
+
+int KInputDialog::getInteger( const QString &caption, const QString &label,
+ int value, int minValue, int maxValue, int step, int base, bool *ok,
+ QWidget *parent, const char *name )
+{
+ KInputDialog dlg( caption, label, value, minValue,
+ maxValue, step, base, parent, name );
+
+ bool _ok = ( dlg.exec() == Accepted );
+
+ if ( ok )
+ *ok = _ok;
+
+ int result=0;
+ if ( _ok )
+ result = dlg.intSpinBox()->value();
+
+ return result;
+}
+
+int KInputDialog::getInteger( const QString &caption, const QString &label,
+ int value, int minValue, int maxValue, int step, bool *ok,
+ QWidget *parent, const char *name )
+{
+ return getInteger( caption, label, value, minValue, maxValue, step,
+ 10, ok, parent, name );
+}
+
+double KInputDialog::getDouble( const QString &caption, const QString &label,
+ double value, double minValue, double maxValue, double step, int decimals,
+ bool *ok, QWidget *parent, const char *name )
+{
+ KInputDialog dlg( caption, label, value, minValue,
+ maxValue, step, decimals, parent, name );
+
+ bool _ok = ( dlg.exec() == Accepted );
+
+ if ( ok )
+ *ok = _ok;
+
+ double result=0;
+ if ( _ok )
+ result = dlg.doubleSpinBox()->value();
+
+ return result;
+}
+
+double KInputDialog::getDouble( const QString &caption, const QString &label,
+ double value, double minValue, double maxValue, int decimals,
+ bool *ok, QWidget *parent, const char *name )
+{
+ return getDouble( caption, label, value, minValue, maxValue, 0.1, decimals,
+ ok, parent, name );
+}
+
+QString KInputDialog::getItem( const QString &caption, const QString &label,
+ const QStringList &list, int current, bool editable, bool *ok,
+ QWidget *parent, const char *name )
+{
+ KInputDialog dlg( caption, label, list, current,
+ editable, parent, name );
+ if ( !editable)
+ {
+ connect( dlg.listBox(), SIGNAL(doubleClicked ( QListBoxItem *)), &dlg, SLOT( slotOk()));
+ }
+ bool _ok = ( dlg.exec() == Accepted );
+
+ if ( ok )
+ *ok = _ok;
+
+ QString result;
+ if ( _ok )
+ if ( editable )
+ result = dlg.comboBox()->currentText();
+ else
+ result = dlg.listBox()->currentText();
+
+ return result;
+}
+
+QStringList KInputDialog::getItemList( const QString &caption,
+ const QString &label, const QStringList &list, const QStringList &select,
+ bool multiple, bool *ok, QWidget *parent, const char *name )
+{
+ KInputDialog dlg( caption, label, list, select,
+ multiple, parent, name );
+
+ bool _ok = ( dlg.exec() == Accepted );
+
+ if ( ok )
+ *ok = _ok;
+
+ QStringList result;
+ if ( _ok )
+ {
+ for (const QListBoxItem* i = dlg.listBox()->firstItem(); i != 0; i = i->next() )
+ if ( i->isSelected() )
+ result.append( i->text() );
+ }
+
+ return result;
+}
+
+void KInputDialog::slotEditTextChanged( const QString &text )
+{
+ bool on;
+ if ( lineEdit()->validator() ) {
+ QString str = lineEdit()->text();
+ int index = lineEdit()->cursorPosition();
+ on = ( lineEdit()->validator()->validate( str, index )
+ == QValidator::Acceptable );
+ } else {
+ on = !text.stripWhiteSpace().isEmpty();
+ }
+
+ enableButton( Ok, on );
+ enableButton( User1, !text.isEmpty() );
+}
+
+void KInputDialog::slotUpdateButtons( const QString &text )
+{
+ enableButton( Ok, !text.isEmpty() );
+ enableButton( User1, !text.isEmpty() );
+}
+
+KLineEdit *KInputDialog::lineEdit() const
+{
+ return d->m_lineEdit;
+}
+
+KIntSpinBox *KInputDialog::intSpinBox() const
+{
+ return d->m_intSpinBox;
+}
+
+KDoubleSpinBox *KInputDialog::doubleSpinBox() const
+{
+ return d->m_doubleSpinBox;
+}
+
+KComboBox *KInputDialog::comboBox() const
+{
+ return d->m_comboBox;
+}
+
+KListBox *KInputDialog::listBox() const
+{
+ return d->m_listBox;
+}
+
+KTextEdit *KInputDialog::textEdit() const
+{
+ return d->m_textEdit;
+}
+
+#include "kinputdialog.moc"
+
+/* vim: set ai et sw=2 ts=2
+*/
diff --git a/kdeui/kinputdialog.h b/kdeui/kinputdialog.h
new file mode 100644
index 000000000..c6cd22d87
--- /dev/null
+++ b/kdeui/kinputdialog.h
@@ -0,0 +1,290 @@
+/*
+ Copyright (C) 2003 Nadeem Hasan <nhasan@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KINPUTDIALOG_H
+#define KINPUTDIALOG_H
+
+class QValidator;
+
+class KLineEdit;
+class KIntSpinBox;
+class KDoubleSpinBox;
+class KComboBox;
+class KTextEdit;
+class KInputDialogPrivate;
+
+#include <kdialogbase.h>
+
+/**
+ * The KInputDialog class provides a simple dialog to get a single value
+ * from the user. The value can be a string, a number (either an integer or
+ * a float) or an item from a list. This class is designed to be source
+ * compatible with QInputDialog.
+ *
+ * Five static convenience functions are provided: getText(), getInteger().
+ * getDouble(), getItem() and getItemList().
+ *
+ * @since 3.2
+ * @author Nadeem Hasan <nhasan@kde.org>
+ */
+class KDEUI_EXPORT KInputDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ private:
+
+ /**
+ * Constructor. This class is not designed to be instantiated except
+ * from the static member functions.
+ */
+ KInputDialog( const QString &caption, const QString &label,
+ const QString &value, QWidget *parent, const char *name,
+ QValidator *validator, const QString &mask );
+ KInputDialog( const QString &caption, const QString &label,
+ const QString &value, QWidget *parent, const char *name );
+ KInputDialog( const QString &caption, const QString &label, int value,
+ int minValue, int maxValue, int step, int base, QWidget *parent,
+ const char *name );
+ KInputDialog( const QString &caption, const QString &label, double value,
+ double minValue, double maxValue, double step, int decimals,
+ QWidget *parent, const char *name );
+ KInputDialog( const QString &caption, const QString &label,
+ const QStringList &list, int current, bool editable, QWidget *parent,
+ const char *name );
+ KInputDialog( const QString &caption, const QString &label,
+ const QStringList &list, const QStringList &select, bool editable,
+ QWidget *parent, const char *name );
+
+ ~KInputDialog();
+
+ KLineEdit *lineEdit() const;
+ KIntSpinBox *intSpinBox() const;
+ KDoubleSpinBox *doubleSpinBox() const;
+ KComboBox *comboBox() const;
+ KListBox *listBox() const;
+ KTextEdit *textEdit() const;
+
+ private slots:
+
+ void slotEditTextChanged( const QString& );
+ void slotUpdateButtons( const QString& );
+
+ public:
+
+ /**
+ * Static convenience function to get a string from the user.
+ *
+ * caption is the text that is displayed in the title bar. label is the
+ * text that appears as a label for the line edit. value is the initial
+ * value of the line edit. ok will be set to true if user pressed Ok
+ * and false if user pressed Cancel.
+ *
+ * If you provide a validator, the Ok button is disabled as long as
+ * the validator doesn't return Acceptable. If there is no validator,
+ * the Ok button is enabled whenever the line edit isn't empty. If you
+ * want to accept empty input, create a trivial QValidator that
+ * always returns acceptable, e.g. QRegExpValidator with a regexp
+ * of ".*".
+ *
+ * @param caption Caption of the dialog
+ * @param label Text of the label for the line edit
+ * @param value Initial value of the line edit
+ * @param ok This bool would be set to true if user pressed Ok
+ * @param parent Parent of the dialog widget
+ * @param name Name of the dialog widget
+ * @param validator A @ref QValidator to be associated with the line edit
+ * @param mask Mask associated with the line edit. See the
+ * documentation for @ref QLineEdit about masks.
+ *
+ * @return String user entered if Ok was pressed, else a null string
+ */
+ static QString getText( const QString &caption, const QString &label,
+ const QString &value=QString::null, bool *ok=0, QWidget *parent=0,
+ const char *name=0, QValidator *validator=0,
+ const QString &mask=QString::null );
+
+ /**
+ * Same as @ref getText except it provides an extra parameter to specify
+ * a QWhatsThis text for the input widget.
+ *
+ * ### KDE4: Merge with getText.
+ *
+ * @since KDE 3.3
+ **/
+ static QString text( const QString &caption, const QString &label,
+ const QString &value=QString::null, bool *ok=0, QWidget *parent=0,
+ const char *name=0, QValidator *validator=0,
+ const QString &mask=QString::null,
+ const QString& whatsThis=QString::null );
+
+ /**
+ * Static convenience function to get a multiline string from the user.
+ *
+ * caption is the text that is displayed in the title bar. label is the
+ * text that appears as a label for the line edit. value is the initial
+ * value of the line edit. ok will be set to true if user pressed Ok
+ * and false if user pressed Cancel.
+ *
+ * @param caption Caption of the dialog
+ * @param label Text of the label for the line edit
+ * @param value Initial value of the line edit
+ * @param ok This bool would be set to true if user pressed Ok
+ * @param parent Parent of the dialog widget
+ * @param name Name of the dialog widget
+ *
+ * @return String user entered if Ok was pressed, else a null string
+ * @since 3.3
+ */
+ static QString getMultiLineText( const QString &caption,
+ const QString &label, const QString &value=QString::null,
+ bool *ok=0, QWidget *parent=0, const char *name=0 );
+
+ /**
+ * Static convenience function to get an integer from the user.
+ *
+ * caption is the text that is displayed in the title bar. label is the
+ * text that appears as the label for the spin box. value is the initial
+ * value for the spin box. minValue and maxValue are the minimum and
+ * maximum allowable values the user may choose. step is the amount by
+ * which the value will change as the user presses the increment and
+ * decrement buttons of the spin box. Base is the base of the number.
+ *
+ * @param caption Caption of the dialog
+ * @param label Text of the label for the spin box
+ * @param value Initial value of the spin box
+ * @param minValue Minimum value user can input
+ * @param maxValue Maximum value user can input
+ * @param step Amount by which value is incremented or decremented
+ * @param base Base of the number
+ * @param ok This bool would be set to true if user pressed Ok
+ * @param parent Parent of the dialog widget
+ * @param name Name of the dialog widget
+ *
+ * @return Number user entered if Ok was pressed, else 0
+ */
+
+ static int getInteger( const QString &caption, const QString &label,
+ int value=0, int minValue=-2147483647, int maxValue=2147483647,
+ int step=1, int base=10, bool *ok=0, QWidget *parent=0,
+ const char *name=0 );
+
+ /**
+ * This is an overloaded convenience function. It behaves exactly same as
+ * above except it assumes base to be 10, i.e. accepts decimal numbers.
+ */
+ static int getInteger( const QString &caption, const QString &label,
+ int value=0, int minValue=-2147483647, int maxValue=2147483647,
+ int step=1, bool *ok=0, QWidget *parent=0, const char *name=0 );
+
+ /**
+ * Static convenience function to get a floating point number from the user.
+ *
+ * caption is the text that is displayed in the title bar. label is the
+ * text that appears as the label for the spin box. value is the initial
+ * value for the spin box. minValue and maxValue are the minimum and
+ * maximum allowable values the user may choose. step is the amount by
+ * which the value will change as the user presses the increment and
+ * decrement buttons of the spin box.
+ *
+ * @param caption Caption of the dialog
+ * @param label Text of the label for the spin box
+ * @param value Initial value of the spin box
+ * @param minValue Minimum value user can input
+ * @param maxValue Maximum value user can input
+ * @param step Amount by which value is incremented or decremented
+ * @param decimals Number of digits after the decimal point
+ * @param ok This bool would be set to true if user pressed Ok
+ * @param parent Parent of the dialog widget
+ * @param name Name of the dialog widget
+ *
+ * @return Number user entered if Ok was pressed, else 0
+ */
+ static double getDouble( const QString &caption, const QString &label,
+ double value=0, double minValue=-2147483647,
+ double maxValue=2147483647, double step=0.1, int decimals=1,
+ bool *ok=0, QWidget *parent=0, const char *name=0 );
+
+ /**
+ * This is an overloaded convenience function. It behaves exctly like
+ * the above function.
+ */
+ static double getDouble( const QString &caption, const QString &label,
+ double value=0, double minValue=-2147483647,
+ double maxValue=2147483647, int decimals=1, bool *ok=0,
+ QWidget *parent=0, const char *name=0 );
+
+ /**
+ * Static convenience function to let the user select an item from a
+ * list. caption is the text that is displayed in the title bar.
+ * label is the text that appears as the label for the list. list
+ * is the string list which is inserted into the list, and current
+ * is the number of the item which should be the selected item. If
+ * editable is true, the user can enter their own text.
+ *
+ * @param caption Caption of the dialog
+ * @param label Text of the label for the spin box
+ * @param list List of item for user to choose from
+ * @param current Index of the selected item
+ * @param editable If true, user can enter own text
+ * @param ok This bool would be set to true if user pressed Ok
+ * @param parent Parent of the dialog widget
+ * @param name Name of the dialog widget
+ *
+ * @return Text of the selected item. If @p editable is true this can be
+ * a text entered by the user.
+ */
+ static QString getItem( const QString &caption, const QString &label,
+ const QStringList &list, int current=0, bool editable=false,
+ bool *ok=0, QWidget *parent=0, const char *name=0 );
+
+ /**
+ * Static convenience function to let the user select one or more
+ * items from a listbox. caption is the text that is displayed in the
+ * title bar. label is the text that appears as the label for the listbox.
+ * list is the string list which is inserted into the listbox, select
+ * is the list of item(s) that should be the selected. If multiple is
+ * true, the user can select multiple items.
+ *
+ * @param caption Caption of the dialog
+ * @param label Text of the label for the spin box
+ * @param list List of item for user to choose from
+ * @param select List of item(s) that should be selected
+ * @param multiple If true, user can select multiple items
+ * @param ok This bool would be set to true if user pressed Ok
+ * @param parent Parent of the dialog widget
+ * @param name Name of the dialog widget
+ *
+ * @return List of selected items if multiple is true, else currently
+ * selected item as a QStringList
+ */
+ static QStringList getItemList( const QString &caption,
+ const QString &label, const QStringList &list=QStringList(),
+ const QStringList &select=QStringList(), bool multiple=false,
+ bool *ok=0, QWidget *parent=0, const char *name=0 );
+
+ private:
+
+ KInputDialogPrivate* const d;
+ friend class KInputDialogPrivate;
+};
+
+#endif // KINPUTDIALOG_H
+
+/* vim: set ai et sw=2 ts=2
+*/
diff --git a/kdeui/kjanuswidget.cpp b/kdeui/kjanuswidget.cpp
new file mode 100644
index 000000000..4a38a7b28
--- /dev/null
+++ b/kdeui/kjanuswidget.cpp
@@ -0,0 +1,1148 @@
+/* This file is part of the KDE Libraries
+ * Copyright (C) 1999-2000 Espen Sand (espensa@online.no)
+ * Copyright (C) 2003 Ravikiran Rajagopal (ravi@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <qbitmap.h>
+#include <qgrid.h>
+#include <qhbox.h>
+#include <qheader.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qobjectlist.h>
+#include <qpixmap.h>
+#include <qsplitter.h>
+#include <qtabwidget.h>
+#include <qvbox.h>
+#include <qwidgetstack.h>
+#include <qpainter.h>
+#include <qstyle.h>
+
+#include <kapplication.h>
+#include <kdialog.h> // Access to some static members
+#include <klocale.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+#include <kseparator.h>
+#include <kdebug.h>
+#include "kjanuswidget.h"
+#include <klistview.h>
+#include "kpushbutton.h"
+#include "kguiitem.h"
+
+class KJanusWidget::IconListItem : public QListBoxItem
+{
+ public:
+ IconListItem( QListBox *listbox, const QPixmap &pixmap,
+ const QString &text );
+ virtual int height( const QListBox *lb ) const;
+ virtual int width( const QListBox *lb ) const;
+ int expandMinimumWidth( int width );
+
+ protected:
+ const QPixmap &defaultPixmap();
+ void paint( QPainter *painter );
+
+ private:
+ QPixmap mPixmap;
+ int mMinimumWidth;
+};
+
+class KJanusWidget::KJanusWidgetPrivate
+{
+public:
+ KJanusWidgetPrivate() : mNextPageIndex(0), mListFrame( 0 ) { }
+
+ int mNextPageIndex; // The next page index.
+
+ // Dictionary for multipage modes.
+ QMap<int,QWidget*> mIntToPage;
+ // Reverse dictionary. Used because showPage() may be performance critical.
+ QMap<QWidget*,int> mPageToInt;
+ // Dictionary of title string associated with page.
+ QMap<int, QString> mIntToTitle;
+
+ QWidget * mListFrame;
+ QSplitter * mSplitter;
+};
+
+template class QPtrList<QListViewItem>;
+
+
+KJanusWidget::KJanusWidget( QWidget *parent, const char *name, int face )
+ : QWidget( parent, name, 0 ),
+ mValid(false), mPageList(0),
+ mTitleList(0), mFace(face), mTitleLabel(0), mActivePageWidget(0),
+ mShowIconsInTreeList(false), d(0)
+{
+ QVBoxLayout *topLayout = new QVBoxLayout( this );
+
+ if( mFace == TreeList || mFace == IconList )
+ {
+ d = new KJanusWidgetPrivate;
+ d->mSplitter = 0;
+
+ QFrame *page;
+ if( mFace == TreeList )
+ {
+ d->mSplitter = new QSplitter( this );
+ topLayout->addWidget( d->mSplitter, 10 );
+ mTreeListResizeMode = QSplitter::KeepSize;
+
+ d->mListFrame = new QWidget( d->mSplitter );
+ QVBoxLayout *dummy = new QVBoxLayout( d->mListFrame, 0, KDialog::spacingHint() );
+ dummy->setAutoAdd( true );
+ mTreeList = new KListView( d->mListFrame );
+ mTreeList->addColumn( QString::null );
+ mTreeList->header()->hide();
+ mTreeList->setRootIsDecorated(true);
+ mTreeList->setSorting( -1 );
+ connect( mTreeList, SIGNAL(selectionChanged()), SLOT(slotShowPage()) );
+ connect( mTreeList, SIGNAL(clicked(QListViewItem *)), SLOT(slotItemClicked(QListViewItem *)));
+
+ //
+ // Page area. Title at top with a separator below and a pagestack using
+ // all available space at bottom.
+ //
+ QFrame *p = new QFrame( d->mSplitter );
+
+ QHBoxLayout *hbox = new QHBoxLayout( p, 0, 0 );
+
+ page = new QFrame( p );
+ hbox->addWidget( page, 10 );
+ }
+ else
+ {
+ QHBoxLayout *hbox = new QHBoxLayout( topLayout );
+ d->mListFrame = new QWidget( this );
+ hbox->addWidget( d->mListFrame );
+
+ ( new QVBoxLayout( d->mListFrame, 0, 0 ) )->setAutoAdd( true );
+ mIconList = new IconListBox( d->mListFrame );
+
+ QFont listFont( mIconList->font() );
+ listFont.setBold( true );
+ mIconList->setFont( listFont );
+
+ mIconList->verticalScrollBar()->installEventFilter( this );
+ connect( mIconList, SIGNAL(selectionChanged()), SLOT(slotShowPage()));
+ hbox->addSpacing( KDialog::marginHint() );
+ page = new QFrame( this );
+ hbox->addWidget( page, 10 );
+ }
+
+ //
+ // Rest of page area. Title at top with a separator below and a
+ // pagestack using all available space at bottom.
+ //
+
+ QVBoxLayout *vbox = new QVBoxLayout( page, 0, KDialog::spacingHint() );
+
+ mTitleLabel = new QLabel( i18n("Empty Page"), page, "KJanusWidgetTitleLabel" );
+ vbox->addWidget( mTitleLabel, 0, QApplication::reverseLayout() ? AlignRight : AlignLeft );
+
+ QFont titleFont( mTitleLabel->font() );
+ titleFont.setBold( true );
+ mTitleLabel->setFont( titleFont );
+
+ mTitleSep = new KSeparator( page );
+ mTitleSep->setFrameStyle( QFrame::HLine|QFrame::Plain );
+ vbox->addWidget( mTitleSep );
+
+ mPageStack = new QWidgetStack( page );
+ connect(mPageStack, SIGNAL(aboutToShow(QWidget *)),
+ SIGNAL(aboutToShowPage(QWidget *)));
+ vbox->addWidget( mPageStack, 10 );
+ }
+ else if( mFace == Tabbed )
+ {
+ d = new KJanusWidgetPrivate;
+
+ mTabControl = new QTabWidget( this );
+ mTabControl->setMargin (KDialog::marginHint());
+ connect(mTabControl, SIGNAL(currentChanged(QWidget *)),
+ SIGNAL(aboutToShowPage(QWidget *)));
+ topLayout->addWidget( mTabControl, 10 );
+ }
+ else if( mFace == Swallow )
+ {
+ mSwallowPage = new QWidget( this );
+ topLayout->addWidget( mSwallowPage, 10 );
+ }
+ else
+ {
+ mFace = Plain;
+ mPlainPage = new QFrame( this );
+ topLayout->addWidget( mPlainPage, 10 );
+ }
+
+ if ( kapp )
+ connect(kapp,SIGNAL(kdisplayFontChanged()),SLOT(slotFontChanged()));
+ mValid = true;
+
+ setSwallowedWidget(0); // Set default size if 'mFace' is Swallow.
+}
+
+
+KJanusWidget::~KJanusWidget()
+{
+ delete d;
+}
+
+
+bool KJanusWidget::isValid() const
+{
+ return mValid;
+}
+
+
+QFrame *KJanusWidget::plainPage()
+{
+ return mPlainPage;
+}
+
+
+int KJanusWidget::face() const
+{
+ return mFace;
+}
+
+QWidget *KJanusWidget::FindParent()
+{
+ if( mFace == Tabbed ) {
+ return mTabControl;
+ }
+ else {
+ return this;
+ }
+}
+
+QFrame *KJanusWidget::addPage( const QStringList &items, const QString &header,
+ const QPixmap &pixmap )
+{
+ if( !mValid )
+ {
+ kdDebug() << "addPage: Invalid object" << endl;
+ return 0;
+ }
+
+ QFrame *page = new QFrame( FindParent(), "page" );
+ addPageWidget( page, items, header, pixmap );
+
+ return page;
+}
+
+void KJanusWidget::pageGone( QObject *obj )
+{
+ removePage( static_cast<QWidget*>( obj ) );
+}
+
+void KJanusWidget::slotReopen( QListViewItem * item )
+{
+ if( item )
+ item->setOpen( true );
+}
+
+QFrame *KJanusWidget::addPage( const QString &itemName, const QString &header,
+ const QPixmap &pixmap )
+{
+ QStringList items;
+ items << itemName;
+ return addPage(items, header, pixmap);
+}
+
+
+
+QVBox *KJanusWidget::addVBoxPage( const QStringList &items,
+ const QString &header,
+ const QPixmap &pixmap )
+{
+ if( !mValid )
+ {
+ kdDebug() << "addPage: Invalid object" << endl;
+ return 0;
+ }
+
+ QVBox *page = new QVBox(FindParent() , "page" );
+ page->setSpacing( KDialog::spacingHint() );
+ addPageWidget( page, items, header, pixmap );
+
+ return page;
+}
+
+QVBox *KJanusWidget::addVBoxPage( const QString &itemName,
+ const QString &header,
+ const QPixmap &pixmap )
+{
+ QStringList items;
+ items << itemName;
+ return addVBoxPage(items, header, pixmap);
+}
+
+QHBox *KJanusWidget::addHBoxPage( const QStringList &items,
+ const QString &header,
+ const QPixmap &pixmap )
+{
+ if( !mValid ) {
+ kdDebug() << "addPage: Invalid object" << endl;
+ return 0;
+ }
+
+ QHBox *page = new QHBox(FindParent(), "page");
+ page->setSpacing( KDialog::spacingHint() );
+ addPageWidget( page, items, header, pixmap );
+
+ return page;
+}
+
+QHBox *KJanusWidget::addHBoxPage( const QString &itemName,
+ const QString &header,
+ const QPixmap &pixmap )
+{
+ QStringList items;
+ items << itemName;
+ return addHBoxPage(items, header, pixmap);
+}
+
+QGrid *KJanusWidget::addGridPage( int n, Orientation dir,
+ const QStringList &items,
+ const QString &header,
+ const QPixmap &pixmap )
+{
+ if( !mValid )
+ {
+ kdDebug() << "addPage: Invalid object" << endl;
+ return 0;
+ }
+
+ QGrid *page = new QGrid( n, dir, FindParent(), "page" );
+ page->setSpacing( KDialog::spacingHint() );
+ addPageWidget( page, items, header, pixmap );
+
+ return page;
+}
+
+
+QGrid *KJanusWidget::addGridPage( int n, Orientation dir,
+ const QString &itemName,
+ const QString &header,
+ const QPixmap &pixmap )
+{
+ QStringList items;
+ items << itemName;
+ return addGridPage(n, dir, items, header, pixmap);
+}
+
+void KJanusWidget::InsertTreeListItem(const QStringList &items, const QPixmap &pixmap, QFrame *page)
+{
+ bool isTop = true;
+ QListViewItem *curTop = 0, *child, *last, *newChild;
+ unsigned int index = 1;
+ QStringList curPath;
+
+ for ( QStringList::ConstIterator it = items.begin(); it != items.end(); ++it, index++ ) {
+ QString name = (*it);
+ bool isPath = ( index != items.count() );
+
+ // Find the first child.
+ if (isTop) {
+ child = mTreeList->firstChild();
+ }
+ else {
+ child = curTop->firstChild();
+ }
+
+ // Now search for a child with the current Name, and if it we doesn't
+ // find it, then remember the location of the last child.
+ for (last = 0; child && child->text(0) != name ; last = child, child = child->nextSibling());
+
+ if (!last && !child) {
+ // This node didn't have any children at all, lets just insert the
+ // new child.
+ if (isTop)
+ newChild = new QListViewItem(mTreeList, name);
+ else
+ newChild = new QListViewItem(curTop, name);
+
+ }
+ else if (child) {
+ // we found the given name in this child.
+ if (!isPath) {
+ kdDebug() << "The element inserted was already in the TreeList box!" << endl;
+ return;
+ }
+ else {
+ // Ok we found the folder
+ newChild = child;
+ }
+ }
+ else {
+ // the node had some children, but we didn't find the given name
+ if (isTop)
+ newChild = new QListViewItem(mTreeList, last, name);
+ else
+ newChild = new QListViewItem(curTop, last, name);
+ }
+
+ // Now make the element expandable if it is a path component, and make
+ // ready for next loop
+ if (isPath) {
+ newChild->setExpandable(true);
+ curTop = newChild;
+ isTop = false;
+ curPath << name;
+
+ QString key = curPath.join("_/_");
+ if (mFolderIconMap.contains(key)) {
+ QPixmap p = mFolderIconMap[key];
+ newChild->setPixmap(0,p);
+ }
+ }
+ else {
+ if (mShowIconsInTreeList) {
+ newChild->setPixmap(0, pixmap);
+ }
+ mTreeListToPageStack.insert(newChild, page);
+ }
+ }
+}
+
+void KJanusWidget::addPageWidget( QFrame *page, const QStringList &items,
+ const QString &header,const QPixmap &pixmap )
+{
+ connect(page, SIGNAL(destroyed(QObject*)), SLOT(pageGone(QObject*)));
+
+ if( mFace == Tabbed )
+ {
+ mTabControl->addTab (page, items.last());
+ d->mIntToPage[d->mNextPageIndex] = static_cast<QWidget*>(page);
+ d->mPageToInt[static_cast<QWidget*>(page)] = d->mNextPageIndex;
+ d->mNextPageIndex++;
+ }
+ else if( mFace == TreeList || mFace == IconList )
+ {
+ d->mIntToPage[d->mNextPageIndex] = static_cast<QWidget*>(page);
+ d->mPageToInt[static_cast<QWidget*>(page)] = d->mNextPageIndex;
+ mPageStack->addWidget( page, 0 );
+
+ if (items.isEmpty()) {
+ kdDebug() << "Invalid QStringList, with zero items" << endl;
+ return;
+ }
+
+ if( mFace == TreeList )
+ {
+ InsertTreeListItem(items, pixmap, page);
+ }
+ else // mFace == IconList
+ {
+ QString itemName = items.last();
+ IconListItem *item = new IconListItem( mIconList, pixmap, itemName );
+ mIconListToPageStack.insert(item, page);
+ mIconList->invalidateHeight();
+ mIconList->invalidateWidth();
+
+ if (mIconList->isVisible())
+ mIconList->updateWidth();
+ }
+
+ //
+ // Make sure the title label is sufficiently wide
+ //
+ QString lastName = items.last();
+ const QString &title = (!header.isNull() ? header : lastName);
+ QRect r = mTitleLabel->fontMetrics().boundingRect( title );
+ if( mTitleLabel->minimumWidth() < r.width() )
+ {
+ mTitleLabel->setMinimumWidth( r.width() );
+ }
+ d->mIntToTitle[d->mNextPageIndex] = title;
+ if( d->mIntToTitle.count() == 1 )
+ {
+ showPage(0);
+ }
+ d->mNextPageIndex++;
+ }
+ else
+ {
+ kdDebug() << "KJanusWidget::addPageWidget: can only add a page in Tabbed, TreeList or IconList modes" << endl;
+ }
+
+}
+
+void KJanusWidget::setFolderIcon(const QStringList &path, const QPixmap &pixmap)
+{
+ QString key = path.join("_/_");
+ mFolderIconMap.insert(key,pixmap);
+}
+
+
+
+bool KJanusWidget::setSwallowedWidget( QWidget *widget )
+{
+ if( mFace != Swallow || !mValid )
+ {
+ return false;
+ }
+
+ //
+ // Remove current layout and make a new.
+ //
+ delete mSwallowPage->layout();
+
+ QGridLayout *gbox = new QGridLayout( mSwallowPage, 1, 1, 0 );
+
+ //
+ // Hide old children
+ //
+ QObjectList *l = (QObjectList*)mSwallowPage->children(); // silence please
+ for( uint i=0; i < l->count(); i++ )
+ {
+ QObject *o = l->at(i);
+ if( o->isWidgetType() )
+ {
+ ((QWidget*)o)->hide();
+ }
+ }
+
+ //
+ // Add new child or make default size
+ //
+ if( !widget )
+ {
+ gbox->addRowSpacing(0,100);
+ gbox->addColSpacing(0,100);
+ mSwallowPage->setMinimumSize(100,100);
+ }
+ else
+ {
+ if( widget->parent() != mSwallowPage )
+ {
+ widget->reparent( mSwallowPage, 0, QPoint(0,0) );
+ }
+ gbox->addWidget(widget, 0, 0 );
+ gbox->activate();
+ mSwallowPage->setMinimumSize( widget->minimumSize() );
+ }
+
+ return true;
+}
+
+bool KJanusWidget::slotShowPage()
+{
+ if( !mValid )
+ {
+ return false;
+ }
+
+ if( mFace == TreeList )
+ {
+ QListViewItem *node = mTreeList->selectedItem();
+ if( !node ) { return false; }
+
+ QWidget *stackItem = mTreeListToPageStack[node];
+ // Make sure to call through the virtual function showPage(int)
+ return showPage(d->mPageToInt[stackItem]);
+ }
+ else if( mFace == IconList )
+ {
+ QListBoxItem *node = mIconList->item( mIconList->currentItem() );
+ if( !node ) { return false; }
+ QWidget *stackItem = mIconListToPageStack[node];
+ // Make sure to call through the virtual function showPage(int)
+ return showPage(d->mPageToInt[stackItem]);
+ }
+
+ return false;
+}
+
+
+bool KJanusWidget::showPage( int index )
+{
+ if( !d || !mValid )
+ {
+ return false;
+ }
+ else
+ {
+ return showPage(d->mIntToPage[index]);
+ }
+}
+
+
+bool KJanusWidget::showPage( QWidget *w )
+{
+ if( !w || !mValid )
+ {
+ return false;
+ }
+
+ if( mFace == TreeList || mFace == IconList )
+ {
+ mPageStack->raiseWidget( w );
+ mActivePageWidget = w;
+
+ int index = d->mPageToInt[w];
+ mTitleLabel->setText( d->mIntToTitle[index] );
+ if( mFace == TreeList )
+ {
+ QMap<QListViewItem *, QWidget *>::Iterator it;
+ for (it = mTreeListToPageStack.begin(); it != mTreeListToPageStack.end(); ++it){
+ QListViewItem *key = it.key();
+ QWidget *val = it.data();
+ if (val == w) {
+ mTreeList->setSelected(key, true );
+ break;
+ }
+ }
+ }
+ else
+ {
+ QMap<QListBoxItem *, QWidget *>::Iterator it;
+ for (it = mIconListToPageStack.begin(); it != mIconListToPageStack.end(); ++it){
+ QListBoxItem *key = it.key();
+ QWidget *val = it.data();
+ if (val == w) {
+ mIconList->setSelected( key, true );
+ break;
+ }
+ }
+ }
+ }
+ else if( mFace == Tabbed )
+ {
+ mTabControl->showPage(w);
+ mActivePageWidget = w;
+ }
+ else
+ {
+ return false;
+ }
+
+ return true;
+}
+
+
+int KJanusWidget::activePageIndex() const
+{
+ if( mFace == TreeList) {
+ QListViewItem *node = mTreeList->selectedItem();
+ if( !node ) { return -1; }
+ QWidget *stackItem = mTreeListToPageStack[node];
+ return d->mPageToInt[stackItem];
+ }
+ else if (mFace == IconList) {
+ QListBoxItem *node = mIconList->item( mIconList->currentItem() );
+ if( !node ) { return false; }
+ QWidget *stackItem = mIconListToPageStack[node];
+ return d->mPageToInt[stackItem];
+ }
+ else if( mFace == Tabbed ) {
+ QWidget *widget = mTabControl->currentPage();
+ return ( !widget ? -1 : d->mPageToInt[widget] );
+ }
+ else {
+ return -1;
+ }
+}
+
+
+int KJanusWidget::pageIndex( QWidget *widget ) const
+{
+ if( !widget )
+ {
+ return -1;
+ }
+ else if( mFace == TreeList || mFace == IconList )
+ {
+ return d->mPageToInt[widget];
+ }
+ else if( mFace == Tabbed )
+ {
+ //
+ // The user gets the real page widget with addVBoxPage(), addHBoxPage()
+ // and addGridPage() but not with addPage() which returns a child of
+ // the toplevel page. addPage() returns a QFrame so I check for that.
+ //
+ if( widget->isA("QFrame") )
+ {
+ return d->mPageToInt[widget->parentWidget()];
+ }
+ else
+ {
+ return d->mPageToInt[widget];
+ }
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+void KJanusWidget::slotFontChanged()
+{
+ if( mTitleLabel )
+ {
+ mTitleLabel->setFont( KGlobalSettings::generalFont() );
+ QFont titleFont( mTitleLabel->font() );
+ titleFont.setBold( true );
+ mTitleLabel->setFont( titleFont );
+ }
+
+ if( mFace == IconList )
+ {
+ QFont listFont( mIconList->font() );
+ listFont.setBold( true );
+ mIconList->setFont( listFont );
+ mIconList->invalidateHeight();
+ mIconList->invalidateWidth();
+ }
+}
+
+// makes the treelist behave like the list of kcontrol
+void KJanusWidget::slotItemClicked(QListViewItem *it)
+{
+ if(it && (it->childCount()>0))
+ it->setOpen(!it->isOpen());
+}
+
+void KJanusWidget::setFocus()
+{
+ if( !mValid ) { return; }
+ if( mFace == TreeList )
+ {
+ mTreeList->setFocus();
+ }
+ if( mFace == IconList )
+ {
+ mIconList->setFocus();
+ }
+ else if( mFace == Tabbed )
+ {
+ mTabControl->setFocus();
+ }
+ else if( mFace == Swallow )
+ {
+ mSwallowPage->setFocus();
+ }
+ else if( mFace == Plain )
+ {
+ mPlainPage->setFocus();
+ }
+}
+
+
+QSize KJanusWidget::minimumSizeHint() const
+{
+ if( mFace == TreeList || mFace == IconList )
+ {
+ QSize s1( KDialog::spacingHint(), KDialog::spacingHint()*2 );
+ QSize s2(0,0);
+ QSize s3(0,0);
+ QSize s4( mPageStack->sizeHint() );
+
+ if( mFace == TreeList )
+ {
+ s1.rwidth() += style().pixelMetric( QStyle::PM_SplitterWidth );
+ s2 = mTreeList->minimumSize();
+ }
+ else
+ {
+ mIconList->updateMinimumHeight();
+ mIconList->updateWidth();
+ s2 = mIconList->minimumSize();
+ }
+
+ if( mTitleLabel->isVisible() )
+ {
+ s3 += mTitleLabel->sizeHint();
+ s3.rheight() += mTitleSep->minimumSize().height();
+ }
+
+ //
+ // Select the tallest item. It has only effect in IconList mode
+ //
+ int h1 = s1.rheight() + s3.rheight() + s4.height();
+ int h2 = QMAX( h1, s2.rheight() );
+
+ return QSize( s1.width()+s2.width()+QMAX(s3.width(),s4.width()), h2 );
+ }
+ else if( mFace == Tabbed )
+ {
+ return mTabControl->sizeHint();
+ }
+ else if( mFace == Swallow )
+ {
+ return mSwallowPage->minimumSize();
+ }
+ else if( mFace == Plain )
+ {
+ return mPlainPage->sizeHint();
+ }
+ else
+ {
+ return QSize( 100, 100 ); // Should never happen though.
+ }
+
+}
+
+
+QSize KJanusWidget::sizeHint() const
+{
+ return minimumSizeHint();
+}
+
+
+void KJanusWidget::setTreeListAutoResize( bool state )
+{
+ if( mFace == TreeList )
+ {
+ mTreeListResizeMode = !state ?
+ QSplitter::KeepSize : QSplitter::Stretch;
+ if( d->mSplitter )
+ d->mSplitter->setResizeMode( d->mListFrame, mTreeListResizeMode );
+ }
+}
+
+
+void KJanusWidget::setIconListAllVisible( bool state )
+{
+ if( mFace == IconList )
+ {
+ mIconList->setShowAll( state );
+ }
+}
+
+void KJanusWidget::setShowIconsInTreeList( bool state )
+{
+ mShowIconsInTreeList = state;
+}
+
+void KJanusWidget::setRootIsDecorated( bool state )
+{
+ if( mFace == TreeList ) {
+ mTreeList->setRootIsDecorated(state);
+ }
+}
+
+void KJanusWidget::unfoldTreeList( bool persist )
+{
+ if( mFace == TreeList )
+ {
+ if( persist )
+ connect( mTreeList, SIGNAL( collapsed( QListViewItem * ) ), this, SLOT( slotReopen( QListViewItem * ) ) );
+ else
+ disconnect( mTreeList, SIGNAL( collapsed( QListViewItem * ) ), this, SLOT( slotReopen( QListViewItem * ) ) );
+
+ for( QListViewItem * item = mTreeList->firstChild(); item; item = item->itemBelow() )
+ item->setOpen( true );
+ }
+}
+
+void KJanusWidget::addWidgetBelowList( QWidget * widget )
+{
+ if( ( mFace == TreeList || mFace == IconList ) && d->mListFrame )
+ {
+ widget->reparent( d->mListFrame, QPoint() );
+ }
+}
+
+void KJanusWidget::addButtonBelowList( const QString & text, QObject * recv, const char * slot )
+{
+ if( ( mFace == TreeList || mFace == IconList ) && d->mListFrame )
+ {
+ QPushButton * button = new QPushButton( text, d->mListFrame, "KJanusWidget::buttonBelowList" );
+ connect( button, SIGNAL( clicked() ), recv, slot );
+ }
+}
+
+void KJanusWidget::addButtonBelowList( const KGuiItem & item, QObject * recv, const char * slot )
+{
+ if( ( mFace == TreeList || mFace == IconList ) && d->mListFrame )
+ {
+ KPushButton * button = new KPushButton( item, d->mListFrame, "KJanusWidget::buttonBelowList" );
+ connect( button, SIGNAL( clicked() ), recv, slot );
+ }
+}
+
+void KJanusWidget::showEvent( QShowEvent * )
+{
+ if( mFace == TreeList )
+ {
+ if( d->mSplitter )
+ d->mSplitter->setResizeMode( d->mListFrame, mTreeListResizeMode );
+ }
+}
+
+
+//
+// 2000-13-02 Espen Sand
+// It should be obvious that this eventfilter must only be
+// be installed on the vertical scrollbar of the mIconList.
+//
+bool KJanusWidget::eventFilter( QObject *o, QEvent *e )
+{
+ if( e->type() == QEvent::Show )
+ {
+ IconListItem *item = (IconListItem*)mIconList->item(0);
+ if( item )
+ {
+ int lw = item->width( mIconList );
+ int sw = mIconList->verticalScrollBar()->sizeHint().width();
+ mIconList->setFixedWidth( lw+sw+mIconList->frameWidth()*2 );
+ }
+ }
+ else if( e->type() == QEvent::Hide )
+ {
+ IconListItem *item = (IconListItem*)mIconList->item(0);
+ if( item )
+ {
+ int lw = item->width( mIconList );
+ mIconList->setFixedWidth( lw+mIconList->frameWidth()*2 );
+ }
+ }
+ return QWidget::eventFilter( o, e );
+}
+
+
+
+//
+// Code for the icon list box
+//
+
+
+KJanusWidget::IconListBox::IconListBox( QWidget *parent, const char *name,
+ WFlags f )
+ :KListBox( parent, name, f ), mShowAll(false), mHeightValid(false),
+ mWidthValid(false)
+{
+}
+
+
+void KJanusWidget::IconListBox::updateMinimumHeight()
+{
+ if( mShowAll && !mHeightValid )
+ {
+ int h = frameWidth()*2;
+ for( QListBoxItem *i = item(0); i; i = i->next() )
+ {
+ h += i->height( this );
+ }
+ setMinimumHeight( h );
+ mHeightValid = true;
+ }
+}
+
+
+void KJanusWidget::IconListBox::updateWidth()
+{
+ if( !mWidthValid )
+ {
+ int maxWidth = 10;
+ for( QListBoxItem *i = item(0); i; i = i->next() )
+ {
+ int w = ((IconListItem *)i)->width(this);
+ maxWidth = QMAX( w, maxWidth );
+ }
+
+ for( QListBoxItem *i = item(0); i; i = i->next() )
+ {
+ ((IconListItem *)i)->expandMinimumWidth( maxWidth );
+ }
+
+ if( verticalScrollBar()->isVisible() )
+ {
+ maxWidth += verticalScrollBar()->sizeHint().width();
+ }
+
+ setFixedWidth( maxWidth + frameWidth()*2 );
+ mWidthValid = true;
+ }
+}
+
+
+void KJanusWidget::IconListBox::invalidateHeight()
+{
+ mHeightValid = false;
+}
+
+
+void KJanusWidget::IconListBox::invalidateWidth()
+{
+ mWidthValid = false;
+}
+
+
+void KJanusWidget::IconListBox::setShowAll( bool showAll )
+{
+ mShowAll = showAll;
+ mHeightValid = false;
+}
+
+
+
+KJanusWidget::IconListItem::IconListItem( QListBox *listbox, const QPixmap &pixmap,
+ const QString &text )
+ : QListBoxItem( listbox )
+{
+ mPixmap = pixmap;
+ if( mPixmap.isNull() )
+ {
+ mPixmap = defaultPixmap();
+ }
+ setText( text );
+ mMinimumWidth = 0;
+}
+
+
+int KJanusWidget::IconListItem::expandMinimumWidth( int width )
+{
+ mMinimumWidth = QMAX( mMinimumWidth, width );
+ return mMinimumWidth;
+}
+
+
+const QPixmap &KJanusWidget::IconListItem::defaultPixmap()
+{
+ static QPixmap *pix=0;
+ if( !pix )
+ {
+ pix = new QPixmap( 32, 32 );
+ QPainter p( pix );
+ p.eraseRect( 0, 0, pix->width(), pix->height() );
+ p.setPen( Qt::red );
+ p.drawRect ( 0, 0, pix->width(), pix->height() );
+ p.end();
+
+ QBitmap mask( pix->width(), pix->height(), true );
+ mask.fill( Qt::black );
+ p.begin( &mask );
+ p.setPen( Qt::white );
+ p.drawRect ( 0, 0, pix->width(), pix->height() );
+ p.end();
+
+ pix->setMask( mask );
+ }
+ return *pix;
+}
+
+
+void KJanusWidget::IconListItem::paint( QPainter *painter )
+{
+ QFontMetrics fm = painter->fontMetrics();
+ int ht = fm.boundingRect( 0, 0, 0, 0, Qt::AlignCenter, text() ).height();
+ int wp = mPixmap.width();
+ int hp = mPixmap.height();
+
+ painter->drawPixmap( (mMinimumWidth-wp)/2, 5, mPixmap );
+ if( !text().isEmpty() )
+ {
+ painter->drawText( 0, hp+7, mMinimumWidth, ht, Qt::AlignCenter, text() );
+ }
+}
+
+int KJanusWidget::IconListItem::height( const QListBox *lb ) const
+{
+ if( text().isEmpty() )
+ {
+ return mPixmap.height();
+ }
+ else
+ {
+ int ht = lb->fontMetrics().boundingRect( 0, 0, 0, 0, Qt::AlignCenter, text() ).height();
+ return (mPixmap.height() + ht + 10);
+ }
+}
+
+
+int KJanusWidget::IconListItem::width( const QListBox *lb ) const
+{
+ int wt = lb->fontMetrics().boundingRect( 0, 0, 0, 0, Qt::AlignCenter, text() ).width() + 10;
+ int wp = mPixmap.width() + 10;
+ int w = QMAX( wt, wp );
+ return QMAX( w, mMinimumWidth );
+}
+
+
+void KJanusWidget::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+// TODO: In TreeList, if the last child of a node is removed, and there is no corrsponding widget for that node, allow the caller to
+// delete the node.
+void KJanusWidget::removePage( QWidget *page )
+{
+ if (!d || !d->mPageToInt.contains(page))
+ return;
+
+ int index = d->mPageToInt[page];
+
+ if ( mFace == TreeList )
+ {
+ QMap<QListViewItem*, QWidget *>::Iterator i;
+ for( i = mTreeListToPageStack.begin(); i != mTreeListToPageStack.end(); ++i )
+ if (i.data()==page)
+ {
+ delete i.key();
+ mPageStack->removeWidget(page);
+ mTreeListToPageStack.remove(i);
+ d->mIntToTitle.remove(index);
+ d->mPageToInt.remove(page);
+ d->mIntToPage.remove(index);
+ break;
+ }
+ }
+ else if ( mFace == IconList )
+ {
+ QMap<QListBoxItem*, QWidget *>::Iterator i;
+ for( i = mIconListToPageStack.begin(); i != mIconListToPageStack.end(); ++i )
+ if (i.data()==page)
+ {
+ delete i.key();
+ mPageStack->removeWidget(page);
+ mIconListToPageStack.remove(i);
+ d->mIntToTitle.remove(index);
+ d->mPageToInt.remove(page);
+ d->mIntToPage.remove(index);
+ break;
+ }
+ }
+ else // Tabbed
+ {
+ mTabControl->removePage(page);
+ d->mPageToInt.remove(page);
+ d->mIntToPage.remove(index);
+ }
+}
+
+QString KJanusWidget::pageTitle(int index) const
+{
+ if (!d || !d->mIntToTitle.contains(index))
+ return QString::null;
+ else
+ return d->mIntToTitle[index];
+}
+
+QWidget *KJanusWidget::pageWidget(int index) const
+{
+ if (!d || !d->mIntToPage.contains(index))
+ return 0;
+ else
+ return d->mIntToPage[index];
+}
+
+#include "kjanuswidget.moc"
diff --git a/kdeui/kjanuswidget.h b/kdeui/kjanuswidget.h
new file mode 100644
index 000000000..6fbd294fe
--- /dev/null
+++ b/kdeui/kjanuswidget.h
@@ -0,0 +1,606 @@
+/* This file is part of the KDE Libraries
+ * Copyright (C) 1999-2000 Espen Sand (espen@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _KJANUS_WIDGET_H_
+#define _KJANUS_WIDGET_H_
+
+#include <qptrlist.h>
+#include <qpixmap.h>
+#include <qsplitter.h>
+
+#include <klistbox.h>
+#include <qstringlist.h>
+#include <qmap.h>
+
+class KListView;
+
+class QGrid;
+class QHBox;
+class QLabel;
+class QTabWidget;
+class QVBox;
+class QWidgetStack;
+class KSeparator;
+class QListViewItem;
+class KGuiItem;
+
+/**
+ * @short Easy to use widget with many layouts
+ *
+ * Provides a number of ready to use layouts (faces). It is used
+ * as an internal widget in KDialogBase, but can also used as a
+ * widget of its own.
+ *
+ * This class provides KJanusWidget::TreeList, KJanusWidget::IconList,
+ * KJanusWidget::Tabbed, KJanusWidget::Plain and KJanusWidget::Swallow layouts.
+ *
+ * For all modes it is important that you specify the QWidget::minimumSize()
+ * on the page, plain widget or the swallowed widget. If you use a QLayout
+ * on the page, plain widget or the swallowed widget this will be taken care
+ * of automatically. The size is used when the KJanusWidget determines its
+ * own minimum size. You get the minimum size by using the
+ * minimumSizeHint() or sizeHint() methods.
+ *
+ * Pages that have been added in TreeList, IconList or Tabbed mode can be
+ * removed by simply deleting the page. However, it would be preferable to use
+ * the QObject::deleteLater() function on the page as the main event loop
+ * may have optimized UI update events of the page by scheduling them for later.
+ *
+ * @author Espen Sand (espen@kde.org)
+ */
+class KDEUI_EXPORT KJanusWidget : public QWidget
+{
+ Q_OBJECT
+
+ private:
+ class IconListBox : public KListBox
+ {
+ public:
+ IconListBox( QWidget *parent=0, const char *name=0, WFlags f=0 );
+ void updateMinimumHeight();
+ void updateWidth();
+ void invalidateHeight();
+ void invalidateWidth();
+ void setShowAll( bool showAll );
+
+ private:
+ bool mShowAll;
+ bool mHeightValid;
+ bool mWidthValid;
+ };
+
+ public:
+ enum Face
+ {
+ /**
+ * The TreeList face provides a list in the left area and pages in the
+ * right. The area are separated by a movable splitter. The style is somewhat
+ * similar to the layout in the Control Center. A page is raised by
+ * selecting the corresponding tree list item.
+ */
+ TreeList = 0,
+ /** The Tabbed face is a common tabbed widget. The procedure for creating a
+ * page is similar for creating a TreeList. This has the advantage that if
+ * your widget contain too many pages it is trivial to convert it into a
+ * TreeList. Just change the face in the KJanusWidget constructor to
+ * KJanusWidget::TreeList and you have a tree list layout instead.
+ */
+ Tabbed,
+ /**
+ * The Plain face provides an empty widget (QFrame) where you can place your
+ * widgets. The KJanusWidget makes no assumptions regarding the contents so
+ * you are free to add whatever you want.
+ */
+ Plain,
+ /**
+ * The Swallow face is provided in order to simplify the usage of existing
+ * widgets and to allow changing the visible widget. You specify the widget
+ * to be displayed by setSwallowedWidget(). Your widget will be
+ * reparented inside the widget. You can specify a Null (0) widget. A empty
+ * space is then displayed.
+ */
+ Swallow,
+ /**
+ * The IconList face provides an icon list in the left area and pages in the
+ * right. For each entry the Icon is on top with the text below. The style
+ * is somewhat similar to the layout of the Eudora configuation dialog box.
+ * A page is raised by selecting the corresponding icon list item. The
+ * preferred icon size is 32x32 pixels.
+ */
+ IconList
+ };
+
+ public:
+
+ /**
+ * Constructor where you specify the face.
+ *
+ * @param parent Parent of the widget.
+ * @param name Widget name.
+ * @param face The kind of dialog, Use TreeList, Tabbed, Plain or
+ * Swallow.
+ */
+ KJanusWidget( QWidget *parent=0, const char *name=0, int face=Plain );
+
+ /**
+ * Destructor.
+ */
+ ~KJanusWidget();
+
+ /**
+ * Raises the page which was added by addPage().
+ *
+ * @param index The index of the page you want to raise.
+ */
+ virtual bool showPage( int index );
+
+ /**
+ * Returns the index of the page that are currently displayed.
+ *
+ * @return The index or -1 if the face is not Tabbed, TreeList or
+ * IconList.
+ */
+ virtual int activePageIndex() const;
+
+ /**
+ * Use this to verify
+ * that no memory allocation failed.
+ *
+ * @return true if the widget was properly created.
+ */
+ virtual bool isValid() const;
+
+ /**
+ * Returns the face type.
+ *
+ * @return The face type.
+ */
+ virtual int face() const;
+
+ /**
+ * Returns the minimum size that must be made available for the widget
+ * so that UIs can be displayed properly
+ *
+ * @return The minimum size.
+ */
+ virtual QSize minimumSizeHint() const;
+
+ /**
+ * Returns the recommended size for the widget in order to be displayed
+ * properly.
+ *
+ * @return The recommended size.
+ */
+ virtual QSize sizeHint() const;
+
+ /**
+ * Returns the empty widget that is available in Plain mode.
+ *
+ * @return The widget or 0 if the face in not Plain.
+ */
+ virtual QFrame *plainPage();
+
+ /**
+ * Add a new page when the class is used in TreeList, IconList or Tabbed
+ * mode. The returned widget is empty and you must add your widgets
+ * as children to this widget. In most cases you must create a layout
+ * manager and associate it with this widget as well.
+ *
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ *
+ * @param item String used in the list or Tab item.
+ * @param header A longer string used in TreeList and IconList mode to
+ * describe the contents of a page. If empty, the item string
+ * will be used instead.
+ * @param pixmap Used in IconList mode or in TreeList mode. You should
+ * prefer a pixmap with size 32x32 pixels.
+ *
+ * @return The empty page or 0 if the face is not TreeList, IconList or
+ * Tabbed.
+ */
+ virtual QFrame *addPage(const QString &item,const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * This is like addPage just above, with the difference that the first
+ * element is a list of strings. These strings are used to form a path
+ * of folders down to the given page. The initial elements are names
+ * for the folders, while the last element is the name of the page.
+ * Note: This does yet only work for the TreeList face. Later this may
+ * be added for the IconList face too. In other faces than the
+ * TreeList, all the strings except the last one is ignored.
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ *
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ **/
+ virtual QFrame *addPage(const QStringList &items, const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * Add a new page when the class is used in TreeList, IconList or Tabbed
+ * mode. The returned widget is empty and you must add your widgets
+ * as children to this widget. The returned widget is a QVBox
+ * so it contains a QVBoxLayout layout that lines up the child widgets
+ * are vertically.
+ *
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ *
+ * @param item String used in the list or Tab item.
+ * @param header A longer string used in TreeList and IconList mode to
+ * describe the contents of a page. If empty, the item string
+ * will be used instead.
+ * @param pixmap Used in IconList mode or in TreeList mode. You should
+ * prefer a pixmap with size 32x32 pixels.
+ *
+ * @return The empty page or 0 if the face is not TreeList, IconList or
+ * Tabbed. */
+ virtual QVBox *addVBoxPage( const QString &item,
+ const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * This is like addVBoxPage just above, with the difference that the first
+ * element is a list of strings. These strings are used to form a path
+ * of folders down to the given page. The initial elements are names
+ * for the folders, while the last element is the name of the page.
+ * Note: This does yet only work for the TreeList face. Later this may
+ * be added for the IconList face too. In other faces than the
+ * TreeList, all the strings except the last one is ignored.
+ *
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ **/
+ virtual QVBox *addVBoxPage( const QStringList &items,
+ const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * Add a new page when the class is used in TreeList, IconList or Tabbed
+ * mode. The returned widget is empty and you must add your widgets
+ * as children to this widget. The returned widget is a QHBox
+ * so it contains a QHBoxLayout layout that lines up the child widgets
+ * are horizontally.
+ *
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ *
+ * @param itemName String used in the list or Tab item.
+ * @param header A longer string used in TreeList and IconList mode to
+ * describe the contents of a page. If empty, the item string
+ * will be used instead.
+ * @param pixmap Used in IconList mode or in TreeList mode. You should
+ * prefer a pixmap with size 32x32 pixels.
+ *
+ * @return The empty page or 0 if the face is not TreeList, IconList or
+ * Tabbed.
+ */
+ virtual QHBox *addHBoxPage( const QString &itemName,
+ const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * This is like addHBoxPage just above, with the difference that the first
+ * element is a list of strings. These strings are used to form a path
+ * of folders down to the given page. The initial elements are names
+ * for the folders, while the last element is the name of the page.
+ * Note: This does yet only work for the TreeList face. Later this may
+ * be added for the IconList face too. In other faces than the
+ * TreeList, all the strings except the last one is ignored.
+ *
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ **/
+ virtual QHBox *addHBoxPage( const QStringList &items,
+ const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * Add a new page when the class is used in either TreeList or Tabbed
+ * mode. The returned widget is empty and you must add your widgets
+ * as children to this widget. The returned widget is a QGrid
+ * so it contains a QGridLayout layout that places up the child widgets
+ * in a grid.
+ *
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ *
+ * @param n Specifies the number of columns if 'dir' is QGrid::Horizontal
+ * or the number of rows if 'dir' is QGrid::Vertical.
+ * @param dir Can be QGrid::Horizontal or QGrid::Vertical.
+ * @param itemName String used in the list or Tab item.
+ * @param header A longer string used in TreeList and IconList mode to
+ * describe the contents of a page. If empty, the item string
+ * will be used instead.
+ * @param pixmap Used in IconList mode or in TreeList mode. You should
+ * prefer a pixmap with size 32x32 pixels.
+ *
+ * @return The empty page or 0 if the face is not TreeList, IconList or
+ * Tabbed.
+ */
+ virtual QGrid *addGridPage( int n, Orientation dir,
+ const QString &itemName,
+ const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * This is like addGridPage just above, with the difference that the first
+ * element is a list of strings. These strings are used to form a path
+ * of folders down to the given page. The initial elements are names
+ * for the folders, while the last element is the name of the page.
+ * Note: This does yet only work for the TreeList face. Later this may
+ * be added for the IconList face too. In other faces than the
+ * TreeList, all the strings except the last one is ignored.
+ *
+ * Deleting the returned frame will cause the listitem or tab to be
+ * removed (you can re-add a page with the same name later.
+ **/
+ virtual QGrid *addGridPage( int n, Orientation dir,
+ const QStringList &items,
+ const QString &header=QString::null,
+ const QPixmap &pixmap=QPixmap() );
+
+ /**
+ * @short Removes a page created with addPage, addVBoxPage,
+ * addHBoxPage or addGridPage. If the page has already
+ * been deleted or has already been removed, nothing happens. The widget
+ * itself is not deleted.
+ *
+ * @param page The widget returned by addPage , addVBoxPage ,
+ * addHBoxPage or addGridPage .
+ */
+ void removePage( QWidget *page );
+
+
+ /**
+ * Returns the index of a page created with addPage ,
+ * addVBoxPage , addHBoxPage or addGridPage .
+ * You can can compare this index with the value returned from
+ * activePageIndex if you need to do some page specific actions
+ * in your code.
+ *
+ * The returned index will never change so you can safely use this
+ * function once and save the value.
+ *
+ * @param widget The widget returned by addPage , addVBoxPage ,
+ * addHBoxPage or addGridPage .
+ *
+ * @return The index or -1 if the face is not Tabbed, TreeList or
+ * IconList
+ */
+ virtual int pageIndex( QWidget *widget ) const;
+
+ /**
+ * Defines the widget to be swallowed.
+ *
+ * This method can be used several
+ * times. Only the latest defined widget will be shown.
+ *
+ * @param widget The widget to be swallowed. If 0, then an empty rectangle
+ * is displayed.
+ */
+ virtual bool setSwallowedWidget( QWidget *widget );
+
+ /**
+ * This function has only effect in TreeList mode.
+ *
+ * Defines how the tree list is resized when the widget is resized
+ * horizontally. By default the tree list keeps its width when the
+ * widget becomes wider.
+ *
+ * @param state The resize mode. If false (default) the TreeList keeps
+ * its current width when the widget becomes wider.
+ */
+ virtual void setTreeListAutoResize( bool state );
+
+ /**
+ * This function has only effect in TreeList mode.
+ *
+ * This tells the widgets whether the icons given in the addPage,
+ * addVBoxPage, addHBoxPage, or addGridPage methods should
+ * be shown in the TreeList.
+ *
+ * Note: This method must be called before calling any of the methods
+ * which add icons to the page.
+ *
+ * @param state If true the icons are shown.
+ **/
+ virtual void setShowIconsInTreeList(bool state);
+
+ /**
+ * This function has only effect in TreeList mode.
+ *
+ * This tells the widgets whether the root should be decorated.
+ * For details see QListView::setRootIsDecorated
+ *
+ * @param state Root will be decorated if true.
+ **/
+ virtual void setRootIsDecorated( bool state );
+
+ /**
+ * This function has only effect in TreeList mode.
+ *
+ * This tells the TreeList to unfold the whole tree so that all entries
+ * are visible.
+ *
+ * If the list is empty when you call this method newly created entries
+ * will not automatically be opened. If the @p persist flag is set opened
+ * entries cannot be closed again, though.
+ *
+ * @param persist If true the tree always stays unfolded.
+ * @since 3.2
+ */
+ /*virtual*/ void unfoldTreeList( bool persist = false ); //### KDE4 BIC add virtual
+
+ /**
+ * Add a widget at the bottom of the TreeList/IconList.
+ *
+ * @param widget The widget to be added. It will be reparented into the
+ * KJanusWidget, therefor it will be deleted with the
+ * KJanusWidget, too. To be on the save side just don't keep
+ * the pointer to this widget.
+ */
+ /*virtual*/ void addWidgetBelowList( QWidget * widget ); // ### KDE4
+
+ /**
+ * Add a button at the bottom of the TreeList/IconList.
+ *
+ * @param text The text on the PushButton.
+ * @param recv The object that is to receive the signal when the button
+ * is clicked.
+ * @param slot The slot to connect to the clicked signal of the button.
+ *
+ * @since 3.2
+ */
+ /*virtual*/ void addButtonBelowList( const QString & text, QObject * recv,
+ const char * slot ); //### KDE4
+
+ /**
+ * The same as the above function, but with a KGuiItem providing the text
+ * and icon for the button at the bottom of the TreeList/IconList.
+ *
+ * @param guiitem The text and icon on the PushButton.
+ * @param recv The object that is to receive the signal when the button
+ * is clicked.
+ * @param slot The slot to connect to the clicked signal of the button.
+ *
+ * @since 3.2
+ */
+ /*virtual*/ void addButtonBelowList( const KGuiItem & guiitem, QObject *
+ recv, const char * slot ); //### KDE4
+
+ /**
+ * This function has only effect in IconList mode.
+ *
+ * Defines how the icon list widget is displayed. By default it is
+ * the widgets in the pages that decide the minimum height
+ * of the toplevel widget. A vertical scrollbar can be used in
+ * the icon list area.
+ *
+ * @param state The visibility mode. If true, the minimum height is
+ * adjusted so that every icon in the list is visible at the
+ * same time. The vertical scrollbar will never be visible.
+ */
+ virtual void setIconListAllVisible( bool state );
+
+ /**
+ * Sets the icon used in TreeList Mode for the given path.
+ * @param path The path for which this icon should be shown.
+ * @param pixmap The icon used.
+ **/
+ virtual void setFolderIcon(const QStringList &path, const QPixmap &pixmap);
+ /**
+ * Returns the title string associated with a page index in TreeList or IconList mode.
+ * @param index The index of the page or null if there is no such page.
+ * @see pageIndex()
+ * @since 3.2
+ */
+ /*virtual*/ QString pageTitle(int index) const;
+ /**
+ * Returns the page widget associated with a page index or null if there is
+ * no such page.
+ * @param index The index of the page.
+ * @see pageIndex()
+ * @since 3.2
+ */
+ /*virtual*/ QWidget *pageWidget(int index) const;
+
+ signals:
+ /**
+ * This signal is emitted whenever the current page changes.
+ * @param page the new page.
+ * @since 3.4
+ */
+ void aboutToShowPage(QWidget *page);
+
+ public slots:
+ /**
+ * Give the keyboard input focus to the widget.
+ */
+ virtual void setFocus();
+
+ protected:
+ /**
+ * Reimplemented to handle the splitter width when the the face
+ * is TreeList
+ */
+ virtual void showEvent( QShowEvent * );
+
+ /**
+ * This function is used internally when in IconList mode. If you
+ * reimplement this class a make your own event filter, make sure to
+ * call this function from your filter.
+ *
+ * @param o Object that has received an event.
+ * @param e The event.
+ */
+ virtual bool eventFilter( QObject *o, QEvent *e );
+
+ private slots:
+ bool slotShowPage();
+ void slotFontChanged();
+ void slotItemClicked(QListViewItem *it);
+ void pageGone(QObject *obj); // signal from the added page's "destroyed" signal
+ void slotReopen(QListViewItem *item);
+
+ protected:
+ bool showPage( QWidget *w );
+ void addPageWidget( QFrame *page, const QStringList &items,
+ const QString &header, const QPixmap &pixmap );
+ void InsertTreeListItem(const QStringList &items, const QPixmap &pixmap, QFrame *page);
+ QWidget *FindParent();
+
+ private:
+ bool mValid;
+
+ // Obsolete members. Remove in KDE 4.
+ QPtrList<QWidget> *mPageList;
+ QStringList *mTitleList;
+
+ int mFace;
+ KListView *mTreeList;
+ IconListBox *mIconList;
+ QWidgetStack *mPageStack;
+ QLabel *mTitleLabel;
+ QTabWidget *mTabControl;
+ QFrame *mPlainPage;
+ QWidget *mSwallowPage;
+ QWidget *mActivePageWidget;
+ KSeparator *mTitleSep;
+ QSplitter::ResizeMode mTreeListResizeMode;
+ bool mShowIconsInTreeList;
+ QMap<QListViewItem *, QWidget *> mTreeListToPageStack;
+ QMap<QListBoxItem *, QWidget *> mIconListToPageStack;
+ QMap<QString, QPixmap> mFolderIconMap;
+ QMap<QString, QStringList> mChildrenNames;
+ QMap<QString, QWidget *> mChildPages;
+
+ public:
+ class IconListItem;
+ protected:
+ virtual void virtual_hook( int id, void* data );
+ private:
+ class KJanusWidgetPrivate;
+ KJanusWidgetPrivate *d;
+};
+
+#endif
diff --git a/kdeui/kkeybutton.cpp b/kdeui/kkeybutton.cpp
new file mode 100644
index 000000000..0472ab495
--- /dev/null
+++ b/kdeui/kkeybutton.cpp
@@ -0,0 +1,178 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1998 Mark Donohoe <donohoe@kde.org>
+ Copyright (C) 2001 Ellis Whitehead <ellis@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kkeybutton.h"
+#include "kshortcutdialog.h"
+
+#include <qcursor.h>
+#include <qdrawutil.h>
+#include <qpainter.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kglobalaccel.h>
+#include <klocale.h>
+
+#include "config.h"
+#ifdef Q_WS_X11
+#define XK_XKB_KEYS
+#define XK_MISCELLANY
+#include <X11/Xlib.h> // For x11Event()
+#include <X11/keysymdef.h> // For XK_...
+
+#ifdef KeyPress
+const int XFocusOut = FocusOut;
+const int XFocusIn = FocusIn;
+const int XKeyPress = KeyPress;
+const int XKeyRelease = KeyRelease;
+#undef KeyRelease
+#undef KeyPress
+#undef FocusOut
+#undef FocusIn
+#endif // KeyPress
+#endif // Q_WS_X11
+
+//static const char* psTemp[] = {
+// I18N_NOOP("Primary"), I18N_NOOP("Alternate"), I18N_NOOP("Multi-Key")
+//};
+
+class KKeyButtonPrivate
+{
+ public:
+ bool bQtShortcut;
+};
+
+/***********************************************************************/
+/* KKeyButton */
+/* */
+/* Initially added by Mark Donohoe <donohoe@kde.org> */
+/* */
+/***********************************************************************/
+
+KKeyButton::KKeyButton(QWidget *parent, const char *name)
+: QPushButton( parent, name )
+{
+ d = new KKeyButtonPrivate;
+ setFocusPolicy( QWidget::StrongFocus );
+ m_bEditing = false;
+ connect( this, SIGNAL(clicked()), this, SLOT(captureShortcut()) );
+ setShortcut( KShortcut(), true );
+}
+
+KKeyButton::~KKeyButton ()
+{
+ delete d;
+}
+
+void KKeyButton::setShortcut( const KShortcut& cut, bool bQtShortcut )
+{
+ d->bQtShortcut = bQtShortcut;
+ m_cut = cut;
+ QString keyStr = m_cut.toString();
+ keyStr.replace('&', QString::fromLatin1("&&"));
+ setText( keyStr.isEmpty() ? i18n("None") : keyStr );
+}
+
+// deprecated //
+void KKeyButton::setShortcut( const KShortcut& cut )
+{
+ setShortcut( cut, false );
+}
+
+void KKeyButton::setText( const QString& text )
+{
+ QPushButton::setText( text );
+ setFixedSize( sizeHint().width()+12, sizeHint().height()+8 );
+}
+
+void KKeyButton::captureShortcut()
+{
+ KShortcut cut;
+
+ m_bEditing = true;
+ repaint();
+
+ {
+ KShortcutDialog dlg( m_cut, d->bQtShortcut, this );
+ if( dlg.exec() == KDialog::Accepted )
+ cut = dlg.shortcut();
+ } // emit the signal after the dialog is destroyed, otherwise it still has grab
+ if( !cut.isNull())
+ emit capturedShortcut( cut );
+
+ m_bEditing = false;
+ repaint();
+}
+
+void KKeyButton::drawButton( QPainter *painter )
+{
+ QPointArray a( 4 );
+ a.setPoint( 0, 0, 0) ;
+ a.setPoint( 1, width(), 0 );
+ a.setPoint( 2, 0, height() );
+ a.setPoint( 3, 0, 0 );
+
+ QRegion r1( a );
+ painter->setClipRegion( r1 );
+ painter->setBrush( backgroundColor().light() );
+ painter->drawRoundRect( 0, 0, width(), height(), 20, 20);
+
+ a.setPoint( 0, width(), height() );
+ a.setPoint( 1, width(), 0 );
+ a.setPoint( 2, 0, height() );
+ a.setPoint( 3, width(), height() );
+
+ QRegion r2( a );
+ painter->setClipRegion( r2 );
+ painter->setBrush( backgroundColor().dark() );
+ painter->drawRoundRect( 0, 0, width(), height(), 20, 20 );
+
+ painter->setClipping( false );
+ if( width() > 12 && height() > 8 )
+ qDrawShadePanel( painter, 6, 4, width() - 12, height() - 8,
+ colorGroup(), true, 1, 0L );
+ if ( m_bEditing )
+ {
+ painter->setPen( colorGroup().base() );
+ painter->setBrush( colorGroup().base() );
+ }
+ else
+ {
+ painter->setPen( backgroundColor() );
+ painter->setBrush( backgroundColor() );
+ }
+ if( width() > 14 && height() > 10 )
+ painter->drawRect( 7, 5, width() - 14, height() - 10 );
+
+ drawButtonLabel( painter );
+
+ painter->setPen( colorGroup().text() );
+ painter->setBrush( NoBrush );
+ if( hasFocus() || m_bEditing )
+ {
+ if( width() > 16 && height() > 12 )
+ painter->drawRect( 8, 6, width() - 16, height() - 12 );
+ }
+
+}
+
+void KKeyButton::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "kkeybutton.moc"
diff --git a/kdeui/kkeybutton.h b/kdeui/kkeybutton.h
new file mode 100644
index 000000000..ebebfdb90
--- /dev/null
+++ b/kdeui/kkeybutton.h
@@ -0,0 +1,91 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2001, 2002 Ellis Whitehead <ellis@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _KKEYBUTTON_H_
+#define _KKEYBUTTON_H_
+
+#include <qpushbutton.h>
+#include <kshortcut.h>
+
+/**
+ * @short A push button that looks like a keyboard key.
+ *
+ * You must call setShortcut() to set the widget's currently displayed key.
+ * You can call captureShortcut() to get a new shortcut from the user.
+ * If captureShortcut() succeeds, then the capturedShortcut() signal will be
+ * emitted with the value of the new shortcut. The widget containing
+ * a KKeyButton widget must connect to this signal and check if the shortcut
+ * is valid. If it is, you will need to call setShortcut() with the new
+ * value in order make it the key currently displayed.
+ *
+ * @author Mark Donohoe <donohoe@kde.org>
+ * @internal
+ */
+class KDEUI_EXPORT KKeyButton: public QPushButton
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Constructs key button widget.
+ */
+ KKeyButton( QWidget *parent = 0, const char *name = 0 );
+ /**
+ * Destructs the key button widget.
+ */
+ virtual ~KKeyButton();
+
+ /** @deprecated Use setShortcut( cut, false ) instead */
+ void setShortcut( const KShortcut& cut ) KDE_DEPRECATED;
+ /// @since 3.1
+ void setShortcut( const KShortcut& cut, bool bQtShortcut );
+ const KShortcut& shortcut() const
+ { return m_cut; }
+
+ /**
+ * Reimplemented for internal purposes.
+ */
+ void setText( const QString& text );
+
+ signals:
+ void capturedShortcut( const KShortcut& );
+
+ public slots:
+ /**
+ * Call this method to capture a shortcut from the keyboard.
+ * If it succeeds, the capturedShortcut() signal will be emitted.
+ */
+ void captureShortcut();
+
+ protected:
+ KShortcut m_cut;
+ bool m_bEditing;
+
+ /**
+ * Reimplemented for internal reasons.
+ */
+ void drawButton( QPainter* _painter );
+
+ protected:
+ virtual void virtual_hook( int id, void* data );
+ private:
+ class KKeyButtonPrivate* d;
+};
+
+#endif
diff --git a/kdeui/kkeydialog.cpp b/kdeui/kkeydialog.cpp
new file mode 100644
index 000000000..5f831767a
--- /dev/null
+++ b/kdeui/kkeydialog.cpp
@@ -0,0 +1,1209 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1998 Mark Donohoe <donohoe@kde.org>
+ Copyright (C) 1997 Nicolas Hadacek <hadacek@kde.org>
+ Copyright (C) 1998 Matthias Ettrich <ettrich@kde.org>
+ Copyright (C) 2001 Ellis Whitehead <ellis@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kkeydialog.h"
+#include "kkeybutton.h"
+
+#include <string.h>
+
+#include <qbuttongroup.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qdrawutil.h>
+#include <qpainter.h>
+#include <qradiobutton.h>
+#include <qregexp.h>
+#include <qtoolbutton.h>
+#include <qwhatsthis.h>
+
+#include <kaccel.h>
+#include <kaction.h>
+#include <kaccelaction.h>
+#include <kactionshortcutlist.h>
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kglobalaccel.h>
+#include <kiconloader.h>
+#include <klistviewsearchline.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kshortcut.h>
+#include <kshortcutlist.h>
+#include <kxmlguifactory.h>
+#include <kaboutdata.h>
+#include <kstaticdeleter.h>
+
+#ifdef Q_WS_X11
+#define XK_XKB_KEYS
+#define XK_MISCELLANY
+#include <X11/Xlib.h> // For x11Event()
+#include <X11/keysymdef.h> // For XK_...
+#include <qwhatsthis.h>
+
+#ifdef KeyPress
+const int XFocusOut = FocusOut;
+const int XFocusIn = FocusIn;
+const int XKeyPress = KeyPress;
+const int XKeyRelease = KeyRelease;
+#undef KeyRelease
+#undef KeyPress
+#undef FocusOut
+#undef FocusIn
+#endif // KEYPRESS
+#endif // Q_WX_X11
+
+//---------------------------------------------------------------------
+// KKeyChooserItem
+//---------------------------------------------------------------------
+
+class KKeyChooserItem : public KListViewItem
+{
+ public:
+ KKeyChooserItem( KListView* parent, QListViewItem* after, KShortcutList* pList, uint iAction );
+ KKeyChooserItem( QListViewItem* parent, QListViewItem* after, KShortcutList* pList, uint iAction );
+
+ QString actionName() const;
+ const KShortcut& shortcut() const;
+ bool isConfigurable() const
+ { return m_pList->isConfigurable( m_iAction ); }
+ const KShortcut& shortcutDefault() const
+ { return m_pList->shortcutDefault( m_iAction ); }
+ QString whatsThis() const
+ { return m_pList->whatsThis( m_iAction ); }
+
+ void setShortcut( const KShortcut& cut );
+ void commitChanges();
+
+ virtual QString text( int iCol ) const;
+ virtual int compare( QListViewItem*, int iCol, bool bAscending ) const;
+
+ protected:
+ KShortcutList* m_pList;
+ uint m_iAction;
+ bool m_bModified;
+ KShortcut m_cut;
+};
+
+// WhatsThis on KKeyChooserItems
+class KKeyChooserWhatsThis : public QWhatsThis
+{
+public:
+ KKeyChooserWhatsThis( QListView* listview )
+ : QWhatsThis( listview->viewport() ), m_listView( listview ) {}
+
+protected:
+ virtual QString text( const QPoint& p );
+
+private:
+ QListView* m_listView;
+};
+
+//---------------------------------------------------------------------
+// KKeyChooserPrivate
+//---------------------------------------------------------------------
+
+class KKeyChooserPrivate
+{
+ public:
+ QValueList<KShortcutList*> rgpLists;
+ QValueList<KShortcutList*> rgpListsAllocated;
+
+ KListView *pList;
+ QLabel *lInfo;
+ KKeyButton *pbtnShortcut;
+ QGroupBox *fCArea;
+ QButtonGroup *kbGroup;
+
+ QMap<QString, KShortcut> mapGlobals;
+
+ // If this is set, then shortcuts require a modifier:
+ // so 'A' would not be valid, whereas 'Ctrl+A' would be.
+ // Note, however, that this only applies to printable characters.
+ // 'F1', 'Insert', etc., could still be used.
+ bool bAllowLetterShortcuts;
+ // When set, pressing the 'Default' button will select the aDefaultKeycode4,
+ // otherwise aDefaultKeycode.
+ bool bPreferFourModifierKeys;
+};
+
+//---------------------------------------------------------------------
+// KKeyChooser
+//---------------------------------------------------------------------
+
+KKeyChooser::KKeyChooser( QWidget* parent, ActionType type, bool bAllowLetterShortcuts )
+: QWidget( parent )
+{
+ initGUI( type, bAllowLetterShortcuts );
+}
+
+KKeyChooser::KKeyChooser( KActionCollection* coll, QWidget* parent, bool bAllowLetterShortcuts )
+: QWidget( parent )
+{
+ initGUI( Application, bAllowLetterShortcuts );
+ insert( coll );
+}
+
+KKeyChooser::KKeyChooser( KAccel* pAccel, QWidget* parent, bool bAllowLetterShortcuts )
+: QWidget( parent )
+{
+ initGUI( Application, bAllowLetterShortcuts );
+ insert( pAccel );
+}
+
+KKeyChooser::KKeyChooser( KGlobalAccel* pAccel, QWidget* parent )
+: QWidget( parent )
+{
+ initGUI( ApplicationGlobal, false );
+ insert( pAccel );
+}
+
+KKeyChooser::KKeyChooser( KShortcutList* pList, QWidget* parent, ActionType type, bool bAllowLetterShortcuts )
+: QWidget( parent )
+{
+ initGUI( type, bAllowLetterShortcuts );
+ insert( pList );
+}
+
+KKeyChooser::KKeyChooser( KAccel* actions, QWidget* parent,
+ bool bCheckAgainstStdKeys,
+ bool bAllowLetterShortcuts,
+ bool bAllowWinKey )
+: QWidget( parent )
+{
+ ActionType type;
+ if( bAllowWinKey )
+ type = (bCheckAgainstStdKeys) ? ApplicationGlobal : Global;
+ else
+ type = Application;
+
+ initGUI( type, bAllowLetterShortcuts );
+ insert( actions );
+}
+
+KKeyChooser::KKeyChooser( KGlobalAccel* actions, QWidget* parent,
+ bool bCheckAgainstStdKeys,
+ bool bAllowLetterShortcuts,
+ bool /*bAllowWinKey*/ )
+: QWidget( parent )
+{
+ ActionType type = (bCheckAgainstStdKeys) ? ApplicationGlobal : Global;
+
+ initGUI( type, bAllowLetterShortcuts );
+ insert( actions );
+}
+
+// list of all existing KKeyChooser's
+// Used when checking global shortcut for a possible conflict
+// (just checking against kdeglobals isn't enough, the shortcuts
+// might have changed in KKeyChooser and not being saved yet).
+// Also used when reassigning a shortcut from one chooser to another.
+static QValueList< KKeyChooser* >* allChoosers = NULL;
+static KStaticDeleter< QValueList< KKeyChooser* > > allChoosersDeleter;
+
+KKeyChooser::~KKeyChooser()
+{
+ allChoosers->remove( this );
+ // Delete allocated KShortcutLists
+ for( uint i = 0; i < d->rgpListsAllocated.count(); i++ )
+ delete d->rgpListsAllocated[i];
+ delete d;
+}
+
+bool KKeyChooser::insert( KActionCollection *pColl)
+{
+ return insert(pColl, QString::null);
+}
+
+bool KKeyChooser::insert( KActionCollection* pColl, const QString &title )
+{
+ QString str = title;
+ if ( title.isEmpty() && pColl->instance()
+ && pColl->instance()->aboutData() )
+ str = pColl->instance()->aboutData()->programName();
+
+ KShortcutList* pList = new KActionShortcutList( pColl );
+ d->rgpListsAllocated.append( pList );
+ d->rgpLists.append( pList );
+ buildListView(d->rgpLists.count() - 1, str);
+ return true;
+}
+
+bool KKeyChooser::insert( KAccel* pAccel )
+{
+ KShortcutList* pList = new KAccelShortcutList( pAccel );
+ d->rgpListsAllocated.append( pList );
+ return insert( pList );
+}
+
+bool KKeyChooser::insert( KGlobalAccel* pAccel )
+{
+ KShortcutList* pList = new KAccelShortcutList( pAccel );
+ d->rgpListsAllocated.append( pList );
+ return insert( pList );
+}
+
+bool KKeyChooser::insert( KShortcutList* pList )
+{
+ d->rgpLists.append( pList );
+ buildListView( d->rgpLists.count() - 1, QString::null );
+ return true;
+}
+
+void KKeyChooser::commitChanges()
+{
+ kdDebug(125) << "KKeyChooser::commitChanges()" << endl;
+
+ QListViewItemIterator it( d->pList );
+ for( ; it.current(); ++it ) {
+ KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>(it.current());
+ if( pItem )
+ pItem->commitChanges();
+ }
+}
+
+void KKeyChooser::save()
+{
+ commitChanges();
+ for( uint i = 0; i < d->rgpLists.count(); i++ )
+ d->rgpLists[i]->save();
+}
+
+void KKeyChooser::initGUI( ActionType type, bool bAllowLetterShortcuts )
+{
+ d = new KKeyChooserPrivate();
+
+ m_type = type;
+ d->bAllowLetterShortcuts = bAllowLetterShortcuts;
+
+ d->bPreferFourModifierKeys = KGlobalAccel::useFourModifierKeys();
+
+ //
+ // TOP LAYOUT MANAGER
+ //
+ // The following layout is used for the dialog
+ // LIST LABELS LAYOUT
+ // SPLIT LIST BOX WIDGET
+ // CHOOSE KEY GROUP BOX WIDGET
+ // BUTTONS LAYOUT
+ // Items are added to topLayout as they are created.
+ //
+
+ QBoxLayout *topLayout = new QVBoxLayout( this, 0, KDialog::spacingHint() );
+
+ //
+ // ADD SEARCHLINE
+ //
+ QHBoxLayout* searchLayout = new QHBoxLayout(0, 0, KDialog::spacingHint());
+ topLayout->addLayout(searchLayout, 10);
+
+ QToolButton *clearSearch = new QToolButton(this);
+ clearSearch->setTextLabel(i18n("Clear Search"), true);
+ clearSearch->setIconSet(SmallIconSet(QApplication::reverseLayout() ? "clear_left" : "locationbar_erase"));
+ searchLayout->addWidget(clearSearch);
+ QLabel* slbl = new QLabel(i18n("&Search:"), this);
+ searchLayout->addWidget(slbl);
+ KListViewSearchLine* listViewSearch = new KListViewSearchLine(this);
+ searchLayout->addWidget(listViewSearch);
+ slbl->setBuddy(listViewSearch);
+ connect(clearSearch, SIGNAL(pressed()), listViewSearch, SLOT(clear()));
+
+ QString wtstr = i18n("Search interactively for shortcut names (e.g. Copy) "
+ "or combination of keys (e.g. Ctrl+C) by typing them here.");
+
+ QWhatsThis::add(slbl, wtstr);
+ QWhatsThis::add(listViewSearch, wtstr);
+
+ //
+ // CREATE SPLIT LIST BOX
+ //
+ // fill up the split list box with the action/key pairs.
+ //
+ QGridLayout *stackLayout = new QGridLayout(2, 2, 2);
+ topLayout->addLayout( stackLayout, 10 );
+ stackLayout->setRowStretch( 1, 10 ); // Only list will stretch
+
+ d->pList = new KListView( this );
+ listViewSearch->setListView(d->pList); // Plug into search line
+ QValueList<int> columns;
+ columns.append(0);
+ listViewSearch->setSearchColumns(columns);
+
+ stackLayout->addMultiCellWidget( d->pList, 1, 1, 0, 1 );
+
+ wtstr = i18n("Here you can see a list of key bindings, "
+ "i.e. associations between actions (e.g. 'Copy') "
+ "shown in the left column and keys or combination "
+ "of keys (e.g. Ctrl+V) shown in the right column.");
+
+ QWhatsThis::add( d->pList, wtstr );
+ new KKeyChooserWhatsThis( d->pList );
+
+ d->pList->setAllColumnsShowFocus( true );
+ d->pList->addColumn(i18n("Action"));
+ d->pList->addColumn(i18n("Shortcut"));
+ d->pList->addColumn(i18n("Alternate"));
+
+ connect( d->pList, SIGNAL(currentChanged(QListViewItem*)),
+ SLOT(slotListItemSelected(QListViewItem*)) );
+
+ // handle double clicking an item
+ connect ( d->pList, SIGNAL ( doubleClicked ( QListViewItem *, const QPoint &, int ) ),
+ SLOT ( captureCurrentItem()) );
+ connect ( d->pList, SIGNAL ( spacePressed( QListViewItem* )), SLOT( captureCurrentItem()));
+ //
+ // CREATE CHOOSE KEY GROUP
+ //
+ d->fCArea = new QGroupBox( this );
+ topLayout->addWidget( d->fCArea, 1 );
+
+ d->fCArea->setTitle( i18n("Shortcut for Selected Action") );
+ d->fCArea->setFrameStyle( QFrame::GroupBoxPanel | QFrame::Plain );
+
+ //
+ // CHOOSE KEY GROUP LAYOUT MANAGER
+ //
+ QGridLayout *grid = new QGridLayout( d->fCArea, 3, 4, KDialog::spacingHint() );
+ grid->addRowSpacing( 0, fontMetrics().lineSpacing() );
+
+ d->kbGroup = new QButtonGroup( d->fCArea );
+ d->kbGroup->hide();
+ d->kbGroup->setExclusive( true );
+
+ m_prbNone = new QRadioButton( i18n("no key", "&None"), d->fCArea );
+ d->kbGroup->insert( m_prbNone, NoKey );
+ m_prbNone->setEnabled( false );
+ //grid->addMultiCellWidget( rb, 1, 1, 1, 2 );
+ grid->addWidget( m_prbNone, 1, 0 );
+ QWhatsThis::add( m_prbNone, i18n("The selected action will not be associated with any key.") );
+ connect( m_prbNone, SIGNAL(clicked()), SLOT(slotNoKey()) );
+
+ m_prbDef = new QRadioButton( i18n("default key", "De&fault"), d->fCArea );
+ d->kbGroup->insert( m_prbDef, DefaultKey );
+ m_prbDef->setEnabled( false );
+ //grid->addMultiCellWidget( rb, 2, 2, 1, 2 );
+ grid->addWidget( m_prbDef, 1, 1 );
+ QWhatsThis::add( m_prbDef, i18n("This will bind the default key to the selected action. Usually a reasonable choice.") );
+ connect( m_prbDef, SIGNAL(clicked()), SLOT(slotDefaultKey()) );
+
+ m_prbCustom = new QRadioButton( i18n("C&ustom"), d->fCArea );
+ d->kbGroup->insert( m_prbCustom, CustomKey );
+ m_prbCustom->setEnabled( false );
+ //grid->addMultiCellWidget( rb, 3, 3, 1, 2 );
+ grid->addWidget( m_prbCustom, 1, 2 );
+ QWhatsThis::add( m_prbCustom, i18n("If this option is selected you can create a customized key binding for the"
+ " selected action using the buttons below.") );
+ connect( m_prbCustom, SIGNAL(clicked()), SLOT(slotCustomKey()) );
+
+ //connect( d->kbGroup, SIGNAL( clicked( int ) ), SLOT( keyMode( int ) ) );
+
+ QBoxLayout *pushLayout = new QHBoxLayout( KDialog::spacingHint() );
+ grid->addLayout( pushLayout, 1, 3 );
+
+ d->pbtnShortcut = new KKeyButton(d->fCArea, "key");
+ d->pbtnShortcut->setEnabled( false );
+ connect( d->pbtnShortcut, SIGNAL(capturedShortcut(const KShortcut&)), SLOT(capturedShortcut(const KShortcut&)) );
+ grid->addRowSpacing( 1, d->pbtnShortcut->sizeHint().height() + 5 );
+
+ wtstr = i18n("Use this button to choose a new shortcut key. Once you click it, "
+ "you can press the key-combination which you would like to be assigned "
+ "to the currently selected action.");
+ QWhatsThis::add( d->pbtnShortcut, wtstr );
+
+ //
+ // Add widgets to the geometry manager
+ //
+ pushLayout->addSpacing( KDialog::spacingHint()*2 );
+ pushLayout->addWidget( d->pbtnShortcut );
+ pushLayout->addStretch( 10 );
+
+ d->lInfo = new QLabel(d->fCArea);
+ //resize(0,0);
+ //d->lInfo->setAlignment( AlignCenter );
+ //d->lInfo->setEnabled( false );
+ //d->lInfo->hide();
+ grid->addMultiCellWidget( d->lInfo, 2, 2, 0, 3 );
+
+ //d->globalDict = new QDict<int> ( 100, false );
+ //d->globalDict->setAutoDelete( true );
+ readGlobalKeys();
+ //d->stdDict = new QDict<int> ( 100, false );
+ //d->stdDict->setAutoDelete( true );
+ //if (type == Application || type == ApplicationGlobal)
+ // readStdKeys();
+ connect( kapp, SIGNAL( settingsChanged( int )), SLOT( slotSettingsChanged( int )));
+ if( allChoosers == NULL )
+ allChoosers = allChoosersDeleter.setObject( allChoosers, new QValueList< KKeyChooser* > );
+ allChoosers->append( this );
+}
+
+// Add all shortcuts to the list
+void KKeyChooser::buildListView( uint iList, const QString &title )
+{
+ KShortcutList* pList = d->rgpLists[iList];
+ KActionShortcutList *pAList = dynamic_cast<KActionShortcutList*>(pList);
+
+ if( m_type == Global || m_type == ApplicationGlobal )
+ d->pList->setSorting( -1 );
+ KListViewItem *pProgramItem, *pGroupItem = 0, *pParentItem, *pItem;
+
+ QString str = (title.isEmpty() ? i18n("Shortcuts") : title);
+ pParentItem = pProgramItem = pItem = new KListViewItem( d->pList, str );
+ pParentItem->setExpandable( true );
+ pParentItem->setOpen( true );
+ pParentItem->setSelectable( false );
+ uint nSize = pList->count();
+ for( uint iAction = 0; iAction < nSize; iAction++ ) {
+ QString sName = pList->name(iAction);
+ kdDebug(125) << "Key: " << sName << endl;
+ if( sName.startsWith( "Program:" ) ) {
+ pItem = new KListViewItem( d->pList, pProgramItem, pList->label(iAction) );
+ pItem->setSelectable( false );
+ pItem->setExpandable( true );
+ pItem->setOpen( true );
+ if( !pProgramItem->firstChild() )
+ delete pProgramItem;
+ pProgramItem = pParentItem = pItem;
+ } else if( sName.startsWith( "Group:" ) ) {
+ pItem = new KListViewItem( pProgramItem, pParentItem, pList->label(iAction) );
+ pItem->setSelectable( false );
+ pItem->setExpandable( true );
+ pItem->setOpen( true );
+ if( pGroupItem && !pGroupItem->firstChild() )
+ delete pGroupItem;
+ pGroupItem = pParentItem = pItem;
+ } else if( !sName.isEmpty() && sName != "unnamed" && pList->isConfigurable(iAction) ) {
+ pItem = new KKeyChooserItem( pParentItem, pItem, pList, iAction );
+ if(pAList)
+ pItem->setPixmap(0,pAList->action(iAction)->iconSet().pixmap(QIconSet::Small,QIconSet::Normal));
+ }
+ }
+ if( !pProgramItem->firstChild() )
+ delete pProgramItem;
+ if( pGroupItem && !pGroupItem->firstChild() )
+ delete pGroupItem;
+}
+
+
+void KKeyChooser::updateButtons()
+{
+ // Hack: Do this incase we still have changeKey() running.
+ // Better would be to capture the mouse pointer so that we can't click
+ // around while we're supposed to be entering a key.
+ // Better yet would be a modal dialog for changeKey()!
+ releaseKeyboard();
+ KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>( d->pList->currentItem() );
+
+ if ( !pItem ) {
+ // if nothing is selected -> disable radio boxes
+ m_prbNone->setEnabled( false );
+ m_prbDef->setEnabled( false );
+ m_prbCustom->setEnabled( false );
+ d->pbtnShortcut->setEnabled( false );
+ d->pbtnShortcut->setShortcut( KShortcut(), false );
+ } else {
+ bool bConfigurable = pItem->isConfigurable();
+ bool bQtShortcut = (m_type == Application || m_type == Standard);
+ const KShortcut& cutDef = pItem->shortcutDefault();
+
+ // Set key strings
+ QString keyStrCfg = pItem->shortcut().toString();
+ QString keyStrDef = cutDef.toString();
+
+ d->pbtnShortcut->setShortcut( pItem->shortcut(), bQtShortcut );
+ //item->setText( 1, keyStrCfg );
+ pItem->repaint();
+ d->lInfo->setText( i18n("Default key:") + QString(" %1").arg(keyStrDef.isEmpty() ? i18n("None") : keyStrDef) );
+
+ // Select the appropriate radio button.
+ int index = (pItem->shortcut().isNull()) ? NoKey
+ : (pItem->shortcut() == cutDef) ? DefaultKey
+ : CustomKey;
+ m_prbNone->setChecked( index == NoKey );
+ m_prbDef->setChecked( index == DefaultKey );
+ m_prbCustom->setChecked( index == CustomKey );
+
+ // Enable buttons if this key is configurable.
+ // The 'Default Key' button must also have a default key.
+ m_prbNone->setEnabled( bConfigurable );
+ m_prbDef->setEnabled( bConfigurable && cutDef.count() != 0 );
+ m_prbCustom->setEnabled( bConfigurable );
+ d->pbtnShortcut->setEnabled( bConfigurable );
+ }
+}
+
+void KKeyChooser::slotNoKey()
+{
+ // return if no key is selected
+ KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>( d->pList->currentItem() );
+ if( pItem ) {
+ //kdDebug(125) << "no Key" << d->pList->currentItem()->text(0) << endl;
+ pItem->setShortcut( KShortcut() );
+ updateButtons();
+ emit keyChange();
+ }
+}
+
+void KKeyChooser::slotDefaultKey()
+{
+ // return if no key is selected
+ KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>( d->pList->currentItem() );
+ if( pItem ) // don't set it directly, check for conflicts
+ setShortcut( pItem->shortcutDefault() );
+}
+
+void KKeyChooser::slotCustomKey()
+{
+ d->pbtnShortcut->captureShortcut();
+}
+
+void KKeyChooser::readGlobalKeys()
+{
+ d->mapGlobals.clear();
+ if( m_type == Global )
+ return; // they will be checked normally, because we're configuring them
+ readGlobalKeys( d->mapGlobals );
+}
+
+void KKeyChooser::readGlobalKeys( QMap< QString, KShortcut >& map )
+{
+ QMap<QString, QString> mapEntry = KGlobal::config()->entryMap( "Global Shortcuts" );
+ QMap<QString, QString>::Iterator it( mapEntry.begin() );
+ for( uint i = 0; it != mapEntry.end(); ++it, i++ )
+ map[it.key()] = KShortcut(*it);
+}
+
+void KKeyChooser::slotSettingsChanged( int category )
+{
+ if( category == KApplication::SETTINGS_SHORTCUTS )
+ readGlobalKeys(); // reread
+}
+
+void KKeyChooser::fontChange( const QFont & )
+{
+ d->fCArea->setMinimumHeight( 4*d->pbtnShortcut->sizeHint().height() );
+
+ int widget_width = 0;
+
+ setMinimumWidth( 20+5*(widget_width+10) );
+}
+
+// KDE4 IMHO this shouldn't be here at all - it cannot check whether the default
+// shortcut don't conflict with some already changed ones (e.g. global shortcuts).
+// Also, I personally find reseting all shortcuts to default (i.e. hardcoded in the app)
+// ones after pressing the 'Default' button rather a misfeature.
+void KKeyChooser::allDefault()
+{
+ kdDebug(125) << "KKeyChooser::allDefault()" << endl;
+
+ QListViewItemIterator it( d->pList );
+ for( ; it.current(); ++it ) {
+ KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>(it.current());
+ if( pItem )
+ pItem->setShortcut( pItem->shortcutDefault() );
+ }
+
+ updateButtons();
+ emit keyChange();
+}
+
+void KKeyChooser::slotListItemSelected( QListViewItem* )
+{
+ updateButtons();
+}
+
+void KKeyChooser::slotListItemDoubleClicked ( QListViewItem *, const QPoint & , int )
+{ // KDE4 dump this
+ captureCurrentItem();
+}
+
+void KKeyChooser::captureCurrentItem()
+{
+ KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>( d->pList->currentItem() );
+ if( pItem != NULL && pItem->isConfigurable())
+ d->pbtnShortcut->captureShortcut ( );
+}
+
+void KKeyChooser::setPreferFourModifierKeys( bool bPreferFourModifierKeys )
+{
+ d->bPreferFourModifierKeys = bPreferFourModifierKeys;
+}
+
+void KKeyChooser::capturedShortcut( const KShortcut& cut )
+{
+ if( cut.isNull() )
+ slotNoKey();
+ else
+ setShortcut( cut );
+}
+
+// FIXME: give this functionality again -- I don't think it's ever used, though. -- ellis
+// TODO: Check lxr.kde.org to see if it's used anywhere
+void KKeyChooser::listSync()
+{
+/* kdDebug(125) << "KKeyChooser::listSync()" << endl;
+
+ if( d->pColl ) {
+ // TODO: This is very inefficient. Come up with something better.
+ KAccelActions aa;
+ d->pColl->createKeyMap( aa );
+ d->actionsNew.updateShortcuts( aa );
+ } else if( d->pActionsOrig ) {
+ d->actionsNew.updateShortcuts( *d->pActionsOrig );
+ update();
+ updateButtons();
+ }*/
+}
+
+void KKeyChooser::syncToConfig( const QString& sConfigGroup, KConfigBase* pConfig, bool bClearUnset )
+{
+ kdDebug(125) << "KKeyChooser::syncToConfig( \"" << sConfigGroup << "\", " << pConfig << " ) start" << endl;
+ if( !pConfig )
+ pConfig = KGlobal::config();
+ KConfigGroupSaver cgs( pConfig, sConfigGroup );
+
+ QListViewItemIterator it( d->pList );
+ for( ; it.current(); ++it ) {
+ KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>(it.current());
+ if( pItem ) {
+ QString sEntry = pConfig->readEntry( pItem->actionName() );
+ if( !sEntry.isNull() || bClearUnset ) {
+ if( sEntry == "none" )
+ sEntry = QString::null;
+ pItem->setShortcut( sEntry );
+ }
+ kdDebug(125) << pItem->actionName() << " = " << pItem->shortcut().toStringInternal() << endl;
+ }
+ }
+ updateButtons();
+ kdDebug(125) << "KKeyChooser::syncToConfig() done" << endl;
+}
+
+void KKeyChooser::setShortcut( const KShortcut& cut )
+{
+ kdDebug(125) << "KKeyChooser::setShortcut( " << cut.toString() << " )" << endl;
+ KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>(d->pList->currentItem());
+ if( !pItem )
+ return;
+
+ for( uint i = 0; i < cut.count(); i++ ) {
+ const KKeySequence& seq = cut.seq(i);
+ const KKey& key = seq.key(0);
+
+ if( !d->bAllowLetterShortcuts && key.modFlags() == 0
+ && key.sym() < 0x3000 && QChar(key.sym()).isLetterOrNumber() ) {
+ QString s = i18n( "In order to use the '%1' key as a shortcut, "
+ "it must be combined with the "
+ "Win, Alt, Ctrl, and/or Shift keys." ).arg(QChar(key.sym()));
+ KMessageBox::sorry( this, s, i18n("Invalid Shortcut Key") );
+ return;
+ }
+ }
+
+ // If key isn't already in use,
+ if( !isKeyPresent( cut ) ) {
+ // Set new key code
+ pItem->setShortcut( cut );
+ // Update display
+ updateButtons();
+ emit keyChange();
+ }
+}
+
+// Returns iSeq index if cut2 has a sequence of equal or higher priority to a sequence in cut.
+// else -1
+static int keyConflict( const KShortcut& cut, const KShortcut& cut2 )
+{
+ for( uint iSeq = 0; iSeq < cut.count(); iSeq++ ) {
+ for( uint iSeq2 = 0; iSeq2 < cut2.count(); iSeq2++ ) {
+ if( cut.seq(iSeq) == cut2.seq(iSeq2) )
+ return iSeq;
+ }
+ }
+ return -1;
+}
+
+// Removes the sequences in cut2 from cut1
+static void removeFromShortcut( KShortcut & cut1, const KShortcut &cut2)
+{
+ for( uint iSeq2 = 0; iSeq2 < cut2.count(); iSeq2++ )
+ cut1.remove(cut2.seq(iSeq2));
+}
+
+bool KKeyChooser::isKeyPresent( const KShortcut& cut, bool bWarnUser )
+{
+ KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>(d->pList->currentItem());
+
+ if (!pItem) {
+ return false;
+ }
+
+ bool has_global_chooser = false;
+ bool has_standard_chooser = false;
+ for( QValueList< KKeyChooser* >::ConstIterator it = allChoosers->begin();
+ it != allChoosers->end();
+ ++it ) {
+ has_global_chooser |= ((*it)->m_type == Global);
+ has_standard_chooser |= ((*it)->m_type == Standard);
+ }
+
+ // If editing global shortcuts, check them for conflicts with the stdaccels.
+ if( m_type == ApplicationGlobal || m_type == Global ) {
+ if( !has_standard_chooser ) {
+ if( checkStandardShortcutsConflict( cut, bWarnUser, this ))
+ return true;
+ }
+ }
+
+ // only check the global keys if one of the keychoosers isn't global
+ if( !has_global_chooser ) {
+ if( checkGlobalShortcutsConflict( cut, bWarnUser, this, d->mapGlobals,
+ m_type == Global ? pItem->actionName() : QString::null ))
+ return true;
+ }
+
+ if( isKeyPresentLocally( cut, pItem, bWarnUser ))
+ return true;
+
+ // check also other KKeyChooser's
+ for( QValueList< KKeyChooser* >::ConstIterator it = allChoosers->begin();
+ it != allChoosers->end();
+ ++it ) {
+ if( (*it) != this && (*it)->isKeyPresentLocally( cut, NULL, bWarnUser ))
+ return true;
+ }
+ return false;
+}
+
+// KDE4 remove
+bool KKeyChooser::isKeyPresentLocally( const KShortcut& cut, KKeyChooserItem* ignoreItem, const QString& warnText )
+{
+ return isKeyPresentLocally( cut, ignoreItem, !warnText.isNull());
+}
+
+bool KKeyChooser::isKeyPresentLocally( const KShortcut& cut, KKeyChooserItem* ignoreItem, bool bWarnUser )
+{
+ if ( cut.toString().isEmpty())
+ return false;
+ // Search for shortcut conflicts with other actions in the
+ // lists we're configuring.
+ for( QListViewItemIterator it( d->pList ); it.current(); ++it ) {
+ KKeyChooserItem* pItem2 = dynamic_cast<KKeyChooserItem*>(it.current());
+ if( pItem2 && pItem2 != ignoreItem ) {
+ int iSeq = keyConflict( cut, pItem2->shortcut() );
+ if( iSeq > -1 ) {
+ if( bWarnUser ) {
+ if( !promptForReassign( cut.seq(iSeq), pItem2->text(0), Application, this ))
+ return true;
+ // else remove the shortcut from it
+ KShortcut cut2 = pItem2->shortcut();
+ removeFromShortcut(cut2, cut);
+ pItem2->setShortcut(cut2);
+ updateButtons();
+ emit keyChange();
+ }
+ }
+ }
+ }
+ return false;
+}
+
+bool KKeyChooser::checkStandardShortcutsConflict( const KShortcut& cut, bool bWarnUser, QWidget* parent )
+{
+ // For each key sequence in the shortcut,
+ for( uint i = 0; i < cut.count(); i++ ) {
+ const KKeySequence& seq = cut.seq(i);
+ KStdAccel::StdAccel id = KStdAccel::findStdAccel( seq );
+ if( id != KStdAccel::AccelNone
+ && keyConflict( cut, KStdAccel::shortcut( id ) ) > -1 ) {
+ if( bWarnUser ) {
+ if( !promptForReassign( seq, KStdAccel::label(id), Standard, parent ))
+ return true;
+ removeStandardShortcut( KStdAccel::label(id), dynamic_cast< KKeyChooser* > ( parent ), KStdAccel::shortcut( id ), cut);
+ }
+ }
+ }
+ return false;
+}
+
+bool KKeyChooser::checkGlobalShortcutsConflict( const KShortcut& cut, bool bWarnUser, QWidget* parent )
+{
+ QMap< QString, KShortcut > map;
+ readGlobalKeys( map );
+ return checkGlobalShortcutsConflict( cut, bWarnUser, parent, map, QString::null );
+}
+
+bool KKeyChooser::checkGlobalShortcutsConflict( const KShortcut& cut, bool bWarnUser, QWidget* parent,
+ const QMap< QString, KShortcut >& map, const QString& ignoreAction )
+{
+ QMap<QString, KShortcut>::ConstIterator it;
+ for( it = map.begin(); it != map.end(); ++it ) {
+ int iSeq = keyConflict( cut, (*it) );
+ if( iSeq > -1 ) {
+ if( ignoreAction.isEmpty() || it.key() != ignoreAction ) {
+ if( bWarnUser ) {
+ if( !promptForReassign( cut.seq(iSeq), it.key(), Global, parent ))
+ return true;
+ removeGlobalShortcut( it.key(), dynamic_cast< KKeyChooser* >( parent ), (*it), cut);
+ }
+ }
+ }
+ }
+ return false;
+}
+
+void KKeyChooser::removeStandardShortcut( const QString& name, KKeyChooser* chooser, const KShortcut &origCut, const KShortcut &cut )
+{
+ bool was_in_choosers = false;
+ if( allChoosers != NULL ) {
+ for( QValueList< KKeyChooser* >::ConstIterator it = allChoosers->begin();
+ it != allChoosers->end();
+ ++it ) {
+ if( (*it) != chooser && (*it)->m_type == Standard ) {
+ was_in_choosers |= ( (*it)->removeShortcut( name, cut ));
+ }
+ }
+ }
+ if( !was_in_choosers ) { // not edited, needs to be changed in config file
+ KStdAccel::ShortcutList std_list;
+ KShortcut newCut = origCut;
+ removeFromShortcut(newCut, cut);
+ int index = std_list.index( name );
+ if ( index >= 0 ) {
+ std_list.setShortcut( index, newCut );
+ std_list.save();
+ }
+ }
+}
+
+void KKeyChooser::removeGlobalShortcut( const QString& name, KKeyChooser* chooser, const KShortcut &origCut, const KShortcut &cut )
+{
+ bool was_in_choosers = false;
+ if( allChoosers != NULL ) {
+ for( QValueList< KKeyChooser* >::ConstIterator it = allChoosers->begin();
+ it != allChoosers->end();
+ ++it ) {
+ if( (*it) != chooser && (*it)->m_type == Global ) {
+ was_in_choosers |= ( (*it)->removeShortcut( name, cut ));
+ }
+ }
+ }
+ if( !was_in_choosers ) { // not edited, needs to be changed in config file
+ KAccelActions actions;
+ KShortcut newCut = origCut;
+ removeFromShortcut(newCut, cut);
+ actions.insert( name, "", "", newCut, newCut);
+ actions.writeActions( "Global Shortcuts", 0, true, true );
+ }
+}
+
+bool KKeyChooser::removeShortcut( const QString& name, const KShortcut &cut )
+{
+ for( QListViewItemIterator it( d->pList ); it.current(); ++it ) {
+ KKeyChooserItem* pItem2 = dynamic_cast<KKeyChooserItem*>(it.current());
+ if( pItem2 && pItem2->actionName() == name ) {
+ // remove the shortcut from it
+ KShortcut cut2 = pItem2->shortcut();
+ removeFromShortcut(cut2, cut);
+ pItem2->setShortcut(cut2);
+ updateButtons();
+ emit keyChange();
+ return true;
+ }
+ }
+ return false;
+}
+
+// KDE4 remove this
+void KKeyChooser::_warning( const KKeySequence& cut, QString sAction, QString sTitle )
+{
+ sAction = sAction.stripWhiteSpace();
+
+ QString s =
+ i18n("The '%1' key combination has already been allocated "
+ "to the \"%2\" action.\n"
+ "Please choose a unique key combination.").
+ arg(cut.toString()).arg(sAction);
+
+ KMessageBox::sorry( this, s, sTitle );
+}
+
+bool KKeyChooser::promptForReassign( const KKeySequence& cut, const QString& sAction, ActionType type, QWidget* parent )
+{
+ if(cut.isNull())
+ return true;
+ QString sTitle;
+ QString s;
+ if( type == Standard ) {
+ sTitle = i18n("Conflict with Standard Application Shortcut");
+ s = i18n("The '%1' key combination has already been allocated "
+ "to the standard action \"%2\".\n"
+ "Do you want to reassign it from that action to the current one?");
+ }
+ else if( type == Global ) {
+ sTitle = i18n("Conflict with Global Shortcut");
+ s = i18n("The '%1' key combination has already been allocated "
+ "to the global action \"%2\".\n"
+ "Do you want to reassign it from that action to the current one?");
+ }
+ else {
+ sTitle = i18n("Key Conflict");
+ s = i18n("The '%1' key combination has already been allocated "
+ "to the \"%2\" action.\n"
+ "Do you want to reassign it from that action to the current one?");
+ }
+ s = s.arg(cut.toString()).arg(sAction.stripWhiteSpace());
+
+ return KMessageBox::warningContinueCancel( parent, s, sTitle, i18n("Reassign") ) == KMessageBox::Continue;
+}
+
+//---------------------------------------------------
+KKeyChooserItem::KKeyChooserItem( KListView* parent, QListViewItem* after, KShortcutList* pList, uint iAction )
+: KListViewItem( parent, after )
+{
+ m_pList = pList;
+ m_iAction = iAction;
+ m_bModified = false;
+ m_cut = m_pList->shortcut(m_iAction);
+}
+
+KKeyChooserItem::KKeyChooserItem( QListViewItem* parent, QListViewItem* after, KShortcutList* pList, uint iAction )
+: KListViewItem( parent, after )
+{
+ m_pList = pList;
+ m_iAction = iAction;
+ m_bModified = false;
+ m_cut = m_pList->shortcut(m_iAction);
+}
+
+QString KKeyChooserItem::actionName() const
+{
+ return m_pList->name(m_iAction);
+}
+
+const KShortcut& KKeyChooserItem::shortcut() const
+{
+ return m_cut;
+}
+
+void KKeyChooserItem::setShortcut( const KShortcut& cut )
+{
+ m_cut = cut;
+ m_bModified = (m_cut != m_pList->shortcut(m_iAction));
+ listView()->repaintItem( this );
+}
+
+void KKeyChooserItem::commitChanges()
+{
+ if( m_bModified )
+ m_pList->setShortcut( m_iAction, m_cut );
+}
+
+QString KKeyChooserItem::text( int iCol ) const
+{
+ if( iCol == 0 ) {
+ // Quick HACK to get rid of '&'s.
+ QString s = m_pList->label(m_iAction);
+ QString s2;
+ for( uint i = 0; i < s.length(); i++ )
+ if( s[i] != '&' || ( i+1<s.length() && s[i+1] == '&' ) )
+ s2 += s[i];
+ return s2;
+ }
+ else if( iCol <= (int) m_cut.count() )
+ return m_cut.seq(iCol-1).toString();
+ else
+ return QString::null;
+}
+
+int KKeyChooserItem::compare( QListViewItem* item, int iCol, bool bAscending ) const
+{
+ KKeyChooserItem* pItem = dynamic_cast<KKeyChooserItem*>( item );
+ if( iCol == 0 && pItem ) {
+ QString psName1 = m_pList->name(m_iAction);
+ QString psName2 = pItem->m_pList->name(pItem->m_iAction);
+ QRegExp rxNumber1( " (\\d+)$" );
+ QRegExp rxNumber2( " (\\d+)$" );
+ int iNumber1 = rxNumber1.search( psName1 );
+ int iNumber2 = rxNumber2.search( psName2 );
+
+ // Check if the last word is one or more digits
+ if( iNumber1 >= 0 && iNumber1 == iNumber2 && psName1.startsWith( psName2.left( iNumber1+1 ) ) ) {
+ int n1 = rxNumber1.cap(1).toInt();
+ int n2 = rxNumber2.cap(1).toInt();
+ return (n1 < n2) ? -1 : (n1 > n2) ? 1 : 0;
+ }
+ }
+
+ return QListViewItem::compare( item, iCol, bAscending );
+}
+
+////
+
+QString KKeyChooserWhatsThis::text( const QPoint& p ) {
+ if ( !m_listView )
+ return QString::null;
+
+ const QListViewItem* item = m_listView->itemAt( p );
+ const KKeyChooserItem* pItem = dynamic_cast<const KKeyChooserItem*>(item);
+ if ( !pItem )
+ return QWhatsThis::textFor( m_listView );
+
+ const QString itemWhatsThis = pItem->whatsThis();
+ if ( itemWhatsThis.isEmpty() )
+ return QWhatsThis::textFor( m_listView );
+
+ return itemWhatsThis;
+}
+
+/************************************************************************/
+/* KKeyDialog */
+/* */
+/* Originally by Nicolas Hadacek <hadacek@via.ecp.fr> */
+/* */
+/* Substantially revised by Mark Donohoe <donohoe@kde.org> */
+/* */
+/* And by Espen Sand <espen@kde.org> 1999-10-19 */
+/* (by using KDialogBase there is almost no code left ;) */
+/* */
+/************************************************************************/
+KKeyDialog::KKeyDialog( KKeyChooser::ActionType type, bool bAllowLetterShortcuts, QWidget *parent, const char* name )
+: KDialogBase( parent, name ? name : "kkeydialog", true, i18n("Configure Shortcuts"), Default|Ok|Cancel, Ok )
+{
+ m_pKeyChooser = new KKeyChooser( this, type, bAllowLetterShortcuts );
+ setMainWidget( m_pKeyChooser );
+ connect( this, SIGNAL(defaultClicked()), m_pKeyChooser, SLOT(allDefault()) );
+
+ KConfigGroup group( KGlobal::config(), "KKeyDialog Settings" );
+ QSize sz = size();
+ resize( group.readSizeEntry( "Dialog Size", &sz ) );
+}
+
+KKeyDialog::KKeyDialog( bool bAllowLetterShortcuts, QWidget *parent, const char* name )
+: KDialogBase( parent, name ? name : "kkeydialog", true, i18n("Configure Shortcuts"), Default|Ok|Cancel, Ok )
+{
+ m_pKeyChooser = new KKeyChooser( this, KKeyChooser::Application, bAllowLetterShortcuts );
+ setMainWidget( m_pKeyChooser );
+ connect( this, SIGNAL(defaultClicked()), m_pKeyChooser, SLOT(allDefault()) );
+
+ KConfigGroup group( KGlobal::config(), "KKeyDialog Settings" );
+ QSize sz = size();
+ resize( group.readSizeEntry( "Dialog Size", &sz ) );
+}
+
+KKeyDialog::~KKeyDialog()
+{
+ KConfigGroup group( KGlobal::config(), "KKeyDialog Settings" );
+ group.writeEntry( "Dialog Size", size(), true, true );
+}
+
+bool KKeyDialog::insert( KActionCollection* pColl )
+{
+ return m_pKeyChooser->insert( pColl );
+}
+
+bool KKeyDialog::insert(KActionCollection *pColl, const QString &title)
+{
+ return m_pKeyChooser->insert(pColl, title);
+}
+
+bool KKeyDialog::configure( bool bSaveSettings )
+{
+ int retcode = exec();
+ if( retcode == Accepted ) {
+ if( bSaveSettings )
+ m_pKeyChooser->save();
+ else
+ commitChanges();
+ }
+ return retcode;
+}
+
+void KKeyDialog::commitChanges()
+{
+ m_pKeyChooser->commitChanges();
+}
+
+int KKeyDialog::configure( KActionCollection* coll, QWidget* parent, bool bSaveSettings )
+{
+ return configure( coll, true, parent, bSaveSettings);
+}
+
+int KKeyDialog::configure( KAccel* keys, QWidget* parent, bool bSaveSettings )
+{
+ return configure( keys, true, parent, bSaveSettings);
+}
+
+int KKeyDialog::configure( KGlobalAccel* keys, QWidget* parent, bool bSaveSettings )
+{
+ return configure( keys, true, parent, bSaveSettings);
+}
+
+int KKeyDialog::configure( KAccel* keys, bool bAllowLetterShortcuts, QWidget *parent, bool bSaveSettings )
+{
+ KKeyDialog dlg( bAllowLetterShortcuts, parent );
+ dlg.m_pKeyChooser->insert( keys );
+ bool b = dlg.configure( bSaveSettings );
+ if( b && bSaveSettings )
+ keys->updateConnections();
+ return b;
+}
+
+int KKeyDialog::configure( KGlobalAccel* keys, bool bAllowLetterShortcuts, QWidget *parent, bool bSaveSettings )
+{
+ KKeyDialog dlg( KKeyChooser::ApplicationGlobal, bAllowLetterShortcuts, parent );
+ dlg.m_pKeyChooser->insert( keys );
+ bool b = dlg.configure( bSaveSettings );
+ if( b && bSaveSettings )
+ keys->updateConnections();
+ return b;
+}
+
+int KKeyDialog::configure( KActionCollection* coll, bool bAllowLetterShortcuts, QWidget *parent, bool bSaveSettings )
+{
+ kdDebug(125) << "KKeyDialog::configureKeys( KActionCollection*, " << bSaveSettings << " )" << endl;
+ KKeyDialog dlg( bAllowLetterShortcuts, parent );
+ dlg.m_pKeyChooser->insert( coll );
+ return dlg.configure( bSaveSettings );
+}
+
+/*int KKeyDialog::configure( KActionPtrList* coll, const QString& file, QWidget *parent, bool bSaveSettings )
+{
+ kdDebug(125) << "KKeyDialog::configureKeys( KActionCollection*, " << file << ", " << bSaveSettings << " )" << endl;
+ KAccelActions actions;
+ coll->createKeyMap( actions );
+
+ int retcode = configure( actions, file, parent, bSaveSettings );
+ if( retcode == Accepted )
+ coll->setKeyMap( actions );
+
+ return retcode;
+}*/
+
+void KKeyChooser::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void KKeyDialog::virtual_hook( int id, void* data )
+{ KDialogBase::virtual_hook( id, data ); }
+
+#include "kkeydialog.moc"
diff --git a/kdeui/kkeydialog.h b/kdeui/kkeydialog.h
new file mode 100644
index 000000000..c7bfc36dc
--- /dev/null
+++ b/kdeui/kkeydialog.h
@@ -0,0 +1,407 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Nicolas Hadacek <hadacek@kde.org>
+ Copyright (C) 2001,2001 Ellis Whitehead <ellis@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __KKEYDIALOG_H__
+#define __KKEYDIALOG_H__
+
+#include <qdict.h>
+#include <kdialogbase.h>
+#include <klistview.h>
+
+class QButtonGroup;
+class QCheckBox;
+class QGroupBox;
+class QLabel;
+class QLineEdit;
+class QRadioButton;
+class KAccel;
+class KAccelActions;
+class KActionCollection;
+class KConfigBase;
+class KGlobalAccel;
+class KKeySequence;
+class KShortcut;
+class KShortcutList;
+class KKeyChooserItem;
+
+/**
+ * @short Widget for configuration of KAccel and KGlobalAccel.
+ *
+ * Configure dictionaries of key/action associations for KAccel and
+ * KGlobalAccel.
+ *
+ * The class takes care of all aspects of configuration, including
+ * handling key conflicts internally. Connect to the allDefault()
+ * slot if you want to set all configurable shortcuts to their
+ * default values.
+ *
+ * @see KKeyDialog
+ * @author Nicolas Hadacek <hadacek@via.ecp.fr>
+ */
+class KDEUI_EXPORT KKeyChooser : public QWidget
+{
+ Q_OBJECT
+ public:
+ enum ActionType { Application, ApplicationGlobal, Standard, Global };
+
+ /**
+ * Constructor.
+ *
+ * @param parent the parent widget for this widget
+ * @param type the ActionType for this KKeyChooser
+ * @param bAllowLetterShortcuts Set to false if unmodified alphanumeric
+ * keys ('A', '1', etc.) are not permissible shortcuts.
+ **/
+ KKeyChooser( QWidget* parent, ActionType type = Application, bool bAllowLetterShortcuts = true );
+ /**
+ * \overload
+ * @param parent parent widget
+ * @param coll the KActionCollection to configure
+ * @param bAllowLetterShortcuts Set to false if unmodified alphanumeric
+ * keys ('A', '1', etc.) are not permissible shortcuts.
+ */
+ KKeyChooser( KActionCollection* coll, QWidget* parent, bool bAllowLetterShortcuts = true );
+
+ KKeyChooser( KAccel* actions, QWidget* parent, bool bAllowLetterShortcuts = true );
+ KKeyChooser( KGlobalAccel* actions, QWidget* parent );
+ KKeyChooser( KShortcutList*, QWidget* parent, ActionType type = Application, bool bAllowLetterShortcuts = true );
+
+ virtual ~KKeyChooser();
+
+ /**
+ * Insert an action collection, i.e. add all its actions to the ones
+ * already associated with the KKeyChooser object.
+ */
+ bool insert( KActionCollection* ); // #### KDE4 : remove me
+ /**
+ * Insert an action collection, i.e. add all its actions to the ones
+ * already associated with the KKeyChooser object.
+ * @param title subtree title of this collection of shortcut.
+ * @since 3.1
+ */
+ bool insert( KActionCollection *, const QString &title);
+
+ void syncToConfig( const QString& sConfigGroup, KConfigBase* pConfig, bool bClearUnset );
+
+ /**
+ * This function writes any shortcut changes back to the original
+ * action set(s).
+ */
+ void commitChanges();
+
+ /**
+ * This commits and then saves the actions to disk.
+ * Any KActionCollection objects with the xmlFile() value set
+ * will be written to an XML file. All other will be written
+ * to the application's rc file.
+ */
+ void save();
+
+ /**
+ * Checks whether the given shortcut conflicts with global keyboard shortcuts.
+ * If yes, and the warnUser argument is true, warns the user and gives them a chance
+ * to reassign the shortcut from the global shortcut.
+ *
+ * @return true if there was conflict (and the user didn't reassign the shortcut)
+ * @param cut the shortcut that will be checked for conflicts
+ * @param warnUser if true, the user will be warned about a conflict and given a chance
+ * to reassign the shortcut
+ * @param parent parent widget for the warning dialog
+ *
+ * @since 3.2
+ */
+ static bool checkGlobalShortcutsConflict( const KShortcut& cut, bool warnUser, QWidget* parent );
+
+ /**
+ * Checks whether the given shortcut conflicts with standard keyboard shortcuts.
+ * If yes, and the warnUser argument is true, warns the user and gives them a chance
+ * to reassign the shortcut from the standard shortcut.
+ *
+ * @return true if there was conflict (and the user didn't reassign the shortcut)
+ * @param cut the shortcut that will be checked for conflicts
+ * @param warnUser if true, the user will be warned about a conflict and given a chance
+ * to reassign the shortcut
+ * @param parent parent widget for the warning dialog
+ *
+ * @since 3.2
+ */
+ static bool checkStandardShortcutsConflict( const KShortcut& cut, bool warnUser, QWidget* parent );
+
+ signals:
+ /**
+ * Emitted when an action's shortcut has been changed.
+ **/
+ void keyChange();
+
+ public slots:
+ /**
+ * Set all keys to their default values (bindings).
+ **/
+ void allDefault();
+
+ /**
+ * Specifies whether to use the 3 or 4 modifier key scheme.
+ * This determines which default is used when the 'Default' button is
+ * clicked.
+ */
+ void setPreferFourModifierKeys( bool preferFourModifierKeys );
+
+ // KDE4 a lot of stuff in this class should be probably private:
+ protected:
+ enum { NoKey = 1, DefaultKey, CustomKey };
+
+ void initGUI( ActionType type, bool bAllowLetterShortcuts );
+ bool insert( KAccel* );
+ bool insert( KGlobalAccel* );
+ bool insert( KShortcutList* );
+ /// @since 3.1
+ void buildListView( uint iList, const QString &title = QString::null );
+
+ void readGlobalKeys();
+
+ void updateButtons();
+ void fontChange( const QFont& _font );
+ void setShortcut( const KShortcut& cut );
+ bool isKeyPresent( const KShortcut& cut, bool warnuser = true );
+ bool isKeyPresentLocally( const KShortcut& cut, KKeyChooserItem* ignoreItem, const QString& warnText );
+ void _warning( const KKeySequence& seq, QString sAction, QString sTitle );
+
+ protected slots:
+ void slotNoKey();
+ void slotDefaultKey();
+ void slotCustomKey();
+ void slotListItemSelected( QListViewItem *item );
+ void capturedShortcut( const KShortcut& cut );
+ void slotSettingsChanged( int );
+ void slotListItemDoubleClicked ( QListViewItem * ipoQListViewItem, const QPoint & ipoQPoint, int c );
+
+ protected:
+ ActionType m_type;
+ bool m_bAllowLetterShortcuts;
+ bool m_bAllowWinKey; // unused KDE4 remove
+ // When set, pressing the 'Default' button will select the aDefaultKeycode4,
+ // otherwise aDefaultKeycode.
+ bool m_bPreferFourModifierKeys;
+
+ QRadioButton* m_prbNone;
+ QRadioButton* m_prbDef;
+ QRadioButton* m_prbCustom;
+
+ private:
+ bool isKeyPresentLocally( const KShortcut& cut, KKeyChooserItem* ignoreItem, bool bWarnUser );
+ static bool promptForReassign( const KKeySequence& cut, const QString& sAction, ActionType action, QWidget* parent );
+ // Remove the key sequences contained in cut from the standard shortcut @p name
+ // which currently has @p origCut as shortcut.
+ static void removeStandardShortcut( const QString& name, KKeyChooser* chooser, const KShortcut &origCut, const KShortcut &cut );
+ // Remove the key sequences contained in cut from the global shortcut @p name
+ // which currently has @p origCut as shortcut.
+ static void removeGlobalShortcut( const QString& name, KKeyChooser* chooser, const KShortcut &origCut, const KShortcut &cut );
+ static void readGlobalKeys( QMap< QString, KShortcut >& map );
+ static bool checkGlobalShortcutsConflict( const KShortcut& cut, bool bWarnUser, QWidget* parent,
+ const QMap< QString, KShortcut >& map, const QString& ignoreAction );
+ // Remove the key sequences contained in cut from this item
+ bool removeShortcut( const QString& name, const KShortcut &cut );
+
+private slots:
+ void captureCurrentItem();
+
+#ifndef KDE_NO_COMPAT
+ public:
+ /**
+ * @obsolete
+ */
+ KKeyChooser( KAccel* actions, QWidget* parent,
+ bool bCheckAgainstStdKeys,
+ bool bAllowLetterShortcuts,
+ bool bAllowWinKey = false );
+ /**
+ * @obsolete
+ */
+ KKeyChooser( KGlobalAccel* actions, QWidget* parent,
+ bool bCheckAgainstStdKeys,
+ bool bAllowLetterShortcuts,
+ bool bAllowWinKey = false );
+
+ public slots:
+ /**
+ * Rebuild list entries based on underlying map.
+ * Use this if you changed the underlying map.
+ */
+ void listSync();
+
+#endif
+ protected:
+ virtual void virtual_hook( int id, void* data );
+ private:
+ class KKeyChooserPrivate *d;
+ friend class KKeyDialog;
+};
+typedef KKeyChooser KKeyChooser;
+
+/**
+ * @short Dialog for configuration of KActionCollection, KAccel, and KGlobalAccel.
+ *
+ * The KKeyDialog class is used for configuring dictionaries of key/action
+ * associations for KActionCollection, KAccel, and KGlobalAccel. It uses the KKeyChooser widget
+ * and offers buttons to set all keys to defaults and invoke on-line help.
+ *
+ * Several static methods are supplied which provide the most convenient interface
+ * to the dialog. The most common and most encouraged use is with KActionCollection.
+ *
+ * \code
+ * KKeyDialog::configure( actionCollection() );
+ * \endcode
+ *
+ * @author Nicolas Hadacek <hadacek@via.ecp.fr>
+ */
+class KDEUI_EXPORT KKeyDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Constructs a KKeyDialog called @p name as a child of @p parent.
+ * Set @p bAllowLetterShortcuts to false if unmodified alphanumeric
+ * keys ('A', '1', etc.) are not permissible shortcuts.
+ */
+ KKeyDialog( bool bAllowLetterShortcuts = true, QWidget* parent = 0, const char* name = 0 );
+
+ /**
+ * Destructor. Deletes all resources used by a KKeyDialog object.
+ */
+ virtual ~KKeyDialog();
+
+ /**
+ * Insert an action collection, i.e. add all its actions to the ones
+ * displayed by the dialog.
+ * This method can be useful in applications following the document/view
+ * design, with actions in both the document and the view.
+ * Simply call insert with the action collections of each one in turn.
+ * @return true :)
+ */
+ bool insert( KActionCollection* ); // #### KDE4: remove me
+
+ /**
+ * Insert an action collection, i.e. add all its actions to the ones
+ * displayed by the dialog.
+ * This method can be useful in applications following the document/view
+ * design, with actions in both the document and the view.
+ * Simply call insert with the action collections of each one in turn.
+ *
+ * @param title the title associated with the collection (if null, the
+ * KAboutData::progName() of the collection's instance is used)
+ * @return true :)
+ * @since 3.1
+ */
+ bool insert(KActionCollection *, const QString &title);
+
+ /**
+ * Run the dialog and call commitChanges() if @p bSaveSettings
+ * is true.
+ */
+ bool configure( bool bSaveSettings = true );
+
+ /**
+ * Commit key setting changes so that changed settings actually become active.
+ * This method is implicitly called from configure(bool) if
+ * @p bSaveSettings is true.
+ */
+ void commitChanges();
+
+ /**
+ * Pops up a modal dialog for configuring key settings. The new
+ * shortcut settings will be active if the user presses OK. If
+ * @p bSaveSettings if true, the settings will also be saved back to
+ * the *uirc file which they were intially read from.
+ * @return Accept if the dialog was closed with OK, Reject otherwise.
+ */
+ static int configure( KActionCollection* coll, QWidget* parent = 0, bool bSaveSettings = true );
+
+ /**
+ * This is an overloaded member function, provided for convenience.
+ * It behaves essentially like the above function, except that settings
+ * are saved to a *.rc file using KConfig.
+ */
+ static int configure( KAccel* keys, QWidget* parent = 0, bool bSaveSettings = true );
+
+ /**
+ * This is an overloaded member function, provided for convenience.
+ * It behaves essentially like the above function.
+ */
+ static int configure( KGlobalAccel* keys, QWidget* parent = 0, bool bSaveSettings = true );
+
+
+ /**
+ * This is an overloaded member function, provided for convenience.
+ * It behaves essentially like the above function.
+ *
+ * @param coll the KActionCollection to configure
+ * @param bAllowLetterShortcuts Set to false if unmodified alphanumeric
+ * keys ('A', '1', etc.) are not permissible shortcuts.
+ * @param parent the parent widget to attach to
+ * @param bSaveSettings if true, the settings will also be saved back to
+ * the *uirc file which they were intially read from.
+ */
+ static int configure( KActionCollection* coll, bool bAllowLetterShortcuts, QWidget* parent = 0, bool bSaveSettings = true ); // BCI: merge with bAllowLetterShortcuts = true
+
+ /**
+ * This is an overloaded member function, provided for convenience.
+ * It behaves essentially like the above function.
+ **/
+ static int configure( KAccel* keys, bool bAllowLetterShortcuts, QWidget* parent = 0, bool bSaveSettings = true ); // BCI: merge with bAllowLetterShortcuts = true
+
+ /**
+ * This is an overloaded member function, provided for convenience.
+ * It behaves essentially like the above function.
+ **/
+ static int configure( KGlobalAccel* keys, bool bAllowLetterShortcuts, QWidget* parent = 0, bool bSaveSettings = true ); // BCI: merge with bAllowLetterShortcuts = true
+
+ /**
+ * @deprecated Obsolete.
+ * Please use KKeyDialog::configure instead
+ */
+ static KDE_DEPRECATED int configureKeys( KAccel* keys, bool save_settings = true, QWidget* parent = 0 )
+ { return configure( keys, parent, save_settings ); }
+ /**
+ * @deprecated Obsolete.
+ * Please use KKeyDialog::configure instead
+ */
+ static KDE_DEPRECATED int configureKeys( KGlobalAccel* keys, bool save_settings = true, QWidget* parent = 0 )
+ { return configure( keys, parent, save_settings ); }
+ /**
+ * @deprecated Obsolete.
+ * Please use KKeyDialog::configure instead
+ */
+ static KDE_DEPRECATED int configureKeys( KActionCollection* coll, const QString& /*xmlfile*/,
+ bool save_settings = true, QWidget* parent = 0 )
+ { return configure( coll, parent, save_settings ); }
+
+private:
+ KKeyDialog( KKeyChooser::ActionType, bool bAllowLetterShortcuts = true, QWidget* parent = 0, const char* name = 0 );
+
+ protected:
+ virtual void virtual_hook( int id, void* data );
+
+ private:
+ class KKeyDialogPrivate* d;
+ KKeyChooser* m_pKeyChooser;
+};
+
+#endif // __KKEYDIALOG_H__
diff --git a/kdeui/klanguagebutton.cpp b/kdeui/klanguagebutton.cpp
new file mode 100644
index 000000000..ed70b5ea0
--- /dev/null
+++ b/kdeui/klanguagebutton.cpp
@@ -0,0 +1,284 @@
+/*
+ * klanguagebutton.cpp - Adds some methods for inserting languages.
+ *
+ * Copyright (c) 1999-2003 Hans Petter Bieker <bieker@kde.org>
+ *
+ * Requires the Qt widget libraries, available at no cost at
+ * http://www.trolltech.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#define INCLUDE_MENUITEM_DEF
+#include <qpopupmenu.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+
+#include "klanguagebutton.h"
+#include "klanguagebutton.moc"
+
+#include <kdebug.h>
+
+static void checkInsertPos( QPopupMenu *popup, const QString & str,
+ int &index )
+{
+ if ( index == -1 )
+ return;
+
+ int a = 0;
+ int b = popup->count();
+ while ( a < b )
+ {
+ int w = ( a + b ) / 2;
+
+ int id = popup->idAt( w );
+ int j = str.localeAwareCompare( popup->text( id ) );
+
+ if ( j > 0 )
+ a = w + 1;
+ else
+ b = w;
+ }
+
+ index = a; // it doesn't really matter ... a == b here.
+
+ Q_ASSERT( a == b );
+}
+
+static QPopupMenu * checkInsertIndex( QPopupMenu *popup,
+ const QStringList *tags, const QString &submenu )
+{
+ int pos = tags->findIndex( submenu );
+
+ QPopupMenu *pi = 0;
+ if ( pos != -1 )
+ {
+ QMenuItem *p = popup->findItem( pos );
+ pi = p ? p->popup() : 0;
+ }
+ if ( !pi )
+ pi = popup;
+
+ return pi;
+}
+
+class KLanguageButtonPrivate
+{
+public:
+ QPushButton * button;
+ bool staticText;
+};
+
+KLanguageButton::KLanguageButton( QWidget * parent, const char *name )
+ : QWidget( parent, name )
+{
+ init(name);
+}
+
+KLanguageButton::KLanguageButton( const QString & text, QWidget * parent, const char *name )
+ : QWidget( parent, name )
+{
+ init(name);
+
+ setText(text);
+}
+
+void KLanguageButton::setText(const QString & text)
+{
+ d->staticText = true;
+ d->button->setText(text);
+ d->button->setIconSet(QIconSet()); // remove the icon
+}
+
+void KLanguageButton::init(const char * name)
+{
+ m_current = 0;
+ m_ids = new QStringList;
+ m_popup = 0;
+ m_oldPopup = 0;
+ d = new KLanguageButtonPrivate;
+
+ d->staticText = false;
+
+ QHBoxLayout *layout = new QHBoxLayout(this, 0, 0);
+ layout->setAutoAdd(true);
+ d->button = new QPushButton( this, name ); // HPB don't touch this!!
+
+ clear();
+}
+
+KLanguageButton::~KLanguageButton()
+{
+ delete m_ids;
+
+ delete d->button;
+ delete d;
+}
+
+
+void KLanguageButton::insertLanguage( const QString& path, const QString& name,
+ const QString&, const QString &submenu, int index )
+{
+ QString output = name + QString::fromLatin1( " (" ) + path +
+ QString::fromLatin1( ")" );
+#if 0
+ // Nooooo ! Country != language
+ QPixmap flag( locate( "locale", sub + path +
+ QString::fromLatin1( "/flag.png" ) ) );
+#endif
+ insertItem( output, path, submenu, index );
+}
+
+void KLanguageButton::insertItem( const QIconSet& icon, const QString &text,
+ const QString & id, const QString &submenu, int index )
+{
+ QPopupMenu *pi = checkInsertIndex( m_popup, m_ids, submenu );
+ checkInsertPos( pi, text, index );
+ pi->insertItem( icon, text, count(), index );
+ m_ids->append( id );
+}
+
+void KLanguageButton::insertItem( const QString &text, const QString & id,
+ const QString &submenu, int index )
+{
+ insertItem( QIconSet(), text, id, submenu, index );
+}
+
+void KLanguageButton::insertSeparator( const QString &submenu, int index )
+{
+ QPopupMenu *pi = checkInsertIndex( m_popup, m_ids, submenu );
+ pi->insertSeparator( index );
+ m_ids->append( QString::null );
+}
+
+void KLanguageButton::insertSubmenu( const QIconSet & icon,
+ const QString &text, const QString &id,
+ const QString &submenu, int index )
+{
+ QPopupMenu *pi = checkInsertIndex( m_popup, m_ids, submenu );
+ QPopupMenu *p = new QPopupMenu( pi );
+ checkInsertPos( pi, text, index );
+ pi->insertItem( icon, text, p, count(), index );
+ m_ids->append( id );
+ connect( p, SIGNAL( activated( int ) ),
+ SLOT( slotActivated( int ) ) );
+ connect( p, SIGNAL( highlighted( int ) ), this,
+ SLOT( slotHighlighted( int ) ) );
+}
+
+void KLanguageButton::insertSubmenu( const QString &text, const QString &id,
+ const QString &submenu, int index )
+{
+ insertSubmenu(QIconSet(), text, id, submenu, index);
+}
+
+void KLanguageButton::slotActivated( int index )
+{
+ //kdDebug() << "slotActivated" << index << endl;
+
+ setCurrentItem( index );
+
+ // Forward event from popup menu as if it was emitted from this widget:
+ QString id = *m_ids->at( index );
+ emit activated( id );
+}
+
+void KLanguageButton::slotHighlighted( int index )
+{
+ //kdDebug() << "slotHighlighted" << index << endl;
+
+ QString id = *m_ids->at( index );
+ emit ( highlighted(id) );
+}
+
+int KLanguageButton::count() const
+{
+ return m_ids->count();
+}
+
+void KLanguageButton::clear()
+{
+ m_ids->clear();
+
+ delete m_oldPopup;
+ m_oldPopup = m_popup;
+ m_popup = new QPopupMenu( this );
+
+ d->button->setPopup( m_popup );
+
+ connect( m_popup, SIGNAL( activated( int ) ),
+ SLOT( slotActivated( int ) ) );
+ connect( m_popup, SIGNAL( highlighted( int ) ),
+ SLOT( slotHighlighted( int ) ) );
+
+ if ( !d->staticText )
+ {
+ d->button->setText( QString::null );
+ d->button->setIconSet( QIconSet() );
+ }
+}
+
+bool KLanguageButton::contains( const QString & id ) const
+{
+ return m_ids->contains( id ) > 0;
+}
+
+QString KLanguageButton::current() const
+{
+ return *m_ids->at( currentItem() );
+}
+
+
+QString KLanguageButton::id( int i ) const
+{
+ if ( i < 0 || i >= count() )
+ {
+ kdDebug() << "KLanguageButton::tag(), unknown tag " << i << endl;
+ return QString::null;
+ }
+ return *m_ids->at( i );
+}
+
+
+int KLanguageButton::currentItem() const
+{
+ return m_current;
+}
+
+void KLanguageButton::setCurrentItem( int i )
+{
+ if ( i < 0 || i >= count() )
+ return;
+ m_current = i;
+
+ if ( !d->staticText )
+ {
+ d->button->setText( m_popup->text( m_current ) );
+ QIconSet *icon = m_popup->iconSet( m_current );
+ if ( icon )
+ d->button->setIconSet( *icon );
+ else
+ d->button->setIconSet( QIconSet() );
+ }
+}
+
+void KLanguageButton::setCurrentItem( const QString & id )
+{
+ int i = m_ids->findIndex( id );
+ if ( id.isNull() )
+ i = 0;
+ if ( i != -1 )
+ setCurrentItem( i );
+}
diff --git a/kdeui/klanguagebutton.h b/kdeui/klanguagebutton.h
new file mode 100644
index 000000000..d354b4b77
--- /dev/null
+++ b/kdeui/klanguagebutton.h
@@ -0,0 +1,182 @@
+/*
+ * klangbutton.h - Button with language selection drop down menu.
+ * Derived from the KLangCombo class by Hans Petter Bieker.
+ *
+ * Copyright (c) 1999-2003 Hans Petter Bieker <bieker@kde.org>
+ * (c) 2001 Martijn Klingens <klingens@kde.org>
+ *
+ * Requires the Qt widget libraries, available at no cost at
+ * http://www.troll.no/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef __KLANGBUTTON_H__
+#define __KLANGBUTTON_H__
+
+#include <qwidget.h>
+
+#include <kdelibs_export.h>
+
+class KLanguageButtonPrivate;
+class QIconSet;
+class QPopupMenu;
+
+/**
+ * KLanguageButton provides a combobox with a 2-D dataset. It also supports icons.
+ * It is also possible to construct a non combobox version.
+ *
+ * All items are identified using strings, not integers.
+ *
+ * Combined version of KTagCombo and KLanguageCombo but using a QPushButton
+ * instead.
+ */
+class KDEUI_EXPORT KLanguageButton : public QWidget
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Constructs a combobox widget with parent parent called name.
+ *
+ * @param parent The parent of the combo box
+ * @param name The name of the combo box
+ */
+ KLanguageButton(QWidget * parent = 0, const char * name = 0);
+
+ /**
+ * Constructs a version with static text. The parent parent is called name.
+ *
+ * @param text The text of the button
+ * @param parent The parent of the button
+ * @param name The name of the button
+ */
+ KLanguageButton(const QString & text, QWidget * parent = 0, const char * name = 0);
+
+ /**
+ * Deconstructor
+ */
+ virtual ~KLanguageButton();
+
+ /**
+ * Inserts an item into the combo box. A negative index will append the item.
+ *
+ * @param icon The icon used used when displaying the item.
+ * @param text The text string used when displaying the item.
+ * @param id The text string used to identify the item.
+ * @param submenu The place where the item should be placed.
+ * @param index The visual position in the submenu.
+ */
+ void insertItem( const QIconSet& icon, const QString &text,
+ const QString & id, const QString &submenu = QString::null,
+ int index = -1 );
+ /**
+ * Inserts an item into the combo box. A negative index will append the item.
+ *
+ * @param text The text string used when displaying the item.
+ * @param id The text string used to identify the item.
+ * @param submenu The place where the item should be placed.
+ * @param index The visual position in the submenu.
+ */
+ void insertItem( const QString &text, const QString & id,
+ const QString &submenu = QString::null, int index = -1 );
+ /**
+ * Inserts a seperator item into the combo box. A negative index will append the item.
+ *
+ * @param submenu The place where the item should be placed.
+ * @param index The visual position in the submenu.
+ */
+ void insertSeparator( const QString &submenu = QString::null,
+ int index = -1 );
+ /**
+ * Inserts a submenu into the combo box. A negative index will append the item.
+ *
+ * @param icon The icon used used when displaying the item.
+ * @param text The text string used when displaying the item.
+ * @param id The text string used to identify the item.
+ * @param submenu The place where the item should be placed.
+ * @param index The visual position in the submenu.
+ */
+ void insertSubmenu( const QIconSet & icon, const QString &text,
+ const QString & id, const QString &submenu = QString::null,
+ int index = -1);
+ /**
+ * Inserts a submenu into the combo box. A negative index will append the item.
+ *
+ * @param text The text string used when displaying the item.
+ * @param id The text string used to identify the item.
+ * @param submenu The place where the item should be placed.
+ * @param index The visual position in the submenu.
+ */
+ void insertSubmenu( const QString &text, const QString & id,
+ const QString &submenu = QString::null, int index = -1);
+
+
+ void insertLanguage( const QString& path, const QString& name,
+ const QString& sub = QString::null,
+ const QString &submenu = QString::null, int index = -1);
+
+
+ int count() const;
+ /**
+ * Removes all combobox items.
+ */
+ void clear();
+ /**
+ * Changes the current text item of the combobox, and makes the text static.
+ */
+ void setText(const QString & text);
+ /**
+ * Returns the id of the combobox's current item.
+ */
+ QString current() const;
+ /**
+ * Returns TRUE if the combobox contains id.
+ */
+ bool contains( const QString & id ) const;
+ /**
+ * Sets id as current item.
+ */
+ void setCurrentItem( const QString & id );
+
+ QString id( int i ) const;
+
+signals:
+ /**
+ * This signal is emitted when a new item is activated. The id is
+ * the identificator of the selected item.
+ */
+ void activated( const QString & id );
+ void highlighted( const QString & id );
+
+private slots:
+ void slotActivated( int );
+ void slotHighlighted( int );
+
+private:
+ int currentItem() const;
+ void setCurrentItem( int );
+ void init(const char * name);
+
+ // work space for the new class
+ QStringList *m_ids;
+ QPopupMenu *m_popup, *m_oldPopup;
+ int m_current;
+
+ KLanguageButtonPrivate * d;
+};
+
+#endif
diff --git a/kdeui/kled.cpp b/kdeui/kled.cpp
new file mode 100644
index 000000000..6a8d7c5e0
--- /dev/null
+++ b/kdeui/kled.cpp
@@ -0,0 +1,644 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1998 Jörg Habenicht (j.habenicht@europemail.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#define PAINT_BENCH
+#undef PAINT_BENCH
+
+#ifdef PAINT_BENCH
+#include <qdatetime.h>
+#include <stdio.h>
+#endif
+
+
+#include <qpainter.h>
+#include <qimage.h>
+#include <qcolor.h>
+#include <kapplication.h>
+#include <kpixmapeffect.h>
+#include "kled.h"
+
+
+class KLed::KLedPrivate
+{
+ friend class KLed;
+
+ int dark_factor;
+ QColor offcolor;
+ QPixmap *off_map;
+ QPixmap *on_map;
+};
+
+
+
+KLed::KLed(QWidget *parent, const char *name)
+ : QWidget( parent, name),
+ led_state(On),
+ led_look(Raised),
+ led_shape(Circular)
+{
+ QColor col(green);
+ d = new KLed::KLedPrivate;
+ d->dark_factor = 300;
+ d->offcolor = col.dark(300);
+ d->off_map = 0;
+ d->on_map = 0;
+
+ setColor(col);
+}
+
+
+KLed::KLed(const QColor& col, QWidget *parent, const char *name)
+ : QWidget( parent, name),
+ led_state(On),
+ led_look(Raised),
+ led_shape(Circular)
+{
+ d = new KLed::KLedPrivate;
+ d->dark_factor = 300;
+ d->offcolor = col.dark(300);
+ d->off_map = 0;
+ d->on_map = 0;
+
+ setColor(col);
+ //setShape(Circular);
+}
+
+KLed::KLed(const QColor& col, KLed::State state,
+ KLed::Look look, KLed::Shape shape, QWidget *parent, const char *name )
+ : QWidget(parent, name),
+ led_state(state),
+ led_look(look),
+ led_shape(shape)
+{
+ d = new KLed::KLedPrivate;
+ d->dark_factor = 300;
+ d->offcolor = col.dark(300);
+ d->off_map = 0;
+ d->on_map = 0;
+
+ //setShape(shape);
+ setColor(col);
+}
+
+
+KLed::~KLed()
+{
+ delete d->off_map;
+ delete d->on_map;
+ delete d;
+}
+
+void
+KLed::paintEvent(QPaintEvent *)
+{
+#ifdef PAINT_BENCH
+ const int rounds = 1000;
+ QTime t;
+ t.start();
+ for (int i=0; i<rounds; i++) {
+#endif
+ switch(led_shape)
+ {
+ case Rectangular:
+ switch (led_look)
+ {
+ case Sunken :
+ paintRectFrame(false);
+ break;
+ case Raised :
+ paintRectFrame(true);
+ break;
+ case Flat :
+ paintRect();
+ break;
+ default :
+ qWarning("%s: in class KLed: no KLed::Look set",qApp->argv()[0]);
+ }
+ break;
+ case Circular:
+ switch (led_look)
+ {
+ case Flat :
+ paintFlat();
+ break;
+ case Raised :
+ paintRound();
+ break;
+ case Sunken :
+ paintSunken();
+ break;
+ default:
+ qWarning("%s: in class KLed: no KLed::Look set",qApp->argv()[0]);
+ }
+ break;
+ default:
+ qWarning("%s: in class KLed: no KLed::Shape set",qApp->argv()[0]);
+ break;
+ }
+#ifdef PAINT_BENCH
+ }
+ int ready = t.elapsed();
+ qWarning("elapsed: %d msec. for %d rounds", ready, rounds);
+#endif
+}
+
+int
+KLed::ensureRoundLed()
+{
+ // Initialize coordinates, width, and height of the LED
+ //
+ int width = this->width();
+ // Make sure the LED is round!
+ if (width > this->height())
+ width = this->height();
+ width -= 2; // leave one pixel border
+ if (width < 0)
+ width = 0;
+
+ return width;
+}
+
+bool
+KLed::paintCachedPixmap()
+{
+ if (led_state) {
+ if (d->on_map) {
+ QPainter paint(this);
+ paint.drawPixmap(0, 0, *d->on_map);
+ return true;
+ }
+ } else {
+ if (d->off_map) {
+ QPainter paint(this);
+ paint.drawPixmap(0, 0, *d->off_map);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void
+KLed::paintFlat() // paint a ROUND FLAT led lamp
+{
+ if (paintCachedPixmap()) return;
+
+ QPainter paint;
+ QColor color;
+ QBrush brush;
+ QPen pen;
+
+ int width = ensureRoundLed();
+
+
+ int scale = 3;
+ QPixmap *tmpMap = 0;
+
+ width *= scale;
+
+ tmpMap = new QPixmap(width + 6, width + 6);
+ tmpMap->fill(paletteBackgroundColor());
+
+ // start painting widget
+ //
+ paint.begin(tmpMap);
+
+ // Set the color of the LED according to given parameters
+ color = ( led_state ) ? led_color : d->offcolor;
+
+ // Set the brush to SolidPattern, this fills the entire area
+ // of the ellipse which is drawn with a thin gray "border" (pen)
+ brush.setStyle( QBrush::SolidPattern );
+ brush.setColor( color );
+
+ pen.setWidth( scale );
+ color = colorGroup().dark();
+ pen.setColor( color ); // Set the pen accordingly
+
+ paint.setPen( pen ); // Select pen for drawing
+ paint.setBrush( brush ); // Assign the brush to the painter
+
+ // Draws a "flat" LED with the given color:
+ paint.drawEllipse( scale, scale, width - scale * 2, width - scale * 2 );
+
+ paint.end();
+ //
+ // painting done
+ QPixmap *&dest = led_state ? d->on_map : d->off_map;
+ QImage i = tmpMap->convertToImage();
+ width /= 3;
+ i = i.smoothScale(width, width);
+ delete tmpMap;
+ dest = new QPixmap(i);
+ paint.begin(this);
+ paint.drawPixmap(0, 0, *dest);
+ paint.end();
+
+}
+
+void
+KLed::paintRound() // paint a ROUND RAISED led lamp
+{
+ if (paintCachedPixmap()) return;
+
+ QPainter paint;
+ QColor color;
+ QBrush brush;
+ QPen pen;
+
+ // Initialize coordinates, width, and height of the LED
+ int width = ensureRoundLed();
+
+ int scale = 3;
+ QPixmap *tmpMap = 0;
+
+ width *= scale;
+
+ tmpMap = new QPixmap(width + 6, width + 6);
+ tmpMap->fill(paletteBackgroundColor());
+ paint.begin(tmpMap);
+
+ // Set the color of the LED according to given parameters
+ color = ( led_state ) ? led_color : d->offcolor;
+
+ // Set the brush to SolidPattern, this fills the entire area
+ // of the ellipse which is drawn first
+ brush.setStyle( QBrush::SolidPattern );
+ brush.setColor( color );
+ paint.setBrush( brush ); // Assign the brush to the painter
+
+ // Draws a "flat" LED with the given color:
+ paint.drawEllipse( scale, scale, width - scale*2, width - scale*2 );
+
+ // Draw the bright light spot of the LED now, using modified "old"
+ // painter routine taken from KDEUI´s KLed widget:
+
+ // Setting the new width of the pen is essential to avoid "pixelized"
+ // shadow like it can be observed with the old LED code
+ pen.setWidth( 2 * scale );
+
+ // shrink the light on the LED to a size about 2/3 of the complete LED
+ int pos = width/5 + 1;
+ int light_width = width;
+ light_width *= 2;
+ light_width /= 3;
+
+ // Calculate the LED´s "light factor":
+ int light_quote = (130*2/(light_width?light_width:1))+100;
+
+ // Now draw the bright spot on the LED:
+ while (light_width) {
+ color = color.light( light_quote ); // make color lighter
+ pen.setColor( color ); // set color as pen color
+ paint.setPen( pen ); // select the pen for drawing
+ paint.drawEllipse( pos, pos, light_width, light_width ); // draw the ellipse (circle)
+ light_width--;
+ if (!light_width)
+ break;
+ paint.drawEllipse( pos, pos, light_width, light_width );
+ light_width--;
+ if (!light_width)
+ break;
+ paint.drawEllipse( pos, pos, light_width, light_width );
+ pos++; light_width--;
+ }
+
+ // Drawing of bright spot finished, now draw a thin gray border
+ // around the LED; it looks nicer that way. We do this here to
+ // avoid that the border can be erased by the bright spot of the LED
+
+ pen.setWidth( 2 * scale + 1 );
+ color = colorGroup().dark();
+ pen.setColor( color ); // Set the pen accordingly
+ paint.setPen( pen ); // Select pen for drawing
+ brush.setStyle( QBrush::NoBrush ); // Switch off the brush
+ paint.setBrush( brush ); // This avoids filling of the ellipse
+
+ paint.drawEllipse( 2, 2, width, width );
+
+ paint.end();
+ //
+ // painting done
+ QPixmap *&dest = led_state ? d->on_map : d->off_map;
+ QImage i = tmpMap->convertToImage();
+ width /= 3;
+ i = i.smoothScale(width, width);
+ delete tmpMap;
+ dest = new QPixmap(i);
+ paint.begin(this);
+ paint.drawPixmap(0, 0, *dest);
+ paint.end();
+
+}
+
+void
+KLed::paintSunken() // paint a ROUND SUNKEN led lamp
+{
+ if (paintCachedPixmap()) return;
+
+ QPainter paint;
+ QColor color;
+ QBrush brush;
+ QPen pen;
+
+ // First of all we want to know what area should be updated
+ // Initialize coordinates, width, and height of the LED
+ int width = ensureRoundLed();
+
+ int scale = 3;
+ QPixmap *tmpMap = 0;
+
+ width *= scale;
+
+ tmpMap = new QPixmap(width, width);
+ tmpMap->fill(paletteBackgroundColor());
+ paint.begin(tmpMap);
+
+ // Set the color of the LED according to given parameters
+ color = ( led_state ) ? led_color : d->offcolor;
+
+ // Set the brush to SolidPattern, this fills the entire area
+ // of the ellipse which is drawn first
+ brush.setStyle( QBrush::SolidPattern );
+ brush.setColor( color );
+ paint.setBrush( brush ); // Assign the brush to the painter
+
+ // Draws a "flat" LED with the given color:
+ paint.drawEllipse( scale, scale, width - scale*2, width - scale*2 );
+
+ // Draw the bright light spot of the LED now, using modified "old"
+ // painter routine taken from KDEUI´s KLed widget:
+
+ // Setting the new width of the pen is essential to avoid "pixelized"
+ // shadow like it can be observed with the old LED code
+ pen.setWidth( 2 * scale );
+
+ // shrink the light on the LED to a size about 2/3 of the complete LED
+ int pos = width/5 + 1;
+ int light_width = width;
+ light_width *= 2;
+ light_width /= 3;
+
+ // Calculate the LED´s "light factor":
+ int light_quote = (130*2/(light_width?light_width:1))+100;
+
+ // Now draw the bright spot on the LED:
+ while (light_width) {
+ color = color.light( light_quote ); // make color lighter
+ pen.setColor( color ); // set color as pen color
+ paint.setPen( pen ); // select the pen for drawing
+ paint.drawEllipse( pos, pos, light_width, light_width ); // draw the ellipse (circle)
+ light_width--;
+ if (!light_width)
+ break;
+ paint.drawEllipse( pos, pos, light_width, light_width );
+ light_width--;
+ if (!light_width)
+ break;
+ paint.drawEllipse( pos, pos, light_width, light_width );
+ pos++; light_width--;
+ }
+
+ // Drawing of bright spot finished, now draw a thin border
+ // around the LED which resembles a shadow with light coming
+ // from the upper left.
+
+ pen.setWidth( 2 * scale + 1 ); // ### shouldn't this value be smaller for smaller LEDs?
+ brush.setStyle( QBrush::NoBrush ); // Switch off the brush
+ paint.setBrush( brush ); // This avoids filling of the ellipse
+
+ // Set the initial color value to colorGroup().light() (bright) and start
+ // drawing the shadow border at 45° (45*16 = 720).
+
+ int angle = -720;
+ color = colorGroup().light();
+
+ for ( int arc = 120; arc < 2880; arc += 240 ) {
+ pen.setColor( color );
+ paint.setPen( pen );
+ int w = width - pen.width()/2 - scale + 1;
+ paint.drawArc( pen.width()/2, pen.width()/2, w, w, angle + arc, 240 );
+ paint.drawArc( pen.width()/2, pen.width()/2, w, w, angle - arc, 240 );
+ color = color.dark( 110 ); //FIXME: this should somehow use the contrast value
+ } // end for ( angle = 720; angle < 6480; angle += 160 )
+
+ paint.end();
+ //
+ // painting done
+
+ QPixmap *&dest = led_state ? d->on_map : d->off_map;
+ QImage i = tmpMap->convertToImage();
+ width /= 3;
+ i = i.smoothScale(width, width);
+ delete tmpMap;
+ dest = new QPixmap(i);
+ paint.begin(this);
+ paint.drawPixmap(0, 0, *dest);
+ paint.end();
+
+}
+
+void
+KLed::paintRect()
+{
+ QPainter painter(this);
+ QBrush lightBrush(led_color);
+ QBrush darkBrush(d->offcolor);
+ QPen pen(led_color.dark(300));
+ int w=width();
+ int h=height();
+ // -----
+ switch(led_state)
+ {
+ case On:
+ painter.setBrush(lightBrush);
+ painter.drawRect(0, 0, w, h);
+ break;
+ case Off:
+ painter.setBrush(darkBrush);
+ painter.drawRect(0, 0, w, h);
+ painter.setPen(pen);
+ painter.drawLine(0, 0, w, 0);
+ painter.drawLine(0, h-1, w, h-1);
+ // Draw verticals
+ int i;
+ for(i=0; i < w; i+= 4 /* dx */)
+ painter.drawLine(i, 1, i, h-1);
+ break;
+ default: break;
+ }
+}
+
+void
+KLed::paintRectFrame(bool raised)
+{
+ QPainter painter(this);
+ QBrush lightBrush(led_color);
+ QBrush darkBrush(d->offcolor);
+ int w=width();
+ int h=height();
+ QColor black=Qt::black;
+ QColor white=Qt::white;
+ // -----
+ if(raised)
+ {
+ painter.setPen(white);
+ painter.drawLine(0, 0, 0, h-1);
+ painter.drawLine(1, 0, w-1, 0);
+ painter.setPen(black);
+ painter.drawLine(1, h-1, w-1, h-1);
+ painter.drawLine(w-1, 1, w-1, h-1);
+ painter.fillRect(1, 1, w-2, h-2,
+ (led_state==On)? lightBrush : darkBrush);
+ } else {
+ painter.setPen(black);
+ painter.drawRect(0,0,w,h);
+ painter.drawRect(0,0,w-1,h-1);
+ painter.setPen(white);
+ painter.drawRect(1,1,w-1,h-1);
+ painter.fillRect(2, 2, w-4, h-4,
+ (led_state==On)? lightBrush : darkBrush);
+ }
+}
+
+KLed::State
+KLed::state() const
+{
+ return led_state;
+}
+
+KLed::Shape
+KLed::shape() const
+{
+ return led_shape;
+}
+
+QColor
+KLed::color() const
+{
+ return led_color;
+}
+
+KLed::Look
+KLed::look() const
+{
+ return led_look;
+}
+
+void
+KLed::setState( State state )
+{
+ if (led_state != state)
+ {
+ led_state = state;
+ update();
+ }
+}
+
+void
+KLed::toggleState()
+{
+ toggle();
+}
+
+void
+KLed::setShape(KLed::Shape s)
+{
+ if(led_shape!=s)
+ {
+ led_shape = s;
+ update();
+ }
+}
+
+void
+KLed::setColor(const QColor& col)
+{
+ if(led_color!=col) {
+ if(d->on_map) { delete d->on_map; d->on_map = 0; }
+ if(d->off_map) { delete d->off_map; d->off_map = 0; }
+ led_color = col;
+ d->offcolor = col.dark(d->dark_factor);
+ update();
+ }
+}
+
+void
+KLed::setDarkFactor(int darkfactor)
+{
+ if (d->dark_factor != darkfactor) {
+ d->dark_factor = darkfactor;
+ d->offcolor = led_color.dark(darkfactor);
+ update();
+ }
+}
+
+int
+KLed::darkFactor() const
+{
+ return d->dark_factor;
+}
+
+void
+KLed::setLook( Look look )
+{
+ if(led_look!=look)
+ {
+ led_look = look;
+ update();
+ }
+}
+
+void
+KLed::toggle()
+{
+ led_state = (led_state == On) ? Off : On;
+ // setColor(led_color);
+ update();
+}
+
+void
+KLed::on()
+{
+ setState(On);
+}
+
+void
+KLed::off()
+{
+ setState(Off);
+}
+
+QSize
+KLed::sizeHint() const
+{
+ return QSize(16, 16);
+}
+
+QSize
+KLed::minimumSizeHint() const
+{
+ return QSize(16, 16 );
+}
+
+void KLed::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "kled.moc"
diff --git a/kdeui/kled.h b/kdeui/kled.h
new file mode 100644
index 000000000..3e417feb9
--- /dev/null
+++ b/kdeui/kled.h
@@ -0,0 +1,329 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1998 Jörg Habenicht (j.habenicht@europemail.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+/*************************************************************************
+ * $Id$
+ *************************************************************************/
+
+#ifndef _KLED_H_
+#define _KLED_H_
+
+#include <qwidget.h>
+#include <kdelibs_export.h>
+
+class QColor;
+/**
+ * @short An LED widget.
+ *
+ * Displays a round or rectangular light emitting diode.
+ *
+ * It is configurable to five colors, the two on/off states and three
+ * styles (or "looks");
+ *
+ * It may display itself in a performant flat view, a round view with
+ * light spot or a round view sunken in the screen.
+ *
+ * \image html kled.png "KDE LED Widget"
+ *
+ * @author Joerg Habenicht, Richard J. Moore (rich@kde.org) 1998, 1999
+ */
+class KDEUI_EXPORT KLed : public QWidget
+{
+ Q_OBJECT
+ Q_ENUMS( State Shape Look )
+ Q_PROPERTY( State state READ state WRITE setState )
+ Q_PROPERTY( Shape shape READ shape WRITE setShape )
+ Q_PROPERTY( Look look READ look WRITE setLook )
+ Q_PROPERTY( QColor color READ color WRITE setColor )
+ Q_PROPERTY( int darkFactor READ darkFactor WRITE setDarkFactor )
+
+public:
+
+ /**
+ * Status of the light is on/off.
+ * @short LED on/off.
+ */
+ enum State { Off, On };
+
+ /**
+ * Shades of the lamp.
+ * @short LED shape
+ */
+ enum Shape { Rectangular, Circular };
+
+ /**
+ * Displays a flat, round or sunken LED.
+ *
+ * Displaying the LED flat is less time and color consuming,
+ * but not so nice to see.
+ *
+ * The sunken LED itself is (certainly) smaller than the round LED
+ * because of the 3 shading circles and is
+ * most time consuming. Makes sense for LED > 15x15 pixels.
+ *
+ * \b Timings: \n
+ * ( AMD K5/133, Diamond Stealth 64 PCI Graphics, widgetsize 29x29 )
+ * @li flat Approximately 0.7 msec per paint
+ * @li round Approximately 2.9 msec per paint
+ * @li sunken Approximately 3.3 msec per paint
+ *
+ * The widget will be updated on the next repaining event.
+ *
+ * @short LED look.
+ */
+ enum Look { Flat, Raised, Sunken };
+
+ /**
+ * Constructs a green, round LED widget which will initially
+ * be turned on.
+ */
+ KLed(QWidget *parent=0, const char *name=0);
+ /**
+ * Constructor with the ledcolor, the parent widget, and the name.
+ *
+ * The State will be defaulted On and the Look round.
+ *
+ * @param col Initial color of the LED.
+ * @param parent Will be handed over to QWidget.
+ * @param name Will be handed over to QWidget.
+ * @short Constructor
+ */
+ KLed(const QColor &col, QWidget *parent=0, const char *name=0);
+
+ /**
+ * Constructor with the ledcolor, ledstate, ledlook,
+ * the parent widget, and the name.
+ *
+ * Differs from above only in the parameters, which configure all settings.
+ *
+ * @param col Initial color of the LED.
+ * @param state Sets the State.
+ * @param look Sets the Look.
+ * @param shape Sets the Shape (rectangular or circular)
+ * @param parent Will be handed over to QWidget.
+ * @param name Will be handed over to QWidget.
+ * @short Constructor
+ */
+ KLed(const QColor& col, KLed::State state, KLed::Look look, KLed::Shape shape,
+ QWidget *parent=0, const char *name=0);
+
+
+ /**
+ * Destructor
+ * @short Destructor
+ */
+ ~KLed();
+
+ /**
+ * Returns the current state of the widget (on/off).
+ *
+ * @see State
+ * @short Returns LED state.
+ */
+ State state() const;
+
+ Shape shape() const;
+
+ /**
+ * Returns the color of the widget
+ *
+ * @see Color
+ * @short Returns LED color.
+ */
+ QColor color() const;
+
+ /**
+ * Returns the look of the widget.
+ *
+ * @see Look
+ * @short Returns LED look.
+ */
+ Look look() const;
+
+ /**
+ * Returns the factor to darken the LED.
+ *
+ * @see setDarkFactor()
+ * @short Returns dark factor
+ */
+ int darkFactor() const;
+
+ /**
+ * Sets the state of the widget to On or Off.
+ *
+ * The widget will be painted immediately.
+ * @see on() off() toggle() toggleState()
+ *
+ * @param state The LED state: on or off.
+ * @short Set LED state.
+ */
+ void setState( State state );
+
+ /**
+ * Set the shape of the LED to @p s.
+ */
+ void setShape(Shape s);
+ /**
+ * Toggle the state of the LED from Off to On and vice versa.
+ *
+ * The widget will be repainted when returning to the main
+ * event loop.
+ * @short Toggles LED on->off / off->on.
+ * @deprecated, use #toggle() instead.
+ */
+ void toggleState() KDE_DEPRECATED;
+
+ /**
+ * Set the color of the widget.
+ * The Color is shown with the KLed::On state.
+ * The KLed::Off state is shown with QColor.dark() method
+ *
+ * The widget calls the update() method, so it will
+ * be updated when entering the main event loop.
+ *
+ * @see Color
+ *
+ * @param color New color of the LED.
+ * @short Sets the LED color.
+ */
+ void setColor(const QColor& color);
+
+ /**
+ * Sets the factor to darken the LED in OFF state.
+ * Same as QColor::dark().
+ * "darkfactor should be greater than 100, else the LED gets lighter
+ * in OFF state.
+ * Defaults to 300.
+ *
+ * @see QColor
+ *
+ * @param darkfactor sets the factor to darken the LED.
+ * @short sets the factor to darken the LED.
+ */
+ void setDarkFactor(int darkfactor);
+
+ /**
+ * Sets the color of the widget.
+ * The Color is shown with the KLed::On state.
+ * darkcolor is explicidly used for the off state of the LED.
+ * Normally you don't have to use this method, the setColor(const QColor& color) is sufficient for the task.
+ *
+ * The widget calls the update() method, so it will
+ * be updated when entering the main event loop.
+ *
+ * @see Color setColor()
+ *
+ * @param color New color of the LED used for on state.
+ * @param darkcolor Dark color of the LED used for off state.
+ * @short Sets the light and dark LED color.
+ *
+ void setColor(const QColor& color, const QColor& darkcolor);
+ */
+
+ /**
+ * Sets the look of the widget.
+ *
+ * The look may be flat, round or sunken.
+ * The widget calls the update() method, so it will
+ * be updated when entering the main event loop.
+ *
+ * @see Look
+ *
+ * @param look New look of the LED.
+ * @short Sets LED look.
+ */
+ void setLook( Look look );
+
+ virtual QSize sizeHint() const;
+ virtual QSize minimumSizeHint() const;
+
+public slots:
+
+ /**
+ * Toggles the state of the led from Off to On or vice versa.
+ *
+ * The widget repaints itself immediately.
+ */
+ void toggle();
+
+ /**
+ * Sets the state of the widget to On.
+ *
+ * The widget will be painted immediately.
+ * @see off() toggle() toggleState() setState()
+ */
+ void on();
+
+ /**
+ * Sets the state of the widget to Off.
+ *
+ * The widget will be painted immediately.
+ * @see on() toggle() toggleState() setState()
+ */
+ void off();
+
+protected:
+ /**
+ * Paints a circular, flat LED.
+ */
+ virtual void paintFlat();
+ /**
+ * Paints a circular, raised LED.
+ */
+ virtual void paintRound();
+ /**
+ * Paints a circular, sunken LED.
+ */
+ virtual void paintSunken();
+ /**
+ * Paints a rectangular, flat LED.
+ */
+ virtual void paintRect();
+ /**
+ * Paints a rectangular LED, either raised or
+ * sunken, depending on its argument.
+ */
+ virtual void paintRectFrame(bool raised);
+
+ void paintEvent( QPaintEvent * );
+
+ /**
+ * Compute LED width
+ */
+ int ensureRoundLed();
+
+ /**
+ * Paint the cached antialiased pixmap corresponding to the state if any
+ * @return true if the pixmap was painted, false if it hasn't been created yet
+ */
+ bool paintCachedPixmap();
+
+private:
+ State led_state;
+ QColor led_color;
+ Look led_look;
+ Shape led_shape;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KLedPrivate;
+ KLedPrivate *d;
+};
+
+#endif
diff --git a/kdeui/klineedit.cpp b/kdeui/klineedit.cpp
new file mode 100644
index 000000000..309bd4283
--- /dev/null
+++ b/kdeui/klineedit.cpp
@@ -0,0 +1,1382 @@
+/* This file is part of the KDE libraries
+
+ Copyright (C) 1997 Sven Radej (sven.radej@iname.com)
+ Copyright (c) 1999 Patrick Ward <PAT_WARD@HP-USA-om5.om.hp.com>
+ Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+
+ Re-designed for KDE 2.x by
+ Copyright (c) 2000, 2001 Dawit Alemayehu <adawit@kde.org>
+ Copyright (c) 2000, 2001 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License (LGPL) as published by the Free Software Foundation;
+ either version 2 of the License, or (at your option) any later
+ version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qclipboard.h>
+#include <qpainter.h>
+#include <qtimer.h>
+
+#include <kconfig.h>
+#include <qtooltip.h>
+#include <kcursor.h>
+#include <klocale.h>
+#include <kstdaccel.h>
+#include <kpopupmenu.h>
+#include <kdebug.h>
+#include <kcompletionbox.h>
+#include <kurl.h>
+#include <kurldrag.h>
+#include <kiconloader.h>
+#include <kapplication.h>
+
+#include "klineedit.h"
+#include "klineedit.moc"
+
+
+class KLineEdit::KLineEditPrivate
+{
+public:
+ KLineEditPrivate()
+ {
+ completionBox = 0L;
+ handleURLDrops = true;
+ grabReturnKeyEvents = false;
+
+ userSelection = true;
+ autoSuggest = false;
+ disableRestoreSelection = false;
+ enableSqueezedText = false;
+
+ if ( !initialized )
+ {
+ KConfigGroup config( KGlobal::config(), "General" );
+ backspacePerformsCompletion = config.readBoolEntry( "Backspace performs completion", false );
+
+ initialized = true;
+ }
+
+ }
+
+ ~KLineEditPrivate()
+ {
+// causes a weird crash in KWord at least, so let Qt delete it for us.
+// delete completionBox;
+ }
+
+ static bool initialized;
+ static bool backspacePerformsCompletion; // Configuration option
+
+ QColor previousHighlightColor;
+ QColor previousHighlightedTextColor;
+
+ bool userSelection: 1;
+ bool autoSuggest : 1;
+ bool disableRestoreSelection: 1;
+ bool handleURLDrops:1;
+ bool grabReturnKeyEvents:1;
+ bool enableSqueezedText:1;
+
+ int squeezedEnd;
+ int squeezedStart;
+ BackgroundMode bgMode;
+ QString squeezedText;
+ KCompletionBox *completionBox;
+
+ QString clickMessage;
+ bool drawClickMsg:1;
+};
+
+bool KLineEdit::KLineEditPrivate::backspacePerformsCompletion = false;
+bool KLineEdit::KLineEditPrivate::initialized = false;
+
+
+KLineEdit::KLineEdit( const QString &string, QWidget *parent, const char *name )
+ :QLineEdit( string, parent, name )
+{
+ init();
+}
+
+KLineEdit::KLineEdit( QWidget *parent, const char *name )
+ :QLineEdit( parent, name )
+{
+ init();
+}
+
+KLineEdit::~KLineEdit ()
+{
+ delete d;
+ d = 0;
+}
+
+void KLineEdit::init()
+{
+ d = new KLineEditPrivate;
+ possibleTripleClick = false;
+ d->bgMode = backgroundMode ();
+
+ // Enable the context menu by default.
+ KLineEdit::setContextMenuEnabled( true );
+ KCursor::setAutoHideCursor( this, true, true );
+ installEventFilter( this );
+
+ KGlobalSettings::Completion mode = completionMode();
+ d->autoSuggest = (mode == KGlobalSettings::CompletionMan ||
+ mode == KGlobalSettings::CompletionPopupAuto ||
+ mode == KGlobalSettings::CompletionAuto);
+ connect( this, SIGNAL(selectionChanged()), this, SLOT(slotRestoreSelectionColors()));
+
+ QPalette p = palette();
+ if ( !d->previousHighlightedTextColor.isValid() )
+ d->previousHighlightedTextColor=p.color(QPalette::Normal,QColorGroup::HighlightedText);
+ if ( !d->previousHighlightColor.isValid() )
+ d->previousHighlightColor=p.color(QPalette::Normal,QColorGroup::Highlight);
+
+ d->drawClickMsg = false;
+}
+
+void KLineEdit::setCompletionMode( KGlobalSettings::Completion mode )
+{
+ KGlobalSettings::Completion oldMode = completionMode();
+
+ if ( oldMode != mode && (oldMode == KGlobalSettings::CompletionPopup ||
+ oldMode == KGlobalSettings::CompletionPopupAuto ) &&
+ d->completionBox && d->completionBox->isVisible() )
+ d->completionBox->hide();
+
+ // If the widgets echo mode is not Normal, no completion
+ // feature will be enabled even if one is requested.
+ if ( echoMode() != QLineEdit::Normal )
+ mode = KGlobalSettings::CompletionNone; // Override the request.
+
+ if ( kapp && !kapp->authorize("lineedit_text_completion") )
+ mode = KGlobalSettings::CompletionNone;
+
+ if ( mode == KGlobalSettings::CompletionPopupAuto ||
+ mode == KGlobalSettings::CompletionAuto ||
+ mode == KGlobalSettings::CompletionMan )
+ d->autoSuggest = true;
+ else
+ d->autoSuggest = false;
+
+ KCompletionBase::setCompletionMode( mode );
+}
+
+void KLineEdit::setCompletedText( const QString& t, bool marked )
+{
+ if ( !d->autoSuggest )
+ return;
+
+ QString txt = text();
+
+ if ( t != txt )
+ {
+ int start = marked ? txt.length() : t.length();
+ validateAndSet( t, cursorPosition(), start, t.length() );
+ setUserSelection(false);
+ }
+ else
+ setUserSelection(true);
+
+}
+
+void KLineEdit::setCompletedText( const QString& text )
+{
+ KGlobalSettings::Completion mode = completionMode();
+ bool marked = ( mode == KGlobalSettings::CompletionAuto ||
+ mode == KGlobalSettings::CompletionMan ||
+ mode == KGlobalSettings::CompletionPopup ||
+ mode == KGlobalSettings::CompletionPopupAuto );
+ setCompletedText( text, marked );
+}
+
+void KLineEdit::rotateText( KCompletionBase::KeyBindingType type )
+{
+ KCompletion* comp = compObj();
+ if ( comp &&
+ (type == KCompletionBase::PrevCompletionMatch ||
+ type == KCompletionBase::NextCompletionMatch ) )
+ {
+ QString input;
+
+ if (type == KCompletionBase::PrevCompletionMatch)
+ comp->previousMatch();
+ else
+ comp->nextMatch();
+
+ // Skip rotation if previous/next match is null or the same text
+ if ( input.isNull() || input == displayText() )
+ return;
+ setCompletedText( input, hasSelectedText() );
+ }
+}
+
+void KLineEdit::makeCompletion( const QString& text )
+{
+ KCompletion *comp = compObj();
+ KGlobalSettings::Completion mode = completionMode();
+
+ if ( !comp || mode == KGlobalSettings::CompletionNone )
+ return; // No completion object...
+
+ QString match = comp->makeCompletion( text );
+
+ if ( mode == KGlobalSettings::CompletionPopup ||
+ mode == KGlobalSettings::CompletionPopupAuto )
+ {
+ if ( match.isNull() )
+ {
+ if ( d->completionBox )
+ {
+ d->completionBox->hide();
+ d->completionBox->clear();
+ }
+ }
+ else
+ setCompletedItems( comp->allMatches() );
+ }
+ else // Auto, ShortAuto (Man) and Shell
+ {
+ // all other completion modes
+ // If no match or the same match, simply return without completing.
+ if ( match.isNull() || match == text )
+ return;
+
+ if ( mode != KGlobalSettings::CompletionShell )
+ setUserSelection(false);
+
+ if ( d->autoSuggest )
+ setCompletedText( match );
+ }
+}
+
+void KLineEdit::setReadOnly(bool readOnly)
+{
+ // Do not do anything if nothing changed...
+ if (readOnly == isReadOnly ())
+ return;
+
+ QLineEdit::setReadOnly (readOnly);
+
+ if (readOnly)
+ {
+ d->bgMode = backgroundMode ();
+ setBackgroundMode (Qt::PaletteBackground);
+ if (d->enableSqueezedText && d->squeezedText.isEmpty())
+ {
+ d->squeezedText = text();
+ setSqueezedText();
+ }
+ }
+ else
+ {
+ if (!d->squeezedText.isEmpty())
+ {
+ setText(d->squeezedText);
+ d->squeezedText = QString::null;
+ }
+ setBackgroundMode (d->bgMode);
+ }
+}
+
+void KLineEdit::setSqueezedText( const QString &text)
+{
+ setEnableSqueezedText(true);
+ setText(text);
+}
+
+void KLineEdit::setEnableSqueezedText( bool enable )
+{
+ d->enableSqueezedText = enable;
+}
+
+bool KLineEdit::isSqueezedTextEnabled() const
+{
+ return d->enableSqueezedText;
+}
+
+void KLineEdit::setText( const QString& text )
+{
+ d->drawClickMsg = text.isEmpty() && !d->clickMessage.isEmpty();
+ update();
+
+ if( d->enableSqueezedText && isReadOnly() )
+ {
+ d->squeezedText = text;
+ setSqueezedText();
+ return;
+ }
+
+ QLineEdit::setText( text );
+}
+
+void KLineEdit::setSqueezedText()
+{
+ d->squeezedStart = 0;
+ d->squeezedEnd = 0;
+ QString fullText = d->squeezedText;
+ QFontMetrics fm(fontMetrics());
+ int labelWidth = size().width() - 2*frameWidth() - 2;
+ int textWidth = fm.width(fullText);
+
+ if (textWidth > labelWidth)
+ {
+ // start with the dots only
+ QString squeezedText = "...";
+ int squeezedWidth = fm.width(squeezedText);
+
+ // estimate how many letters we can add to the dots on both sides
+ int letters = fullText.length() * (labelWidth - squeezedWidth) / textWidth / 2;
+ squeezedText = fullText.left(letters) + "..." + fullText.right(letters);
+ squeezedWidth = fm.width(squeezedText);
+
+ if (squeezedWidth < labelWidth)
+ {
+ // we estimated too short
+ // add letters while text < label
+ do
+ {
+ letters++;
+ squeezedText = fullText.left(letters) + "..." + fullText.right(letters);
+ squeezedWidth = fm.width(squeezedText);
+ } while (squeezedWidth < labelWidth);
+ letters--;
+ squeezedText = fullText.left(letters) + "..." + fullText.right(letters);
+ }
+ else if (squeezedWidth > labelWidth)
+ {
+ // we estimated too long
+ // remove letters while text > label
+ do
+ {
+ letters--;
+ squeezedText = fullText.left(letters) + "..." + fullText.right(letters);
+ squeezedWidth = fm.width(squeezedText);
+ } while (squeezedWidth > labelWidth);
+ }
+
+ if (letters < 5)
+ {
+ // too few letters added -> we give up squeezing
+ QLineEdit::setText(fullText);
+ }
+ else
+ {
+ QLineEdit::setText(squeezedText);
+ d->squeezedStart = letters;
+ d->squeezedEnd = fullText.length() - letters;
+ }
+
+ QToolTip::remove( this );
+ QToolTip::add( this, fullText );
+
+ }
+ else
+ {
+ QLineEdit::setText(fullText);
+
+ QToolTip::remove( this );
+ QToolTip::hide();
+ }
+
+ setCursorPosition(0);
+}
+
+void KLineEdit::copy() const
+{
+ if( !copySqueezedText(true))
+ QLineEdit::copy();
+}
+
+bool KLineEdit::copySqueezedText(bool clipboard) const
+{
+ if (!d->squeezedText.isEmpty() && d->squeezedStart)
+ {
+ int start, end;
+ KLineEdit *that = const_cast<KLineEdit *>(this);
+ if (!that->getSelection(&start, &end))
+ return false;
+ if (start >= d->squeezedStart+3)
+ start = start - 3 - d->squeezedStart + d->squeezedEnd;
+ else if (start > d->squeezedStart)
+ start = d->squeezedStart;
+ if (end >= d->squeezedStart+3)
+ end = end - 3 - d->squeezedStart + d->squeezedEnd;
+ else if (end > d->squeezedStart)
+ end = d->squeezedEnd;
+ if (start == end)
+ return false;
+ QString t = d->squeezedText;
+ t = t.mid(start, end - start);
+ disconnect( QApplication::clipboard(), SIGNAL(selectionChanged()), this, 0);
+ QApplication::clipboard()->setText( t, clipboard ? QClipboard::Clipboard : QClipboard::Selection );
+ connect( QApplication::clipboard(), SIGNAL(selectionChanged()), this,
+ SLOT(clipboardChanged()) );
+ return true;
+ }
+ return false;
+}
+
+void KLineEdit::resizeEvent( QResizeEvent * ev )
+{
+ if (!d->squeezedText.isEmpty())
+ setSqueezedText();
+
+ QLineEdit::resizeEvent(ev);
+}
+
+void KLineEdit::keyPressEvent( QKeyEvent *e )
+{
+ KKey key( e );
+
+ if ( KStdAccel::copy().contains( key ) )
+ {
+ copy();
+ return;
+ }
+ else if ( KStdAccel::paste().contains( key ) )
+ {
+ paste();
+ return;
+ }
+ else if ( KStdAccel::pasteSelection().contains( key ) )
+ {
+ QString text = QApplication::clipboard()->text( QClipboard::Selection);
+ insert( text );
+ deselect();
+ return;
+ }
+
+ else if ( KStdAccel::cut().contains( key ) )
+ {
+ cut();
+ return;
+ }
+ else if ( KStdAccel::undo().contains( key ) )
+ {
+ undo();
+ return;
+ }
+ else if ( KStdAccel::redo().contains( key ) )
+ {
+ redo();
+ return;
+ }
+ else if ( KStdAccel::deleteWordBack().contains( key ) )
+ {
+ cursorWordBackward(true);
+ if ( hasSelectedText() )
+ del();
+
+ e->accept();
+ return;
+ }
+ else if ( KStdAccel::deleteWordForward().contains( key ) )
+ {
+ // Workaround for QT bug where
+ cursorWordForward(true);
+ if ( hasSelectedText() )
+ del();
+
+ e->accept();
+ return;
+ }
+ else if ( KStdAccel::backwardWord().contains( key ) )
+ {
+ cursorWordBackward(false);
+ e->accept();
+ return;
+ }
+ else if ( KStdAccel::forwardWord().contains( key ) )
+ {
+ cursorWordForward(false);
+ e->accept();
+ return;
+ }
+ else if ( KStdAccel::beginningOfLine().contains( key ) )
+ {
+ home(false);
+ e->accept();
+ return;
+ }
+ else if ( KStdAccel::endOfLine().contains( key ) )
+ {
+ end(false);
+ e->accept();
+ return;
+ }
+
+
+ // Filter key-events if EchoMode is normal and
+ // completion mode is not set to CompletionNone
+ if ( echoMode() == QLineEdit::Normal &&
+ completionMode() != KGlobalSettings::CompletionNone )
+ {
+ KeyBindingMap keys = getKeyBindings();
+ KGlobalSettings::Completion mode = completionMode();
+ bool noModifier = (e->state() == NoButton ||
+ e->state() == ShiftButton ||
+ e->state() == Keypad);
+
+ if ( (mode == KGlobalSettings::CompletionAuto ||
+ mode == KGlobalSettings::CompletionPopupAuto ||
+ mode == KGlobalSettings::CompletionMan) && noModifier )
+ {
+ if ( !d->userSelection && hasSelectedText() &&
+ ( e->key() == Key_Right || e->key() == Key_Left ) &&
+ e->state()==NoButton )
+ {
+ QString old_txt = text();
+ d->disableRestoreSelection = true;
+ int start,end;
+ getSelection(&start, &end);
+
+ deselect();
+ QLineEdit::keyPressEvent ( e );
+ int cPosition=cursorPosition();
+ if (e->key() ==Key_Right && cPosition > start )
+ validateAndSet(old_txt, cPosition, cPosition, old_txt.length());
+ else
+ validateAndSet(old_txt, cPosition, start, old_txt.length());
+
+ d->disableRestoreSelection = false;
+ return;
+ }
+
+ if ( e->key() == Key_Escape )
+ {
+ if (hasSelectedText() && !d->userSelection )
+ {
+ del();
+ setUserSelection(true);
+ }
+
+ // Don't swallow the Escape press event for the case
+ // of dialogs, which have Escape associated to Cancel
+ e->ignore();
+ return;
+ }
+
+ }
+
+ if ( (mode == KGlobalSettings::CompletionAuto ||
+ mode == KGlobalSettings::CompletionMan) && noModifier )
+ {
+ QString keycode = e->text();
+ if ( !keycode.isEmpty() && (keycode.unicode()->isPrint() ||
+ e->key() == Key_Backspace || e->key() == Key_Delete ) )
+ {
+ bool hasUserSelection=d->userSelection;
+ bool hadSelection=hasSelectedText();
+
+ bool cursorNotAtEnd=false;
+
+ int start,end;
+ getSelection(&start, &end);
+ int cPos = cursorPosition();
+
+ // When moving the cursor, we want to keep the autocompletion as an
+ // autocompletion, so we want to process events at the cursor position
+ // as if there was no selection. After processing the key event, we
+ // can set the new autocompletion again.
+ if ( hadSelection && !hasUserSelection && start>cPos )
+ {
+ del();
+ setCursorPosition(cPos);
+ cursorNotAtEnd=true;
+ }
+
+ d->disableRestoreSelection = true;
+ QLineEdit::keyPressEvent ( e );
+ d->disableRestoreSelection = false;
+
+ QString txt = text();
+ int len = txt.length();
+ if ( !hasSelectedText() && len /*&& cursorPosition() == len */)
+ {
+ if ( e->key() == Key_Backspace )
+ {
+ if ( hadSelection && !hasUserSelection && !cursorNotAtEnd )
+ {
+ backspace();
+ txt = text();
+ len = txt.length();
+ }
+
+ if ( !d->backspacePerformsCompletion || !len )
+ d->autoSuggest = false;
+ }
+
+ if (e->key() == Key_Delete )
+ d->autoSuggest=false;
+
+ if ( emitSignals() )
+ emit completion( txt );
+
+ if ( handleSignals() )
+ makeCompletion( txt );
+
+ if( (e->key() == Key_Backspace || e->key() == Key_Delete) )
+ d->autoSuggest=true;
+
+ e->accept();
+ }
+
+ return;
+ }
+
+ }
+
+ else if (( mode == KGlobalSettings::CompletionPopup ||
+ mode == KGlobalSettings::CompletionPopupAuto ) &&
+ noModifier && !e->text().isEmpty() )
+ {
+ QString old_txt = text();
+ bool hasUserSelection=d->userSelection;
+ bool hadSelection=hasSelectedText();
+ bool cursorNotAtEnd=false;
+
+ int start,end;
+ getSelection(&start, &end);
+ int cPos = cursorPosition();
+ QString keycode = e->text();
+
+ // When moving the cursor, we want to keep the autocompletion as an
+ // autocompletion, so we want to process events at the cursor position
+ // as if there was no selection. After processing the key event, we
+ // can set the new autocompletion again.
+ if (hadSelection && !hasUserSelection && start>cPos &&
+ ( (!keycode.isEmpty() && keycode.unicode()->isPrint()) ||
+ e->key() == Key_Backspace || e->key() == Key_Delete ) )
+ {
+ del();
+ setCursorPosition(cPos);
+ cursorNotAtEnd=true;
+ }
+
+ uint selectedLength=selectedText().length();
+
+ d->disableRestoreSelection = true;
+ QLineEdit::keyPressEvent ( e );
+ d->disableRestoreSelection = false;
+
+ if (( selectedLength != selectedText().length() ) && !hasUserSelection )
+ slotRestoreSelectionColors(); // and set userSelection to true
+
+ QString txt = text();
+ int len = txt.length();
+
+ if ( txt != old_txt && len/* && ( cursorPosition() == len || force )*/ &&
+ ( (!keycode.isEmpty() && keycode.unicode()->isPrint()) ||
+ e->key() == Key_Backspace || e->key() == Key_Delete) )
+ {
+ if ( e->key() == Key_Backspace )
+ {
+ if ( hadSelection && !hasUserSelection && !cursorNotAtEnd )
+ {
+ backspace();
+ txt = text();
+ len = txt.length();
+ }
+
+ if ( !d->backspacePerformsCompletion )
+ d->autoSuggest = false;
+ }
+
+ if (e->key() == Key_Delete )
+ d->autoSuggest=false;
+
+ if ( d->completionBox )
+ d->completionBox->setCancelledText( txt );
+
+ if ( emitSignals() )
+ emit completion( txt ); // emit when requested...
+
+ if ( handleSignals() ) {
+ makeCompletion( txt ); // handle when requested...
+ }
+
+ if ( (e->key() == Key_Backspace || e->key() == Key_Delete ) &&
+ mode == KGlobalSettings::CompletionPopupAuto )
+ d->autoSuggest=true;
+
+ e->accept();
+ }
+ else if (!len && d->completionBox && d->completionBox->isVisible())
+ d->completionBox->hide();
+
+ return;
+ }
+
+ else if ( mode == KGlobalSettings::CompletionShell )
+ {
+ // Handles completion.
+ KShortcut cut;
+ if ( keys[TextCompletion].isNull() )
+ cut = KStdAccel::shortcut(KStdAccel::TextCompletion);
+ else
+ cut = keys[TextCompletion];
+
+ if ( cut.contains( key ) )
+ {
+ // Emit completion if the completion mode is CompletionShell
+ // and the cursor is at the end of the string.
+ QString txt = text();
+ int len = txt.length();
+ if ( cursorPosition() == len && len != 0 )
+ {
+ if ( emitSignals() )
+ emit completion( txt );
+ if ( handleSignals() )
+ makeCompletion( txt );
+ return;
+ }
+ }
+ else if ( d->completionBox )
+ d->completionBox->hide();
+ }
+
+ // handle rotation
+ if ( mode != KGlobalSettings::CompletionNone )
+ {
+ // Handles previous match
+ KShortcut cut;
+ if ( keys[PrevCompletionMatch].isNull() )
+ cut = KStdAccel::shortcut(KStdAccel::PrevCompletion);
+ else
+ cut = keys[PrevCompletionMatch];
+
+ if ( cut.contains( key ) )
+ {
+ if ( emitSignals() )
+ emit textRotation( KCompletionBase::PrevCompletionMatch );
+ if ( handleSignals() )
+ rotateText( KCompletionBase::PrevCompletionMatch );
+ return;
+ }
+
+ // Handles next match
+ if ( keys[NextCompletionMatch].isNull() )
+ cut = KStdAccel::shortcut(KStdAccel::NextCompletion);
+ else
+ cut = keys[NextCompletionMatch];
+
+ if ( cut.contains( key ) )
+ {
+ if ( emitSignals() )
+ emit textRotation( KCompletionBase::NextCompletionMatch );
+ if ( handleSignals() )
+ rotateText( KCompletionBase::NextCompletionMatch );
+ return;
+ }
+ }
+
+ // substring completion
+ if ( compObj() )
+ {
+ KShortcut cut;
+ if ( keys[SubstringCompletion].isNull() )
+ cut = KStdAccel::shortcut(KStdAccel::SubstringCompletion);
+ else
+ cut = keys[SubstringCompletion];
+
+ if ( cut.contains( key ) )
+ {
+ if ( emitSignals() )
+ emit substringCompletion( text() );
+ if ( handleSignals() )
+ {
+ setCompletedItems( compObj()->substringCompletion(text()));
+ e->accept();
+ }
+ return;
+ }
+ }
+ }
+
+ uint selectedLength = selectedText().length();
+
+ // Let QLineEdit handle any other keys events.
+ QLineEdit::keyPressEvent ( e );
+
+ if ( selectedLength != selectedText().length() )
+ slotRestoreSelectionColors(); // and set userSelection to true
+}
+
+void KLineEdit::mouseDoubleClickEvent( QMouseEvent* e )
+{
+ if ( e->button() == Qt::LeftButton )
+ {
+ possibleTripleClick=true;
+ QTimer::singleShot( QApplication::doubleClickInterval(),this,
+ SLOT(tripleClickTimeout()) );
+ }
+ QLineEdit::mouseDoubleClickEvent( e );
+}
+
+void KLineEdit::mousePressEvent( QMouseEvent* e )
+{
+ if ( possibleTripleClick && e->button() == Qt::LeftButton )
+ {
+ selectAll();
+ e->accept();
+ return;
+ }
+ QLineEdit::mousePressEvent( e );
+}
+
+void KLineEdit::mouseReleaseEvent( QMouseEvent* e )
+{
+ QLineEdit::mouseReleaseEvent( e );
+ if (QApplication::clipboard()->supportsSelection() ) {
+ if ( e->button() == LeftButton ) {
+ // Fix copying of squeezed text if needed
+ copySqueezedText( false );
+ }
+ }
+}
+
+void KLineEdit::tripleClickTimeout()
+{
+ possibleTripleClick=false;
+}
+
+void KLineEdit::contextMenuEvent( QContextMenuEvent * e )
+{
+ if ( m_bEnableMenu )
+ QLineEdit::contextMenuEvent( e );
+}
+
+QPopupMenu *KLineEdit::createPopupMenu()
+{
+ enum { IdUndo, IdRedo, IdSep1, IdCut, IdCopy, IdPaste, IdClear, IdSep2, IdSelectAll };
+
+ QPopupMenu *popup = QLineEdit::createPopupMenu();
+
+ int id = popup->idAt(0);
+ popup->changeItem( id - IdUndo, SmallIconSet("undo"), popup->text( id - IdUndo) );
+ popup->changeItem( id - IdRedo, SmallIconSet("redo"), popup->text( id - IdRedo) );
+ popup->changeItem( id - IdCut, SmallIconSet("editcut"), popup->text( id - IdCut) );
+ popup->changeItem( id - IdCopy, SmallIconSet("editcopy"), popup->text( id - IdCopy) );
+ popup->changeItem( id - IdPaste, SmallIconSet("editpaste"), popup->text( id - IdPaste) );
+ popup->changeItem( id - IdClear, SmallIconSet("editclear"), popup->text( id - IdClear) );
+
+ // If a completion object is present and the input
+ // widget is not read-only, show the Text Completion
+ // menu item.
+ if ( compObj() && !isReadOnly() && kapp->authorize("lineedit_text_completion") )
+ {
+ QPopupMenu *subMenu = new QPopupMenu( popup );
+ connect( subMenu, SIGNAL( activated( int ) ),
+ this, SLOT( completionMenuActivated( int ) ) );
+
+ popup->insertSeparator();
+ popup->insertItem( SmallIconSet("completion"), i18n("Text Completion"),
+ subMenu );
+
+ subMenu->insertItem( i18n("None"), NoCompletion );
+ subMenu->insertItem( i18n("Manual"), ShellCompletion );
+ subMenu->insertItem( i18n("Automatic"), AutoCompletion );
+ subMenu->insertItem( i18n("Dropdown List"), PopupCompletion );
+ subMenu->insertItem( i18n("Short Automatic"), ShortAutoCompletion );
+ subMenu->insertItem( i18n("Dropdown List && Automatic"), PopupAutoCompletion );
+
+ subMenu->setAccel( KStdAccel::completion(), ShellCompletion );
+
+ KGlobalSettings::Completion mode = completionMode();
+ subMenu->setItemChecked( NoCompletion,
+ mode == KGlobalSettings::CompletionNone );
+ subMenu->setItemChecked( ShellCompletion,
+ mode == KGlobalSettings::CompletionShell );
+ subMenu->setItemChecked( PopupCompletion,
+ mode == KGlobalSettings::CompletionPopup );
+ subMenu->setItemChecked( AutoCompletion,
+ mode == KGlobalSettings::CompletionAuto );
+ subMenu->setItemChecked( ShortAutoCompletion,
+ mode == KGlobalSettings::CompletionMan );
+ subMenu->setItemChecked( PopupAutoCompletion,
+ mode == KGlobalSettings::CompletionPopupAuto );
+ if ( mode != KGlobalSettings::completionMode() )
+ {
+ subMenu->insertSeparator();
+ subMenu->insertItem( i18n("Default"), Default );
+ }
+ }
+
+ // ### do we really need this? Yes, Please do not remove! This
+ // allows applications to extend the popup menu without having to
+ // inherit from this class! (DA)
+ emit aboutToShowContextMenu( popup );
+
+ return popup;
+}
+
+void KLineEdit::completionMenuActivated( int id )
+{
+ KGlobalSettings::Completion oldMode = completionMode();
+
+ switch ( id )
+ {
+ case Default:
+ setCompletionMode( KGlobalSettings::completionMode() );
+ break;
+ case NoCompletion:
+ setCompletionMode( KGlobalSettings::CompletionNone );
+ break;
+ case AutoCompletion:
+ setCompletionMode( KGlobalSettings::CompletionAuto );
+ break;
+ case ShortAutoCompletion:
+ setCompletionMode( KGlobalSettings::CompletionMan );
+ break;
+ case ShellCompletion:
+ setCompletionMode( KGlobalSettings::CompletionShell );
+ break;
+ case PopupCompletion:
+ setCompletionMode( KGlobalSettings::CompletionPopup );
+ break;
+ case PopupAutoCompletion:
+ setCompletionMode( KGlobalSettings::CompletionPopupAuto );
+ break;
+ default:
+ return;
+ }
+
+ if ( oldMode != completionMode() )
+ {
+ if ( (oldMode == KGlobalSettings::CompletionPopup ||
+ oldMode == KGlobalSettings::CompletionPopupAuto ) &&
+ d->completionBox && d->completionBox->isVisible() )
+ d->completionBox->hide();
+ emit completionModeChanged( completionMode() );
+ }
+}
+
+void KLineEdit::drawContents( QPainter *p )
+{
+ QLineEdit::drawContents( p );
+
+ if ( d->drawClickMsg && !hasFocus() ) {
+ QPen tmp = p->pen();
+ p->setPen( palette().color( QPalette::Disabled, QColorGroup::Text ) );
+ QRect cr = contentsRect();
+
+ // Add two pixel margin on the left side
+ cr.rLeft() += 3;
+ p->drawText( cr, AlignAuto | AlignVCenter, d->clickMessage );
+ p->setPen( tmp );
+ }
+}
+
+void KLineEdit::dropEvent(QDropEvent *e)
+{
+ d->drawClickMsg = false;
+ KURL::List urlList;
+ if( d->handleURLDrops && KURLDrag::decode( e, urlList ) )
+ {
+ QString dropText = text();
+ KURL::List::ConstIterator it;
+ for( it = urlList.begin() ; it != urlList.end() ; ++it )
+ {
+ if(!dropText.isEmpty())
+ dropText+=' ';
+
+ dropText += (*it).prettyURL();
+ }
+
+ validateAndSet( dropText, dropText.length(), 0, 0);
+
+ e->accept();
+ }
+ else
+ QLineEdit::dropEvent(e);
+}
+
+bool KLineEdit::eventFilter( QObject* o, QEvent* ev )
+{
+ if( o == this )
+ {
+ KCursor::autoHideEventFilter( this, ev );
+ if ( ev->type() == QEvent::AccelOverride )
+ {
+ QKeyEvent *e = static_cast<QKeyEvent *>( ev );
+ if (overrideAccel (e))
+ {
+ e->accept();
+ return true;
+ }
+ }
+ else if( ev->type() == QEvent::KeyPress )
+ {
+ QKeyEvent *e = static_cast<QKeyEvent *>( ev );
+
+ if( e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter )
+ {
+ bool trap = d->completionBox && d->completionBox->isVisible();
+
+ bool stopEvent = trap || (d->grabReturnKeyEvents &&
+ (e->state() == NoButton ||
+ e->state() == Keypad));
+
+ // Qt will emit returnPressed() itself if we return false
+ if ( stopEvent )
+ {
+ emit QLineEdit::returnPressed();
+ e->accept ();
+ }
+
+ emit returnPressed( displayText() );
+
+ if ( trap )
+ {
+ d->completionBox->hide();
+ deselect();
+ setCursorPosition(text().length());
+ }
+
+ // Eat the event if the user asked for it, or if a completionbox was visible
+ return stopEvent;
+ }
+ }
+ }
+ return QLineEdit::eventFilter( o, ev );
+}
+
+
+void KLineEdit::setURLDropsEnabled(bool enable)
+{
+ d->handleURLDrops=enable;
+}
+
+bool KLineEdit::isURLDropsEnabled() const
+{
+ return d->handleURLDrops;
+}
+
+void KLineEdit::setTrapReturnKey( bool grab )
+{
+ d->grabReturnKeyEvents = grab;
+}
+
+bool KLineEdit::trapReturnKey() const
+{
+ return d->grabReturnKeyEvents;
+}
+
+void KLineEdit::setURL( const KURL& url )
+{
+ setText( url.prettyURL() );
+}
+
+void KLineEdit::setCompletionBox( KCompletionBox *box )
+{
+ if ( d->completionBox )
+ return;
+
+ d->completionBox = box;
+ if ( handleSignals() )
+ {
+ connect( d->completionBox, SIGNAL(highlighted( const QString& )),
+ SLOT(setTextWorkaround( const QString& )) );
+ connect( d->completionBox, SIGNAL(userCancelled( const QString& )),
+ SLOT(userCancelled( const QString& )) );
+
+ // TODO: we need our own slot, and to call setModified(true) if Qt4 has that.
+ connect( d->completionBox, SIGNAL( activated( const QString& )),
+ SIGNAL(completionBoxActivated( const QString& )) );
+ }
+}
+
+void KLineEdit::userCancelled(const QString & cancelText)
+{
+ if ( completionMode() != KGlobalSettings::CompletionPopupAuto )
+ {
+ // TODO: this sets modified==false. But maybe it was true before...
+ setText(cancelText);
+ }
+ else if (hasSelectedText() )
+ {
+ if (d->userSelection)
+ deselect();
+ else
+ {
+ d->autoSuggest=false;
+ int start,end;
+ getSelection(&start, &end);
+ QString s=text().remove(start, end-start+1);
+ validateAndSet(s,start,s.length(),s.length());
+ d->autoSuggest=true;
+ }
+ }
+}
+
+bool KLineEdit::overrideAccel (const QKeyEvent* e)
+{
+ KShortcut scKey;
+
+ KKey key( e );
+ KeyBindingMap keys = getKeyBindings();
+
+ if (keys[TextCompletion].isNull())
+ scKey = KStdAccel::shortcut(KStdAccel::TextCompletion);
+ else
+ scKey = keys[TextCompletion];
+
+ if (scKey.contains( key ))
+ return true;
+
+ if (keys[NextCompletionMatch].isNull())
+ scKey = KStdAccel::shortcut(KStdAccel::NextCompletion);
+ else
+ scKey = keys[NextCompletionMatch];
+
+ if (scKey.contains( key ))
+ return true;
+
+ if (keys[PrevCompletionMatch].isNull())
+ scKey = KStdAccel::shortcut(KStdAccel::PrevCompletion);
+ else
+ scKey = keys[PrevCompletionMatch];
+
+ if (scKey.contains( key ))
+ return true;
+
+ // Override all the text manupilation accelerators...
+ if ( KStdAccel::copy().contains( key ) )
+ return true;
+ else if ( KStdAccel::paste().contains( key ) )
+ return true;
+ else if ( KStdAccel::cut().contains( key ) )
+ return true;
+ else if ( KStdAccel::undo().contains( key ) )
+ return true;
+ else if ( KStdAccel::redo().contains( key ) )
+ return true;
+ else if (KStdAccel::deleteWordBack().contains( key ))
+ return true;
+ else if (KStdAccel::deleteWordForward().contains( key ))
+ return true;
+ else if (KStdAccel::forwardWord().contains( key ))
+ return true;
+ else if (KStdAccel::backwardWord().contains( key ))
+ return true;
+ else if (KStdAccel::beginningOfLine().contains( key ))
+ return true;
+ else if (KStdAccel::endOfLine().contains( key ))
+ return true;
+
+ if (d->completionBox && d->completionBox->isVisible ())
+ {
+ int key = e->key();
+ ButtonState state = e->state();
+ if ((key == Key_Backtab || key == Key_Tab) &&
+ (state == NoButton || (state & ShiftButton)))
+ {
+ return true;
+ }
+ }
+
+
+ return false;
+}
+
+void KLineEdit::setCompletedItems( const QStringList& items )
+{
+ setCompletedItems( items, true );
+}
+
+void KLineEdit::setCompletedItems( const QStringList& items, bool autoSuggest )
+{
+ QString txt;
+ if ( d->completionBox && d->completionBox->isVisible() ) {
+ // The popup is visible already - do the matching on the initial string,
+ // not on the currently selected one.
+ txt = completionBox()->cancelledText();
+ } else {
+ txt = text();
+ }
+
+ if ( !items.isEmpty() &&
+ !(items.count() == 1 && txt == items.first()) )
+ {
+ // create completion box if non-existent
+ completionBox();
+
+ if ( d->completionBox->isVisible() )
+ {
+ bool wasSelected = d->completionBox->isSelected( d->completionBox->currentItem() );
+ const QString currentSelection = d->completionBox->currentText();
+ d->completionBox->setItems( items );
+ QListBoxItem* item = d->completionBox->findItem( currentSelection, Qt::ExactMatch );
+ // If no item is selected, that means the listbox hasn't been manipulated by the user yet,
+ // because it's not possible otherwise to have no selected item. In such case make
+ // always the first item current and unselected, so that the current item doesn't jump.
+ if( !item || !wasSelected )
+ {
+ wasSelected = false;
+ item = d->completionBox->item( 0 );
+ }
+ if ( item )
+ {
+ d->completionBox->blockSignals( true );
+ d->completionBox->setCurrentItem( item );
+ d->completionBox->setSelected( item, wasSelected );
+ d->completionBox->blockSignals( false );
+ }
+ }
+ else // completion box not visible yet -> show it
+ {
+ if ( !txt.isEmpty() )
+ d->completionBox->setCancelledText( txt );
+ d->completionBox->setItems( items );
+ d->completionBox->popup();
+ }
+
+ if ( d->autoSuggest && autoSuggest )
+ {
+ int index = items.first().find( txt );
+ QString newText = items.first().mid( index );
+ setUserSelection(false);
+ setCompletedText(newText,true);
+ }
+ }
+ else
+ {
+ if ( d->completionBox && d->completionBox->isVisible() )
+ d->completionBox->hide();
+ }
+}
+
+KCompletionBox * KLineEdit::completionBox( bool create )
+{
+ if ( create && !d->completionBox ) {
+ setCompletionBox( new KCompletionBox( this, "completion box" ) );
+ d->completionBox->setFont(font());
+ }
+
+ return d->completionBox;
+}
+
+void KLineEdit::setCompletionObject( KCompletion* comp, bool hsig )
+{
+ KCompletion *oldComp = compObj();
+ if ( oldComp && handleSignals() )
+ disconnect( oldComp, SIGNAL( matches( const QStringList& )),
+ this, SLOT( setCompletedItems( const QStringList& )));
+
+ if ( comp && hsig )
+ connect( comp, SIGNAL( matches( const QStringList& )),
+ this, SLOT( setCompletedItems( const QStringList& )));
+
+ KCompletionBase::setCompletionObject( comp, hsig );
+}
+
+// QWidget::create() turns off mouse-Tracking which would break auto-hiding
+void KLineEdit::create( WId id, bool initializeWindow, bool destroyOldWindow )
+{
+ QLineEdit::create( id, initializeWindow, destroyOldWindow );
+ KCursor::setAutoHideCursor( this, true, true );
+}
+
+void KLineEdit::setUserSelection(bool userSelection)
+{
+ QPalette p = palette();
+
+ if (userSelection)
+ {
+ p.setColor(QColorGroup::Highlight, d->previousHighlightColor);
+ p.setColor(QColorGroup::HighlightedText, d->previousHighlightedTextColor);
+ }
+ else
+ {
+ QColor color=p.color(QPalette::Disabled, QColorGroup::Text);
+ p.setColor(QColorGroup::HighlightedText, color);
+ color=p.color(QPalette::Active, QColorGroup::Base);
+ p.setColor(QColorGroup::Highlight, color);
+ }
+
+ d->userSelection=userSelection;
+ setPalette(p);
+}
+
+void KLineEdit::slotRestoreSelectionColors()
+{
+ if (d->disableRestoreSelection)
+ return;
+
+ setUserSelection(true);
+}
+
+void KLineEdit::clear()
+{
+ setText( QString::null );
+}
+
+void KLineEdit::setTextWorkaround( const QString& text )
+{
+ setText( text );
+ end( false ); // force cursor at end
+}
+
+QString KLineEdit::originalText() const
+{
+ if ( d->enableSqueezedText && isReadOnly() )
+ return d->squeezedText;
+
+ return text();
+}
+
+void KLineEdit::focusInEvent( QFocusEvent* ev)
+{
+ if ( d->drawClickMsg ) {
+ d->drawClickMsg = false;
+ update();
+ }
+
+ // Don't selectAll() in QLineEdit::focusInEvent if selection exists
+ if ( ev->reason() == QFocusEvent::Tab && inputMask().isNull() && hasSelectedText() )
+ return;
+
+ QLineEdit::focusInEvent(ev);
+}
+
+void KLineEdit::focusOutEvent( QFocusEvent* ev)
+{
+ if ( text().isEmpty() && !d->clickMessage.isEmpty() ) {
+ d->drawClickMsg = true;
+ update();
+ }
+ QLineEdit::focusOutEvent( ev );
+}
+
+bool KLineEdit::autoSuggest() const
+{
+ return d->autoSuggest;
+}
+
+void KLineEdit::setClickMessage( const QString &msg )
+{
+ d->clickMessage = msg;
+ update();
+}
+
+QString KLineEdit::clickMessage() const
+{
+ return d->clickMessage;
+}
+
+
+void KLineEdit::virtual_hook( int id, void* data )
+{ KCompletionBase::virtual_hook( id, data ); }
diff --git a/kdeui/klineedit.h b/kdeui/klineedit.h
new file mode 100644
index 000000000..bd3cb6faf
--- /dev/null
+++ b/kdeui/klineedit.h
@@ -0,0 +1,656 @@
+/* This file is part of the KDE libraries
+
+ This class was originally inspired by Torben Weis'
+ fileentry.cpp for KFM II.
+
+ Copyright (C) 1997 Sven Radej <sven.radej@iname.com>
+ Copyright (c) 1999 Patrick Ward <PAT_WARD@HP-USA-om5.om.hp.com>
+ Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+
+ Completely re-designed:
+ Copyright (c) 2000,2001 Dawit Alemayehu <adawit@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License (LGPL) as published by the Free Software Foundation;
+ either version 2 of the License, or (at your option) any later
+ version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _KLINEEDIT_H
+#define _KLINEEDIT_H
+
+#include <qlineedit.h>
+#include <kcompletion.h>
+
+class QPopupMenu;
+
+class KCompletionBox;
+class KURL;
+
+/**
+ * An enhanced QLineEdit widget for inputting text.
+ *
+ * \b Detail \n
+ *
+ * This widget inherits from QLineEdit and implements the following
+ * additional functionalities: a completion object that provides both
+ * automatic and manual text completion as well as multiple match iteration
+ * features, configurable key-bindings to activate these features and a
+ * popup-menu item that can be used to allow the user to set text completion
+ * modes on the fly based on their preference.
+ *
+ * To support these new features KLineEdit also emits a few more
+ * additional signals. These are: completion( const QString& ),
+ * textRotation( KeyBindingType ), and returnPressed( const QString& ).
+ * The completion signal can be connected to a slot that will assist the
+ * user in filling out the remaining text. The text rotation signal is
+ * intended to be used to iterate through the list of all possible matches
+ * whenever there is more than one match for the entered text. The
+ * @p returnPressed( const QString& ) signals are the same as QLineEdit's
+ * except it provides the current text in the widget as its argument whenever
+ * appropriate.
+ *
+ * This widget by default creates a completion object when you invoke
+ * the completionObject( bool ) member function for the first time or
+ * use setCompletionObject( KCompletion*, bool ) to assign your own
+ * completion object. Additionally, to make this widget more functional,
+ * KLineEdit will by default handle the text rotation and completion
+ * events internally when a completion object is created through either one
+ * of the methods mentioned above. If you do not need this functionality,
+ * simply use @p setHandleSignals( bool ) or set the boolean parameter in
+ * the above functions to false.
+ *
+ * The default key-bindings for completion and rotation is determined
+ * from the global settings in KStdAccel. These values, however, can
+ * be overridden locally by invoking @p setKeyBinding(). You can easily
+ * revert these settings back to the default by simply calling
+ * @p useGlobalSettings(). An alternate method would be to default
+ * individual key-bindings by using setKeyBinding() with the default
+ * second argument.
+ *
+ * If @p EchoMode for this widget is set to something other than @p QLineEdit::Normal,
+ * the completion mode will always be defaulted to KGlobalSettings::CompletionNone.
+ * This is done purposefully to guard against protected entries such as passwords being
+ * cached in KCompletion's list. Hence, if the @p EchoMode is not QLineEdit::Normal, the
+ * completion mode is automatically disabled.
+ *
+ * A read-only KLineEdit will have the same background color as a
+ * disabled KLineEdit, but its foreground color will be the one used
+ * for the read-write mode. This differs from QLineEdit's implementation
+ * and is done to give visual distinction between the three different modes:
+ * disabled, read-only, and read-write.
+ *
+ * \b Usage \n
+ *
+ * To enable the basic completion feature :
+ *
+ * \code
+ * KLineEdit *edit = new KLineEdit( this, "mywidget" );
+ * KCompletion *comp = edit->completionObject();
+ * // Connect to the return pressed signal - optional
+ * connect(edit,SIGNAL(returnPressed(const QString&)),comp,SLOT(addItem(const QString&)));
+ * \endcode
+ *
+ * To use a customized completion objects or your
+ * own completion object :
+ *
+ * \code
+ * KLineEdit *edit = new KLineEdit( this,"mywidget" );
+ * KURLCompletion *comp = new KURLCompletion();
+ * edit->setCompletionObject( comp );
+ * // Connect to the return pressed signal - optional
+ * connect(edit,SIGNAL(returnPressed(const QString&)),comp,SLOT(addItem(const QString&)));
+ * \endcode
+ *
+ * Note if you specify your own completion object you have to either delete
+ * it when you don't need it anymore, or you can tell KLineEdit to delete it
+ * for you:
+ * \code
+ * edit->setAutoDeleteCompletionObject( true );
+ * \endcode
+ *
+ * <b>Miscellaneous function calls :</b>\n
+ *
+ * \code
+ * // Tell the widget to not handle completion and iteration automatically.
+ * edit->setHandleSignals( false );
+ *
+ * // Set your own key-bindings for a text completion mode.
+ * edit->setKeyBinding( KCompletionBase::TextCompletion, Qt::End );
+ *
+ * // Hide the context (popup) menu
+ * edit->setContextMenuEnabled( false );
+ *
+ * // Temporarily disable signal (both completion & iteration) emitions
+ * edit->disableSignals();
+ *
+ * // Default the key-bindings back to the default system settings.
+ * edit->useGlobalKeyBindings();
+ * \endcode
+ *
+ * @author Dawit Alemayehu <adawit@kde.org>
+ */
+
+class KDEUI_EXPORT KLineEdit : public QLineEdit, public KCompletionBase
+{
+ friend class KComboBox;
+
+ Q_OBJECT
+ Q_PROPERTY( bool contextMenuEnabled READ isContextMenuEnabled WRITE setContextMenuEnabled )
+ Q_PROPERTY( bool urlDropsEnabled READ isURLDropsEnabled WRITE setURLDropsEnabled )
+ Q_PROPERTY( bool trapEnterKeyEvent READ trapReturnKey WRITE setTrapReturnKey )
+ Q_PROPERTY( bool enableSqueezedText READ isSqueezedTextEnabled WRITE setEnableSqueezedText )
+ // @since 3.5.4
+ Q_PROPERTY( QString clickMessage READ clickMessage WRITE setClickMessage )
+
+public:
+
+ /**
+ * Constructs a KLineEdit object with a default text, a parent,
+ * and a name.
+ *
+ * @param string Text to be shown in the edit widget.
+ * @param parent The parent object of this widget.
+ * @param name the name of this widget
+ */
+ KLineEdit( const QString &string, QWidget *parent, const char *name = 0 );
+
+ /**
+ * Constructs a KLineEdit object with a parent and a name.
+ *
+ * @param parent The parent object of this widget.
+ * @param name The name of this widget.
+ */
+ KLineEdit ( QWidget *parent=0, const char *name=0 );
+
+ /**
+ * Destructor.
+ */
+ virtual ~KLineEdit ();
+
+ /**
+ * Sets @p url into the lineedit. It uses KURL::prettyURL() so
+ * that the url is properly decoded for displaying.
+ */
+ void setURL( const KURL& url );
+
+ /**
+ * Puts the text cursor at the end of the string.
+ *
+ * This method is deprecated. Use QLineEdit::end()
+ * instead.
+ *
+ * @deprecated
+ * QLineEdit::end()
+ */
+ void cursorAtEnd() { end( false ); }
+
+ /**
+ * Re-implemented from KCompletionBase for internal reasons.
+ *
+ * This function is re-implemented in order to make sure that
+ * the EchoMode is acceptable before we set the completion mode.
+ *
+ * See KCompletionBase::setCompletionMode
+ */
+ virtual void setCompletionMode( KGlobalSettings::Completion mode );
+
+ /**
+ * Enables/disables the popup (context) menu.
+ *
+ * Note that when this function is invoked with its argument
+ * set to @p true, then both the context menu and the completion
+ * menu item are enabled. If you do not want to the completion
+ * item to be visible simply invoke hideModechanger() right
+ * after calling this method. Also by default, the context
+ * menu is automatically created if this widget is editable. Thus
+ * you need to call this function with the argument set to false
+ * if you do not want this behavior.
+ *
+ * @param showMenu If @p true, show the context menu.
+ */
+ virtual void setContextMenuEnabled( bool showMenu ) { m_bEnableMenu = showMenu; }
+
+ /**
+ * Returns @p true when the context menu is enabled.
+ */
+ bool isContextMenuEnabled() const { return m_bEnableMenu; }
+
+ /**
+ * Enables/Disables handling of URL drops. If enabled and the user
+ * drops an URL, the decoded URL will be inserted. Otherwise the default
+ * behavior of QLineEdit is used, which inserts the encoded URL.
+ *
+ * @param enable If @p true, insert decoded URLs
+ */
+ void setURLDropsEnabled( bool enable );
+
+ /**
+ * Returns @p true when decoded URL drops are enabled
+ */
+ bool isURLDropsEnabled() const;
+
+ /**
+ * By default, KLineEdit recognizes @p Key_Return and @p Key_Enter and emits
+ * the returnPressed() signals, but it also lets the event pass,
+ * for example causing a dialog's default-button to be called.
+ *
+ * Call this method with @p trap = @p true to make @p KLineEdit stop these
+ * events. The signals will still be emitted of course.
+ *
+ * @see trapReturnKey()
+ */
+ void setTrapReturnKey( bool trap );
+
+ /**
+ * @returns @p true if keyevents of @p Key_Return or
+ * @p Key_Enter will be stopped or if they will be propagated.
+ *
+ * @see setTrapReturnKey ()
+ */
+ bool trapReturnKey() const;
+
+ /**
+ * Re-implemented for internal reasons. API not affected.
+ *
+ */
+ virtual bool eventFilter( QObject *, QEvent * );
+
+ /**
+ * @returns the completion-box, that is used in completion mode
+ * KGlobalSettings::CompletionPopup.
+ * This method will create a completion-box if none is there, yet.
+ *
+ * @param create Set this to false if you don't want the box to be created
+ * i.e. to test if it is available.
+ */
+ KCompletionBox * completionBox( bool create = true );
+
+ /**
+ * Reimplemented for internal reasons, the API is not affected.
+ */
+ virtual void setCompletionObject( KCompletion *, bool hsig = true );
+
+ /**
+ * Reimplemented for internal reasons, the API is not affected.
+ */
+ virtual void copy() const;
+
+ /**
+ * Enable text squeezing whenever the supplied text is too long.
+ * Only works for "read-only" mode.
+ *
+ * Note that once text squeezing is enabled, QLineEdit::text()
+ * and QLineEdit::displayText() return the squeezed text. If
+ * you want the original text, use @ref originalText.
+ *
+ * @see QLineEdit
+ * @since 3.2
+ */
+ void setEnableSqueezedText( bool enable );
+
+ /**
+ * Returns true if text squeezing is enabled.
+ * This is only valid when the widget is in read-only mode.
+ *
+ * @since 3.2
+ */
+ bool isSqueezedTextEnabled() const;
+
+ /**
+ * Returns the original text if text squeezing is enabled.
+ * If the widget is not in "read-only" mode, this function
+ * returns the same thing as QLineEdit::text().
+ *
+ * @see QLineEdit
+ * @since 3.2
+ */
+ QString originalText() const;
+
+ /**
+ * Set the completion-box to be used in completion mode
+ * KGlobalSettings::CompletionPopup.
+ * This will do nothing if a completion-box already exists.
+ *
+ * @param box The KCompletionBox to set
+ * @since 3.4
+ */
+ void setCompletionBox( KCompletionBox *box );
+
+ /**
+ * This makes the line edit display a grayed-out hinting text as long as
+ * the user didn't enter any text. It is often used as indication about
+ * the purpose of the line edit.
+ * @since 3.5.4
+ */
+ void setClickMessage( const QString &msg );
+
+ /**
+ * @return the message set with setClickMessage
+ * @since 3.5.4
+ */
+ QString clickMessage() const;
+
+signals:
+
+ /**
+ * Emitted whenever the completion box is activated.
+ * @since 3.1
+ */
+ void completionBoxActivated (const QString &);
+
+ /**
+ * Emitted when the user presses the return key.
+ *
+ * The argument is the current text. Note that this
+ * signal is @em not emitted if the widget's @p EchoMode is set to
+ * QLineEdit::EchoMode.
+ */
+ void returnPressed( const QString& );
+
+ /**
+ * Emitted when the completion key is pressed.
+ *
+ * Please note that this signal is @em not emitted if the
+ * completion mode is set to @p CompletionNone or @p EchoMode is
+ * @em normal.
+ */
+ void completion( const QString& );
+
+ /**
+ * Emitted when the shortcut for substring completion is pressed.
+ */
+ void substringCompletion( const QString& );
+
+ /**
+ * Emitted when the text rotation key-bindings are pressed.
+ *
+ * The argument indicates which key-binding was pressed.
+ * In KLineEdit's case this can be either one of two values:
+ * PrevCompletionMatch or NextCompletionMatch. See
+ * @p setKeyBinding for details.
+ *
+ * Note that this signal is @em not emitted if the completion
+ * mode is set to @p KGlobalSettings::CompletionNone or
+ * @p echoMode() is @em not normal.
+ */
+ void textRotation( KCompletionBase::KeyBindingType );
+
+ /**
+ * Emitted when the user changed the completion mode by using the
+ * popupmenu.
+ */
+ void completionModeChanged( KGlobalSettings::Completion );
+
+ /**
+ * Emitted before the context menu is displayed.
+ *
+ * The signal allows you to add your own entries into the
+ * the context menu that is created on demand.
+ *
+ * NOTE: Do not store the pointer to the QPopupMenu
+ * provided through since it is created and deleted
+ * on demand.
+ *
+ * @param p the context menu about to be displayed
+ */
+ void aboutToShowContextMenu( QPopupMenu * p );
+
+public slots:
+
+ /**
+ * Re-implemented for internal reasons. API not changed.
+ */
+ virtual void setReadOnly(bool);
+
+ /**
+ * Iterates through all possible matches of the completed text or
+ * the history list.
+ *
+ * This function simply iterates over all possible matches in case
+ * multimple matches are found as a result of a text completion request.
+ * It will have no effect if only a single match is found.
+ *
+ * @param type The key-binding invoked.
+ */
+ void rotateText( KCompletionBase::KeyBindingType type );
+
+ /**
+ * See KCompletionBase::setCompletedText.
+ */
+ virtual void setCompletedText( const QString& );
+
+ /**
+ * Sets @p items into the completion-box if completionMode() is
+ * CompletionPopup. The popup will be shown immediately.
+ *
+ * @param items list of completion matches to be shown in the completion box.
+ */
+ void setCompletedItems( const QStringList& items );
+
+ /**
+ * Same as the above function except it allows you to temporarily
+ * turn off text completion in CompletionPopupAuto mode.
+ *
+ * TODO: Merge with above function in KDE 4.
+ * TODO: Does that make this or the above @deprecated ?
+ *
+ * @param items list of completion matches to be shown in the completion box.
+ * @param autoSuggest true if you want automatic text completion (suggestion) enabled.
+ */
+ void setCompletedItems( const QStringList& items, bool autoSuggest );
+
+ /**
+ * Reimplemented to workaround a buggy QLineEdit::clear()
+ * (changing the clipboard to the text we just had in the lineedit)
+ */
+ virtual void clear();
+
+ /**
+ * Squeezes @p text into the line edit.
+ * This can only be used with read-only line-edits.
+ * @since 3.1
+ */
+ void setSqueezedText( const QString &text);
+
+ /**
+ * Re-implemented to enable text squeezing. API is not affected.
+ */
+ virtual void setText ( const QString& );
+
+
+protected slots:
+
+ /**
+ * Completes the remaining text with a matching one from
+ * a given list.
+ */
+ virtual void makeCompletion( const QString& );
+
+ /**
+ * @deprecated. Will be removed in the next major release!
+ */
+ void slotAboutToShow() {}
+
+ /**
+ * @deprecated. Will be removed in the next major release!
+ */
+ void slotCancelled() {}
+
+ /**
+ * Resets the current displayed text.
+ * Call this function to revert a text completion if the user
+ * cancels the request. Mostly applies to popup completions.
+ */
+ void userCancelled(const QString & cancelText);
+
+protected:
+
+ /**
+ * Re-implemented for internal reasons. API not affected.
+ *
+ * See QLineEdit::resizeEvent().
+ */
+ virtual void resizeEvent( QResizeEvent * );
+
+ /**
+ * Re-implemented for internal reasons. API not affected.
+ *
+ * See QLineEdit::keyPressEvent().
+ */
+ virtual void keyPressEvent( QKeyEvent * );
+
+ /**
+ * Re-implemented for internal reasons. API not affected.
+ *
+ * See QLineEdit::mousePressEvent().
+ */
+ virtual void mousePressEvent( QMouseEvent * );
+
+ /**
+ * Re-implemented for internal reasons. API not affected.
+ *
+ * See QWidget::mouseDoubleClickEvent().
+ */
+ virtual void mouseDoubleClickEvent( QMouseEvent * );
+
+ /**
+ * Re-implemented for internal reasons. API not affected.
+ *
+ * See QLineEdit::mouseReleaseEvent().
+ */
+ virtual void mouseReleaseEvent( QMouseEvent * );
+
+ /**
+ * Re-implemented for internal reasons. API not affected.
+ *
+ * See QLineEdit::contextMenuEvent().
+ */
+ virtual void contextMenuEvent( QContextMenuEvent * );
+
+ /**
+ * Re-implemented for internal reasons. API not affected.
+ *
+ * See QLineEdit::createPopupMenu().
+ */
+ virtual QPopupMenu *createPopupMenu();
+
+ /**
+ * Re-implemented for internal reasons. API not affected.
+ *
+ * See QFrame::drawContents().
+ */
+ virtual void drawContents( QPainter *p );
+
+ /**
+ * Re-implemented to handle URI drops.
+ *
+ * See QLineEdit::dropEvent().
+ */
+ virtual void dropEvent( QDropEvent * );
+
+ /*
+ * This function simply sets the lineedit text and
+ * highlights the text appropriately if the boolean
+ * value is set to true.
+ *
+ * @param text
+ * @param marked
+ */
+ virtual void setCompletedText( const QString& /*text*/, bool /*marked*/ );
+
+
+ /**
+ * Sets the widget in userSelection mode or in automatic completion
+ * selection mode. This changes the colors of selections.
+ */
+ void setUserSelection( bool userSelection );
+
+ /**
+ * Reimplemented for internal reasons, the API is not affected.
+ */
+ virtual void create( WId = 0, bool initializeWindow = true,
+ bool destroyOldWindow = true );
+
+ /**
+ * Re-implemented for internal reasons. API not affected.
+ *
+ * See QLineEdit::focusInEvent().
+ */
+ virtual void focusInEvent( QFocusEvent* );
+
+ /**
+ * Re-implemented for internal reasons. API not affected.
+ *
+ * See QLineEdit::focusOutEvent().
+ */
+ virtual void focusOutEvent( QFocusEvent* );
+
+ /**
+ * Whether in current state text should be auto-suggested
+ * @since 3.4
+ */
+ bool autoSuggest() const;
+
+private slots:
+ void completionMenuActivated( int id );
+ void tripleClickTimeout(); // resets possibleTripleClick
+ void slotRestoreSelectionColors();
+ void setTextWorkaround( const QString& text );
+
+private:
+
+ // Constants that represent the ID's of the popup menu.
+ enum MenuID
+ {
+ Default = 42,
+ NoCompletion,
+ AutoCompletion,
+ ShellCompletion,
+ PopupCompletion,
+ ShortAutoCompletion,
+ PopupAutoCompletion
+ };
+
+ /**
+ * Initializes variables. Called from the constructors.
+ */
+ void init();
+
+ bool copySqueezedText( bool clipboard ) const;
+
+ /**
+ * Checks whether we should/should not consume a key used as
+ * an accelerator.
+ */
+ bool overrideAccel (const QKeyEvent* e);
+
+ /**
+ * Properly sets the squeezed text whenever the widget is
+ * created or resized.
+ */
+ void setSqueezedText ();
+
+ bool m_bEnableMenu;
+
+ bool possibleTripleClick; // set in mousePressEvent, deleted in tripleClickTimeout
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KLineEditPrivate;
+ KLineEditPrivate *d;
+};
+
+#endif
diff --git a/kdeui/klineeditdlg.cpp b/kdeui/klineeditdlg.cpp
new file mode 100644
index 000000000..3d299dad2
--- /dev/null
+++ b/kdeui/klineeditdlg.cpp
@@ -0,0 +1,194 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Preston Brown <pbrown@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#include <config.h>
+
+#include <qvalidator.h>
+#include <qpushbutton.h>
+#include <qlineedit.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#undef Unsorted // Required for --enable-final (qdir.h)
+#include <qfiledialog.h>
+
+#include <kbuttonbox.h>
+#include <klocale.h>
+#include <kapplication.h>
+#include <klineedit.h>
+#include <kstdguiitem.h>
+
+#include "klineeditdlg.h"
+
+KLineEditDlg::KLineEditDlg( const QString&_text, const QString& _value,
+ QWidget *parent )
+ : KDialogBase( Plain, QString::null, Ok|Cancel|User1, Ok, parent, 0L, true,
+ true, KStdGuiItem::clear() )
+{
+ QVBoxLayout *topLayout = new QVBoxLayout( plainPage(), 0, spacingHint() );
+ QLabel *label = new QLabel(_text, plainPage() );
+ topLayout->addWidget( label, 1 );
+
+ edit = new KLineEdit( plainPage(), 0L );
+ edit->setMinimumWidth(edit->sizeHint().width() * 3);
+ label->setBuddy(edit); // please "scheck" style
+ // connect( edit, SIGNAL(returnPressed()), SLOT(accept()) );
+ connect( edit, SIGNAL(textChanged(const QString&)),
+ SLOT(slotTextChanged(const QString&)) );
+ topLayout->addWidget( edit, 1 );
+
+ connect( this, SIGNAL(user1Clicked()), this, SLOT(slotClear()) );
+ edit->setText( _value );
+ if ( _value.isEmpty() )
+ {
+ enableButtonOK( false );
+ enableButton(KDialogBase::User1, false);
+ }
+ edit->setSelection(0, edit->text().length());
+ edit->setFocus();
+}
+
+
+
+#if 0
+KLineEditDlg::KLineEditDlg( const QString&_text, const QString& _value,
+ QWidget *parent, bool _file_mode )
+ : QDialog( parent, 0L, true )
+{
+ QGridLayout *layout = new QGridLayout(this, 4, 3, 10);
+
+ QLabel *label = new QLabel(_text, this);
+ layout->addWidget(label, 0, 0, AlignLeft);
+
+ edit = new KLineEdit( this, 0L );
+ edit->setMinimumWidth(edit->sizeHint().width() * 3);
+ connect( edit, SIGNAL(returnPressed()), SLOT(accept()) );
+
+ if ( _file_mode ) {
+ completion = new KURLCompletion();
+ edit->setCompletionObject( completion );
+ edit->setAutoDeleteCompletionObject( true );
+ } else
+ completion = 0L;
+
+ layout->addMultiCellWidget(edit, 1, 1, 0, _file_mode ? 1 : 2);
+ layout->setColStretch(1, 1);
+
+ if (_file_mode) {
+ QPushButton *browse = new QPushButton(i18n("&Browse..."), this);
+ layout->addWidget(browse, 1, 2, AlignCenter);
+ connect(browse, SIGNAL(clicked()),
+ SLOT(slotBrowse()));
+ }
+
+ QFrame *hLine = new QFrame(this);
+ hLine->setFrameStyle(QFrame::Sunken|QFrame::HLine);
+ layout->addMultiCellWidget(hLine, 2, 2, 0, 2);
+
+ KButtonBox *bBox = new KButtonBox(this);
+ layout->addMultiCellWidget(bBox, 3, 3, 0, 2);
+
+ QPushButton *ok = bBox->addButton(KStdGuiItem::ok());
+ ok->setDefault(true);
+ connect( ok, SIGNAL(clicked()), SLOT(accept()));
+
+ bBox->addStretch(1);
+
+ QPushButton *clear = bBox->addButton(KStdGuiItem::clear());
+ connect( clear, SIGNAL(clicked()), SLOT(slotClear()));
+
+ bBox->addStretch(1);
+
+ QPushButton *cancel = bBox->addButton(KStdGuiItem::cancel());
+ connect( cancel, SIGNAL(clicked()), SLOT(reject()));
+
+ bBox->layout();
+
+ layout->activate();
+
+ edit->setText( _value );
+ edit->setSelection(0, edit->text().length());
+ edit->setFocus();
+}
+#endif
+
+
+KLineEditDlg::~KLineEditDlg()
+{
+}
+
+void KLineEditDlg::slotClear()
+{
+ edit->setText(QString::null);
+}
+
+void KLineEditDlg::slotTextChanged(const QString &text)
+{
+ bool on;
+ if ( edit->validator() ) {
+ QString str = edit->text();
+ int index = edit->cursorPosition();
+ on = ( edit->validator()->validate( str, index )
+ == QValidator::Acceptable );
+ } else {
+ on = !text.isEmpty();
+ }
+ enableButtonOK( on );
+ enableButton(KDialogBase::User1, text.length());
+}
+
+QString KLineEditDlg::text() const
+{
+ return edit->text();
+}
+
+QString KLineEditDlg::getText(const QString &_text, const QString& _value,
+ bool *ok, QWidget *parent, QValidator *_validator )
+{
+ KLineEditDlg dlg(_text, _value, parent );
+ dlg.lineEdit()->setValidator( _validator );
+ dlg.slotTextChanged( _value ); // trigger validation
+
+ bool ok_ = dlg.exec() == QDialog::Accepted;
+ if ( ok )
+ *ok = ok_;
+ if ( ok_ )
+ return dlg.text();
+ return QString::null;
+}
+
+QString KLineEditDlg::getText(const QString &_caption, const QString &_text,
+ const QString& _value,
+ bool *ok, QWidget *parent, QValidator *_validator )
+{
+ KLineEditDlg dlg( _text, _value, parent );
+ dlg.setCaption( _caption );
+ dlg.lineEdit()->setValidator( _validator );
+ dlg.slotTextChanged( _value ); // trigger validation
+
+ bool ok_ = dlg.exec() == QDialog::Accepted;
+ if ( ok )
+ *ok = ok_;
+ if ( ok_ )
+ return dlg.text();
+ return QString::null;
+}
+
+void KLineEditDlg::virtual_hook( int id, void* data )
+{ KDialogBase::virtual_hook( id, data ); }
+
+#include "klineeditdlg.moc"
diff --git a/kdeui/klineeditdlg.h b/kdeui/klineeditdlg.h
new file mode 100644
index 000000000..e5d0d3302
--- /dev/null
+++ b/kdeui/klineeditdlg.h
@@ -0,0 +1,125 @@
+/* This file is part of the KDE libraries
+
+ Copyright (C) 1999 Preston Brown <pbrown@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef __klineeditdlg_h__
+#define __klineeditdlg_h__
+
+class KLineEdit;
+class QValidator;
+
+#include <kdialogbase.h>
+
+/**
+ * @deprecated
+ * Please use KInputDialog instead.
+ *
+ * Dialog for user to enter a single line of text.
+ *
+ * @version $Id$
+ * @author David Faure <faure@kde.org>, layout management by Preston Brown <pbrown@kde.org>
+ */
+
+class KDEUI_EXPORT_DEPRECATED KLineEditDlg : public KDialogBase
+{
+ Q_OBJECT
+public:
+ /**
+ * Create a dialog that asks for a single line of text. _value is
+ * the initial value of the line. _text appears as label on top of
+ * the entry box. If the internal line edit has an associated
+ * QValidator set, the OK button is disabled as long as the
+ * validator doesn't return Acceptable. If there's no validator, the
+ * OK button is enabled whenever the line edit isn't empty.
+ *
+ * If you want to accept empty input, make a trivial QValidator that
+ * always returns Acceptable, e.g. QRegExpValidator with a
+ * regexp of ".*".
+ *
+ * @param _text Text of the label
+ * @param _value Initial value of the inputline
+ * @param parent Parent widget for the line edit dialog
+ */
+ KLineEditDlg( const QString& _text, const QString& _value, QWidget *parent ) KDE_DEPRECATED;
+ virtual ~KLineEditDlg();
+
+ /**
+ * @return the value the user entered
+ */
+ QString text() const;
+
+ /**
+ * @return the line edit widget
+ */
+ KLineEdit *lineEdit() const { return edit; }
+
+ /**
+ * Static convenience function to get a textual input from the user.
+ *
+ * @param text Text of the label
+ * @param value Initial value of the inputline
+ * @param ok this bool will be set to true if user pressed "Ok"
+ * @param validator Validator to be stuffed into the line edit.
+ * @param parent The parent widget
+ */
+ static QString getText(const QString &text, const QString& value,
+ bool *ok, QWidget *parent, QValidator *validator=0 ) KDE_DEPRECATED;
+
+ /**
+ * Static convenience function to get a textual input from the user.
+ * This method includes a caption, and has (almost) the same API as QInputDialog::getText
+ * (no echo mode, we have KPasswordDialog).
+ *
+ * @param caption Caption of the dialog
+ * @param text Text of the label
+ * @param value Initial value of the inputline
+ * @param ok this bool will be set to true if user pressed "Ok"
+ * @param parent The parent widget for this text input dialog
+ * @param validator Validator to be stuffed into the line edit.
+ */
+ static QString getText(const QString &caption, const QString &text,
+ const QString& value=QString::null,
+ bool *ok=0, QWidget *parent=0,
+ QValidator *validator=0) KDE_DEPRECATED;
+
+public slots:
+ /**
+ * Clears the edit widget
+ */
+ void slotClear();
+
+protected slots:
+ /**
+ * Enables and disables the OK button depending on the state
+ * returned by the lineedit's QValidator.
+ */
+ void slotTextChanged( const QString& );
+
+protected:
+ /**
+ * The line edit widget
+ */
+ KLineEdit *edit;
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KLineEditDlgPrivate;
+ KLineEditDlgPrivate* d;
+};
+
+#endif
diff --git a/kdeui/klistbox.cpp b/kdeui/klistbox.cpp
new file mode 100644
index 000000000..e32418149
--- /dev/null
+++ b/kdeui/klistbox.cpp
@@ -0,0 +1,266 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Reginald Stadlbauer <reggie@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#include "config.h"
+
+#include <qtimer.h>
+
+#include <kglobalsettings.h>
+#include <kcursor.h>
+#include <kapplication.h>
+#include <kipc.h>
+#include <kdebug.h>
+
+#include "klistbox.h"
+
+KListBox::KListBox( QWidget *parent, const char *name, WFlags f )
+ : QListBox( parent, name, f ), d(0)
+{
+ connect( this, SIGNAL( onViewport() ),
+ this, SLOT( slotOnViewport() ) );
+ connect( this, SIGNAL( onItem( QListBoxItem * ) ),
+ this, SLOT( slotOnItem( QListBoxItem * ) ) );
+ slotSettingsChanged(KApplication::SETTINGS_MOUSE);
+ if (kapp)
+ {
+ connect( kapp, SIGNAL( settingsChanged(int) ), SLOT( slotSettingsChanged(int) ) );
+ kapp->addKipcEventMask( KIPC::SettingsChanged );
+ }
+
+ m_pCurrentItem = 0L;
+
+ m_pAutoSelect = new QTimer( this );
+ connect( m_pAutoSelect, SIGNAL( timeout() ),
+ this, SLOT( slotAutoSelect() ) );
+}
+
+void KListBox::slotOnItem( QListBoxItem *item )
+{
+ if ( item && m_bChangeCursorOverItem && m_bUseSingle )
+ viewport()->setCursor( KCursor().handCursor() );
+
+ if ( item && (m_autoSelectDelay > -1) && m_bUseSingle ) {
+ m_pAutoSelect->start( m_autoSelectDelay, true );
+ m_pCurrentItem = item;
+ }
+}
+
+void KListBox::slotOnViewport()
+{
+ if ( m_bChangeCursorOverItem )
+ viewport()->unsetCursor();
+
+ m_pAutoSelect->stop();
+ m_pCurrentItem = 0L;
+}
+
+
+void KListBox::slotSettingsChanged(int category)
+{
+ if (category != KApplication::SETTINGS_MOUSE)
+ return;
+ m_bUseSingle = KGlobalSettings::singleClick();
+
+ disconnect( this, SIGNAL( mouseButtonClicked( int, QListBoxItem *,
+ const QPoint & ) ),
+ this, SLOT( slotMouseButtonClicked( int, QListBoxItem *,
+ const QPoint & ) ) );
+// disconnect( this, SIGNAL( doubleClicked( QListBoxItem *,
+// const QPoint & ) ),
+// this, SLOT( slotExecute( QListBoxItem *,
+// const QPoint & ) ) );
+
+ if( m_bUseSingle )
+ {
+ connect( this, SIGNAL( mouseButtonClicked( int, QListBoxItem *,
+ const QPoint & ) ),
+ this, SLOT( slotMouseButtonClicked( int, QListBoxItem *,
+ const QPoint & ) ) );
+ }
+ else
+ {
+// connect( this, SIGNAL( doubleClicked( QListBoxItem *,
+// const QPoint & ) ),
+// this, SLOT( slotExecute( QListBoxItem *,
+// const QPoint & ) ) );
+ }
+
+ m_bChangeCursorOverItem = KGlobalSettings::changeCursorOverIcon();
+ m_autoSelectDelay = KGlobalSettings::autoSelectDelay();
+
+ if( !m_bUseSingle || !m_bChangeCursorOverItem )
+ viewport()->unsetCursor();
+}
+
+void KListBox::slotAutoSelect()
+{
+ // check that the item still exists
+ if( index( m_pCurrentItem ) == -1 )
+ return;
+
+ //Give this widget the keyboard focus.
+ if( !hasFocus() )
+ setFocus();
+
+ ButtonState keybstate = KApplication::keyboardMouseState();
+
+ QListBoxItem* previousItem = item( currentItem() );
+ setCurrentItem( m_pCurrentItem );
+
+ if( m_pCurrentItem ) {
+ //Shift pressed?
+ if( (keybstate & ShiftButton) ) {
+ bool block = signalsBlocked();
+ blockSignals( true );
+
+ //No Ctrl? Then clear before!
+ if( !(keybstate & ControlButton) )
+ clearSelection();
+
+ bool select = !m_pCurrentItem->isSelected();
+ bool update = viewport()->isUpdatesEnabled();
+ viewport()->setUpdatesEnabled( false );
+
+ bool down = index( previousItem ) < index( m_pCurrentItem );
+ QListBoxItem* it = down ? previousItem : m_pCurrentItem;
+ for (;it ; it = it->next() ) {
+ if ( down && it == m_pCurrentItem ) {
+ setSelected( m_pCurrentItem, select );
+ break;
+ }
+ if ( !down && it == previousItem ) {
+ setSelected( previousItem, select );
+ break;
+ }
+ setSelected( it, select );
+ }
+
+ blockSignals( block );
+ viewport()->setUpdatesEnabled( update );
+ triggerUpdate( false );
+
+ emit selectionChanged();
+
+ if( selectionMode() == QListBox::Single )
+ emit selectionChanged( m_pCurrentItem );
+ }
+ else if( (keybstate & ControlButton) )
+ setSelected( m_pCurrentItem, !m_pCurrentItem->isSelected() );
+ else {
+ bool block = signalsBlocked();
+ blockSignals( true );
+
+ if( !m_pCurrentItem->isSelected() )
+ clearSelection();
+
+ blockSignals( block );
+
+ setSelected( m_pCurrentItem, true );
+ }
+ }
+ else
+ kdDebug() << "That´s not supposed to happen!!!!" << endl;
+}
+
+void KListBox::emitExecute( QListBoxItem *item, const QPoint &pos )
+{
+ ButtonState keybstate = KApplication::keyboardMouseState();
+
+ m_pAutoSelect->stop();
+
+ //Don´t emit executed if in SC mode and Shift or Ctrl are pressed
+ if( !( m_bUseSingle && ((keybstate & ShiftButton) || (keybstate & ControlButton)) ) ) {
+ emit executed( item );
+ emit executed( item, pos );
+ }
+}
+
+//
+// 2000-16-01 Espen Sand
+// This widget is used in dialogs. It should ignore
+// F1 (and combinations) and Escape since these are used
+// to start help or close the dialog. This functionality
+// should be done in QListView but it is not (at least now)
+//
+void KListBox::keyPressEvent(QKeyEvent *e)
+{
+ if( e->key() == Key_Escape )
+ {
+ e->ignore();
+ }
+ else if( e->key() == Key_F1 )
+ {
+ e->ignore();
+ }
+ else
+ {
+ QListBox::keyPressEvent(e);
+ }
+}
+
+void KListBox::focusOutEvent( QFocusEvent *fe )
+{
+ m_pAutoSelect->stop();
+
+ QListBox::focusOutEvent( fe );
+}
+
+void KListBox::leaveEvent( QEvent *e )
+{
+ m_pAutoSelect->stop();
+
+ QListBox::leaveEvent( e );
+}
+
+void KListBox::contentsMousePressEvent( QMouseEvent *e )
+{
+ if( (selectionMode() == Extended) && (e->state() & ShiftButton) && !(e->state() & ControlButton) ) {
+ bool block = signalsBlocked();
+ blockSignals( true );
+
+ clearSelection();
+
+ blockSignals( block );
+ }
+
+ QListBox::contentsMousePressEvent( e );
+}
+
+void KListBox::contentsMouseDoubleClickEvent ( QMouseEvent * e )
+{
+ QListBox::contentsMouseDoubleClickEvent( e );
+
+ QListBoxItem* item = itemAt( contentsToViewport( e->pos() ) );
+
+ if( item ) {
+ emit doubleClicked( item, e->globalPos() );
+
+ if( (e->button() == LeftButton) && !m_bUseSingle )
+ emitExecute( item, e->globalPos() );
+ }
+}
+
+void KListBox::slotMouseButtonClicked( int btn, QListBoxItem *item, const QPoint &pos )
+{
+ if( (btn == LeftButton) && item )
+ emitExecute( item, pos );
+}
+
+void KListBox::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "klistbox.moc"
diff --git a/kdeui/klistbox.h b/kdeui/klistbox.h
new file mode 100644
index 000000000..ec1afc29f
--- /dev/null
+++ b/kdeui/klistbox.h
@@ -0,0 +1,128 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Reginald Stadlbauer <reggie@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef KLISTBOX_H
+#define KLISTBOX_H
+
+#include <qlistbox.h>
+
+#include <kdelibs_export.h>
+
+/**
+ * @short A variant of QListBox that honors KDE's system-wide settings.
+ *
+ * Extends the functionality of QListBox to honor the system
+ * wide settings for Single Click/Double Click mode, Auto Selection and
+ * Change Cursor over Link.
+ *
+ * There is a new signal executed(). It gets connected to either
+ * QListBox::clicked() or QListBox::doubleClicked()
+ * depending on the KDE wide Single Click/Double Click settings. It is
+ * strongly recommended that you use this signal instead of the above
+ * mentioned. This way you don't need to care about the current
+ * settings. If you want to get informed when the user selects
+ * something connect to the QListBox::selectionChanged() signal.
+ **/
+class KDEUI_EXPORT KListBox : public QListBox
+{
+ Q_OBJECT
+
+public:
+ KListBox( QWidget *parent = 0, const char *name = 0, WFlags f = 0 );
+
+signals:
+
+ /**
+ * Emitted whenever the user executes an listbox item.
+ *
+ * That means depending on the KDE wide Single Click/Double Click
+ * setting the user clicked or double clicked on that item.
+ * @param item is the pointer to the executed listbox item.
+ *
+ * Note that you may not delete any QListBoxItem objects in slots
+ * connected to this signal.
+ */
+ void executed( QListBoxItem *item );
+
+ /**
+ * Emitted whenever the user executes an listbox item.
+ *
+ * That means depending on the KDE wide Single Click/Double Click
+ * setting the user clicked or double clicked on that item.
+ * @param item is the pointer to the executed listbox item.
+ * @param pos is the position where the user has clicked
+ *
+ * Note that you may not delete any QListBoxItem objects in slots
+ * connected to this signal.
+ */
+ void executed( QListBoxItem *item, const QPoint &pos );
+
+ /**
+ * This signal gets emitted whenever the user double clicks into the
+ * listbox.
+ *
+ * @param item The pointer to the clicked listbox item.
+ * @param pos The position where the user has clicked.
+ *
+ * Note that you may not delete any QListBoxItem objects in slots
+ * connected to this signal.
+ *
+ * This signal is more or less here for the sake of completeness.
+ * You should normally not need to use this. In most cases it's better
+ * to use executed() instead.
+ */
+ void doubleClicked( QListBoxItem *item, const QPoint &pos );
+
+protected slots:
+ void slotOnItem( QListBoxItem *item );
+ void slotOnViewport();
+
+ void slotSettingsChanged(int);
+
+ /**
+ * Auto selection happend.
+ */
+ void slotAutoSelect();
+
+protected:
+ void emitExecute( QListBoxItem *item, const QPoint &pos );
+
+ virtual void keyPressEvent(QKeyEvent *e);
+ virtual void focusOutEvent( QFocusEvent *fe );
+ virtual void leaveEvent( QEvent *e );
+ virtual void contentsMousePressEvent( QMouseEvent *e );
+ virtual void contentsMouseDoubleClickEvent ( QMouseEvent *e );
+
+ bool m_bUseSingle;
+ bool m_bChangeCursorOverItem;
+
+ QListBoxItem* m_pCurrentItem;
+
+ QTimer* m_pAutoSelect;
+ int m_autoSelectDelay;
+
+private slots:
+ void slotMouseButtonClicked( int btn, QListBoxItem *item, const QPoint &pos );
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KListBoxPrivate;
+ KListBoxPrivate* const d;
+};
+
+#endif
diff --git a/kdeui/klistview.cpp b/kdeui/klistview.cpp
new file mode 100644
index 000000000..9aeedfb2c
--- /dev/null
+++ b/kdeui/klistview.cpp
@@ -0,0 +1,2365 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2000,2003 Charles Samuels <charles@kde.org>
+ Copyright (C) 2000 Peter Putzer
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#include "config.h"
+
+#include <qdragobject.h>
+#include <qtimer.h>
+#include <qheader.h>
+#include <qcursor.h>
+#include <qtooltip.h>
+#include <qstyle.h>
+#include <qpainter.h>
+
+#include <kglobalsettings.h>
+#include <kconfig.h>
+#include <kcursor.h>
+#include <kapplication.h>
+#include <kipc.h>
+#include <kdebug.h>
+
+#include "klistview.h"
+#include "klistviewlineedit.h"
+
+class KListView::Tooltip : public QToolTip
+{
+public:
+ Tooltip (KListView* parent, QToolTipGroup* group = 0L);
+ virtual ~Tooltip () {}
+
+protected:
+ /**
+ * Reimplemented from QToolTip for internal reasons.
+ */
+ virtual void maybeTip (const QPoint&);
+
+private:
+ KListView* mParent;
+};
+
+KListView::Tooltip::Tooltip (KListView* parent, QToolTipGroup* group)
+ : QToolTip (parent, group),
+ mParent (parent)
+{
+}
+
+void KListView::Tooltip::maybeTip (const QPoint&)
+{
+ // FIXME
+}
+
+class KListView::KListViewPrivate
+{
+public:
+ KListViewPrivate (KListView* listview)
+ : pCurrentItem (0),
+ autoSelectDelay(0),
+ dragOverItem(0),
+ dragDelay (KGlobalSettings::dndEventDelay()),
+ editor (new KListViewLineEdit (listview)),
+ cursorInExecuteArea(false),
+ itemsMovable (true),
+ selectedBySimpleMove(false),
+ selectedUsingMouse(false),
+ itemsRenameable (false),
+ validDrag (false),
+ dragEnabled (false),
+ autoOpen (true),
+ disableAutoSelection (false),
+ dropVisualizer (true),
+ dropHighlighter (false),
+ createChildren (true),
+ pressedOnSelected (false),
+ wasShiftEvent (false),
+ fullWidth (false),
+ sortAscending(true),
+ tabRename(true),
+ sortColumn(0),
+ selectionDirection(0),
+ tooltipColumn (0),
+ selectionMode (Single),
+ contextMenuKey (KGlobalSettings::contextMenuKey()),
+ showContextMenusOnPress (KGlobalSettings::showContextMenusOnPress()),
+ mDropVisualizerWidth (4),
+ paintAbove (0),
+ paintCurrent (0),
+ paintBelow (0),
+ painting (false),
+ shadeSortColumn(KGlobalSettings::shadeSortColumn())
+ {
+ renameable.append(0);
+ connect(editor, SIGNAL(done(QListViewItem*,int)), listview, SLOT(doneEditing(QListViewItem*,int)));
+ }
+
+ ~KListViewPrivate ()
+ {
+ delete editor;
+ }
+
+ QListViewItem* pCurrentItem;
+
+ QTimer autoSelect;
+ int autoSelectDelay;
+
+ QTimer dragExpand;
+ QListViewItem* dragOverItem;
+ QPoint dragOverPoint;
+
+ QPoint startDragPos;
+ int dragDelay;
+
+ KListViewLineEdit *editor;
+ QValueList<int> renameable;
+
+ bool cursorInExecuteArea:1;
+ bool bUseSingle:1;
+ bool bChangeCursorOverItem:1;
+ bool itemsMovable:1;
+ bool selectedBySimpleMove : 1;
+ bool selectedUsingMouse:1;
+ bool itemsRenameable:1;
+ bool validDrag:1;
+ bool dragEnabled:1;
+ bool autoOpen:1;
+ bool disableAutoSelection:1;
+ bool dropVisualizer:1;
+ bool dropHighlighter:1;
+ bool createChildren:1;
+ bool pressedOnSelected:1;
+ bool wasShiftEvent:1;
+ bool fullWidth:1;
+ bool sortAscending:1;
+ bool tabRename:1;
+
+ int sortColumn;
+
+ //+1 means downwards (y increases, -1 means upwards, 0 means not selected), aleXXX
+ int selectionDirection;
+ int tooltipColumn;
+
+ SelectionModeExt selectionMode;
+ int contextMenuKey;
+ bool showContextMenusOnPress;
+
+ QRect mOldDropVisualizer;
+ int mDropVisualizerWidth;
+ QRect mOldDropHighlighter;
+ QListViewItem *afterItemDrop;
+ QListViewItem *parentItemDrop;
+
+ QListViewItem *paintAbove;
+ QListViewItem *paintCurrent;
+ QListViewItem *paintBelow;
+ bool painting:1;
+ bool shadeSortColumn:1;
+
+ QColor alternateBackground;
+};
+
+
+KListViewLineEdit::KListViewLineEdit(KListView *parent)
+ : KLineEdit(parent->viewport()), item(0), col(0), p(parent)
+{
+ setFrame( false );
+ hide();
+ connect( parent, SIGNAL( selectionChanged() ), SLOT( slotSelectionChanged() ));
+ connect( parent, SIGNAL( itemRemoved( QListViewItem * ) ),
+ SLOT( slotItemRemoved( QListViewItem * ) ));
+}
+
+KListViewLineEdit::~KListViewLineEdit()
+{
+}
+
+QListViewItem *KListViewLineEdit::currentItem() const
+{
+ return item;
+}
+
+void KListViewLineEdit::load(QListViewItem *i, int c)
+{
+ item=i;
+ col=c;
+
+ QRect rect(p->itemRect(i));
+ setText(item->text(c));
+ home( true );
+
+ int fieldX = rect.x() - 1;
+ int fieldW = p->columnWidth(col) + 2;
+
+ QHeader* const pHeader = p->header();
+
+ const int pos = pHeader->mapToIndex(col);
+ for ( int index = 0; index < pos; ++index )
+ fieldX += p->columnWidth( pHeader->mapToSection( index ));
+
+ if ( col == 0 ) {
+ int d = i->depth() + (p->rootIsDecorated() ? 1 : 0);
+ d *= p->treeStepSize();
+ fieldX += d;
+ fieldW -= d;
+ }
+
+ if ( i->pixmap( col ) ) {// add width of pixmap
+ int d = i->pixmap( col )->width();
+ fieldX += d;
+ fieldW -= d;
+ }
+
+ setGeometry(fieldX, rect.y() - 1, fieldW, rect.height() + 2);
+ show();
+ setFocus();
+}
+
+/* Helper functions to for
+ * tabOrderedRename functionality.
+ */
+
+static int nextCol (KListView *pl, QListViewItem *pi, int start, int dir)
+{
+ if (pi)
+ {
+ // Find the next renameable column in the current row
+ for (; ((dir == +1) ? (start < pl->columns()) : (start >= 0)); start += dir)
+ if (pl->isRenameable(start))
+ return start;
+ }
+
+ return -1;
+}
+
+static QListViewItem *prevItem (QListViewItem *pi)
+{
+ QListViewItem *pa = pi->itemAbove();
+
+ /* Does what the QListViewItem::previousSibling()
+ * of my dreams would do.
+ */
+ if (pa && pa->parent() == pi->parent())
+ return pa;
+
+ return 0;
+}
+
+static QListViewItem *lastQChild (QListViewItem *pi)
+{
+ if (pi)
+ {
+ /* Since there's no QListViewItem::lastChild().
+ * This finds the last sibling for the given
+ * item.
+ */
+ for (QListViewItem *pt = pi->nextSibling(); pt; pt = pt->nextSibling())
+ pi = pt;
+ }
+
+ return pi;
+}
+
+void KListViewLineEdit::selectNextCell (QListViewItem *pitem, int column, bool forward)
+{
+ const int ncols = p->columns();
+ const int dir = forward ? +1 : -1;
+ const int restart = forward ? 0 : (ncols - 1);
+ QListViewItem *top = (pitem && pitem->parent())
+ ? pitem->parent()->firstChild()
+ : p->firstChild();
+ QListViewItem *pi = pitem;
+
+ terminate(); // Save current changes
+
+ do
+ {
+ /* Check the rest of the current row for an editable column,
+ * if that fails, check the entire next/previous row. The
+ * last case goes back to the first item in the current branch
+ * or the last item in the current branch depending on the
+ * direction.
+ */
+ if ((column = nextCol(p, pi, column + dir, dir)) != -1 ||
+ (column = nextCol(p, (pi = (forward ? pi->nextSibling() : prevItem(pi))), restart, dir)) != -1 ||
+ (column = nextCol(p, (pi = (forward ? top : lastQChild(pitem))), restart, dir)) != -1)
+ {
+ if (pi)
+ {
+ p->setCurrentItem(pi); // Calls terminate
+ p->rename(pi, column);
+
+ /* Some listviews may override rename() to
+ * prevent certain items from being renamed,
+ * if this is done, [m_]item will be NULL
+ * after the rename() call... try again.
+ */
+ if (!item)
+ continue;
+
+ break;
+ }
+ }
+ }
+ while (pi && !item);
+}
+
+#ifdef KeyPress
+#undef KeyPress
+#endif
+
+bool KListViewLineEdit::event (QEvent *pe)
+{
+ if (pe->type() == QEvent::KeyPress)
+ {
+ QKeyEvent *k = (QKeyEvent *) pe;
+
+ if ((k->key() == Qt::Key_Backtab || k->key() == Qt::Key_Tab) &&
+ p->tabOrderedRenaming() && p->itemsRenameable() &&
+ !(k->state() & ControlButton || k->state() & AltButton))
+ {
+ selectNextCell(item, col,
+ (k->key() == Key_Tab && !(k->state() & ShiftButton)));
+ return true;
+ }
+ }
+
+ return KLineEdit::event(pe);
+}
+
+void KListViewLineEdit::keyPressEvent(QKeyEvent *e)
+{
+ if(e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter )
+ terminate(true);
+ else if(e->key() == Qt::Key_Escape)
+ terminate(false);
+ else if (e->key() == Qt::Key_Down || e->key() == Qt::Key_Up)
+ {
+ terminate(true);
+ KLineEdit::keyPressEvent(e);
+ }
+ else
+ KLineEdit::keyPressEvent(e);
+}
+
+void KListViewLineEdit::terminate()
+{
+ terminate(true);
+}
+
+void KListViewLineEdit::terminate(bool commit)
+{
+ if ( item )
+ {
+ //kdDebug() << "KListViewLineEdit::terminate " << commit << endl;
+ if (commit)
+ item->setText(col, text());
+ int c=col;
+ QListViewItem *i=item;
+ col=0;
+ item=0;
+ p->setFocus();// will call focusOutEvent, that's why we set item=0 before
+ hide();
+ if (commit)
+ emit done(i,c);
+ }
+}
+
+void KListViewLineEdit::focusOutEvent(QFocusEvent *ev)
+{
+ QFocusEvent * focusEv = static_cast<QFocusEvent*>(ev);
+ // Don't let a RMB close the editor
+ if (focusEv->reason() != QFocusEvent::Popup && focusEv->reason() != QFocusEvent::ActiveWindow)
+ terminate(true);
+ else
+ KLineEdit::focusOutEvent(ev);
+}
+
+void KListViewLineEdit::paintEvent( QPaintEvent *e )
+{
+ KLineEdit::paintEvent( e );
+
+ if ( !frame() ) {
+ QPainter p( this );
+ p.setClipRegion( e->region() );
+ p.drawRect( rect() );
+ }
+}
+
+// selection changed -> terminate. As our "item" can be already deleted,
+// we can't call terminate(false), because that would emit done() with
+// a dangling pointer to "item".
+void KListViewLineEdit::slotSelectionChanged()
+{
+ item = 0;
+ col = 0;
+ hide();
+}
+
+// if the current item was removed -> terminate. Can't call terminate(false)
+// due to same reason as slotSelectionChanged().
+void KListViewLineEdit::slotItemRemoved(QListViewItem *i)
+{
+ if (currentItem() != i)
+ return;
+
+ item = 0;
+ col = 0;
+ hide();
+}
+
+
+KListView::KListView( QWidget *parent, const char *name )
+ : QListView( parent, name ),
+ d (new KListViewPrivate (this))
+{
+ setDragAutoScroll(true);
+
+ connect( this, SIGNAL( onViewport() ),
+ this, SLOT( slotOnViewport() ) );
+ connect( this, SIGNAL( onItem( QListViewItem * ) ),
+ this, SLOT( slotOnItem( QListViewItem * ) ) );
+
+ connect (this, SIGNAL(contentsMoving(int,int)),
+ this, SLOT(cleanDropVisualizer()));
+ connect (this, SIGNAL(contentsMoving(int,int)),
+ this, SLOT(cleanItemHighlighter()));
+
+ slotSettingsChanged(KApplication::SETTINGS_MOUSE);
+ if (kapp)
+ {
+ connect( kapp, SIGNAL( settingsChanged(int) ), SLOT( slotSettingsChanged(int) ) );
+ kapp->addKipcEventMask( KIPC::SettingsChanged );
+ }
+
+ connect(&d->autoSelect, SIGNAL( timeout() ),
+ this, SLOT( slotAutoSelect() ) );
+ connect(&d->dragExpand, SIGNAL( timeout() ),
+ this, SLOT( slotDragExpand() ) );
+
+ // context menu handling
+ if (d->showContextMenusOnPress)
+ {
+ connect (this, SIGNAL (rightButtonPressed (QListViewItem*, const QPoint&, int)),
+ this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int)));
+ }
+ else
+ {
+ connect (this, SIGNAL (rightButtonClicked (QListViewItem*, const QPoint&, int)),
+ this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int)));
+ }
+
+ connect (this, SIGNAL (menuShortCutPressed (KListView*, QListViewItem*)),
+ this, SLOT (emitContextMenu (KListView*, QListViewItem*)));
+ d->alternateBackground = KGlobalSettings::alternateBackgroundColor();
+}
+
+KListView::~KListView()
+{
+ delete d;
+}
+
+bool KListView::isExecuteArea( const QPoint& point )
+{
+ QListViewItem* item = itemAt( point );
+ if ( item ) {
+ return isExecuteArea( point.x(), item );
+ }
+
+ return false;
+}
+
+bool KListView::isExecuteArea( int x )
+{
+ return isExecuteArea( x, 0 );
+}
+
+bool KListView::isExecuteArea( int x, QListViewItem* item )
+{
+ if( allColumnsShowFocus() )
+ return true;
+ else {
+ int offset = 0;
+
+
+ int width = columnWidth( 0 );
+
+ QHeader* const thisHeader = header();
+ const int pos = thisHeader->mapToIndex( 0 );
+
+ for ( int index = 0; index < pos; ++index )
+ offset += columnWidth( thisHeader->mapToSection( index ) );
+
+ x += contentsX(); // in case of a horizontal scrollbar
+
+ if ( item )
+ {
+ width = treeStepSize()*( item->depth() + ( rootIsDecorated() ? 1 : 0 ) );
+ width += itemMargin();
+ int ca = AlignHorizontal_Mask & columnAlignment( 0 );
+ if ( ca == AlignLeft || ca == AlignAuto ) {
+ width += item->width( fontMetrics(), this, 0 );
+ if ( width > columnWidth( 0 ) )
+ width = columnWidth( 0 );
+ }
+ }
+
+ return ( x > offset && x < ( offset + width ) );
+ }
+}
+
+void KListView::slotOnItem( QListViewItem *item )
+{
+ QPoint vp = viewport()->mapFromGlobal( QCursor::pos() );
+ if ( item && isExecuteArea( vp.x() ) && (d->autoSelectDelay > -1) && d->bUseSingle ) {
+ d->autoSelect.start( d->autoSelectDelay, true );
+ d->pCurrentItem = item;
+ }
+}
+
+void KListView::slotOnViewport()
+{
+ if ( d->bChangeCursorOverItem )
+ viewport()->unsetCursor();
+
+ d->autoSelect.stop();
+ d->pCurrentItem = 0L;
+}
+
+void KListView::slotSettingsChanged(int category)
+{
+ switch (category)
+ {
+ case KApplication::SETTINGS_MOUSE:
+ d->dragDelay = KGlobalSettings::dndEventDelay();
+ d->bUseSingle = KGlobalSettings::singleClick();
+
+ disconnect(this, SIGNAL (mouseButtonClicked (int, QListViewItem*, const QPoint &, int)),
+ this, SLOT (slotMouseButtonClicked (int, QListViewItem*, const QPoint &, int)));
+
+ if( d->bUseSingle )
+ connect (this, SIGNAL (mouseButtonClicked (int, QListViewItem*, const QPoint &, int)),
+ this, SLOT (slotMouseButtonClicked( int, QListViewItem*, const QPoint &, int)));
+
+ d->bChangeCursorOverItem = KGlobalSettings::changeCursorOverIcon();
+ if ( !d->disableAutoSelection )
+ d->autoSelectDelay = KGlobalSettings::autoSelectDelay();
+
+ if( !d->bUseSingle || !d->bChangeCursorOverItem )
+ viewport()->unsetCursor();
+
+ break;
+
+ case KApplication::SETTINGS_POPUPMENU:
+ d->contextMenuKey = KGlobalSettings::contextMenuKey ();
+ d->showContextMenusOnPress = KGlobalSettings::showContextMenusOnPress ();
+
+ if (d->showContextMenusOnPress)
+ {
+ disconnect (0L, 0L, this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int)));
+
+ connect(this, SIGNAL (rightButtonPressed (QListViewItem*, const QPoint&, int)),
+ this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int)));
+ }
+ else
+ {
+ disconnect (0L, 0L, this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int)));
+
+ connect(this, SIGNAL (rightButtonClicked (QListViewItem*, const QPoint&, int)),
+ this, SLOT (emitContextMenu (QListViewItem*, const QPoint&, int)));
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void KListView::slotAutoSelect()
+{
+ // check that the item still exists
+ if( itemIndex( d->pCurrentItem ) == -1 )
+ return;
+
+ if (!isActiveWindow())
+ {
+ d->autoSelect.stop();
+ return;
+ }
+
+ //Give this widget the keyboard focus.
+ if( !hasFocus() )
+ setFocus();
+
+ ButtonState keybstate = KApplication::keyboardMouseState();
+
+ QListViewItem* previousItem = currentItem();
+ setCurrentItem( d->pCurrentItem );
+
+ if( d->pCurrentItem ) {
+ //Shift pressed?
+ if( (keybstate & Qt::ShiftButton) ) {
+ bool block = signalsBlocked();
+ blockSignals( true );
+
+ //No Ctrl? Then clear before!
+ if( !(keybstate & Qt::ControlButton) )
+ clearSelection();
+
+ bool select = !d->pCurrentItem->isSelected();
+ bool update = viewport()->isUpdatesEnabled();
+ viewport()->setUpdatesEnabled( false );
+
+ bool down = previousItem->itemPos() < d->pCurrentItem->itemPos();
+ QListViewItemIterator lit( down ? previousItem : d->pCurrentItem );
+ for ( ; lit.current(); ++lit ) {
+ if ( down && lit.current() == d->pCurrentItem ) {
+ d->pCurrentItem->setSelected( select );
+ break;
+ }
+ if ( !down && lit.current() == previousItem ) {
+ previousItem->setSelected( select );
+ break;
+ }
+ lit.current()->setSelected( select );
+ }
+
+ blockSignals( block );
+ viewport()->setUpdatesEnabled( update );
+ triggerUpdate();
+
+ emit selectionChanged();
+
+ if( selectionMode() == QListView::Single )
+ emit selectionChanged( d->pCurrentItem );
+ }
+ else if( (keybstate & KApplication::ControlModifier) )
+ setSelected( d->pCurrentItem, !d->pCurrentItem->isSelected() );
+ else {
+ bool block = signalsBlocked();
+ blockSignals( true );
+
+ if( !d->pCurrentItem->isSelected() )
+ clearSelection();
+
+ blockSignals( block );
+
+ setSelected( d->pCurrentItem, true );
+ }
+ }
+ else
+ kdDebug() << "KListView::slotAutoSelect: That´s not supposed to happen!!!!" << endl;
+}
+
+void KListView::slotHeaderChanged()
+{
+
+ const int colCount = columns();
+ if (d->fullWidth && colCount)
+ {
+ int w = 0;
+ const int lastColumn = colCount - 1;
+ for (int i = 0; i < lastColumn; ++i) w += columnWidth(i);
+ setColumnWidth( lastColumn, viewport()->width() - w - 1 );
+ }
+}
+
+void KListView::emitExecute( QListViewItem *item, const QPoint &pos, int c )
+{
+ if( isExecuteArea( viewport()->mapFromGlobal(pos) ) ) {
+ d->validDrag=false;
+
+ // Double click mode ?
+ if ( !d->bUseSingle )
+ {
+ viewport()->unsetCursor();
+ emit executed( item );
+ emit executed( item, pos, c );
+ }
+ else
+ {
+ ButtonState keybstate = KApplication::keyboardMouseState();
+
+ d->autoSelect.stop();
+
+ //Don´t emit executed if in SC mode and Shift or Ctrl are pressed
+ if( !( ((keybstate & Qt::ShiftButton) || (keybstate & Qt::ControlButton)) ) ) {
+ viewport()->unsetCursor();
+ emit executed( item );
+ emit executed( item, pos, c );
+ }
+ }
+ }
+}
+
+void KListView::focusInEvent( QFocusEvent *fe )
+{
+ // kdDebug()<<"KListView::focusInEvent()"<<endl;
+ QListView::focusInEvent( fe );
+ if ((d->selectedBySimpleMove)
+ && (d->selectionMode == FileManager)
+ && (fe->reason()!=QFocusEvent::Popup)
+ && (fe->reason()!=QFocusEvent::ActiveWindow)
+ && (currentItem()))
+ {
+ currentItem()->setSelected(true);
+ currentItem()->repaint();
+ emit selectionChanged();
+ };
+}
+
+void KListView::focusOutEvent( QFocusEvent *fe )
+{
+ cleanDropVisualizer();
+ cleanItemHighlighter();
+
+ d->autoSelect.stop();
+
+ if ((d->selectedBySimpleMove)
+ && (d->selectionMode == FileManager)
+ && (fe->reason()!=QFocusEvent::Popup)
+ && (fe->reason()!=QFocusEvent::ActiveWindow)
+ && (currentItem())
+ && (!d->editor->isVisible()))
+ {
+ currentItem()->setSelected(false);
+ currentItem()->repaint();
+ emit selectionChanged();
+ };
+
+ QListView::focusOutEvent( fe );
+}
+
+void KListView::leaveEvent( QEvent *e )
+{
+ d->autoSelect.stop();
+
+ QListView::leaveEvent( e );
+}
+
+bool KListView::event( QEvent *e )
+{
+ if (e->type() == QEvent::ApplicationPaletteChange)
+ d->alternateBackground=KGlobalSettings::alternateBackgroundColor();
+
+ return QListView::event(e);
+}
+
+void KListView::contentsMousePressEvent( QMouseEvent *e )
+{
+ if( (selectionModeExt() == Extended) && (e->state() & ShiftButton) && !(e->state() & ControlButton) )
+ {
+ bool block = signalsBlocked();
+ blockSignals( true );
+
+ clearSelection();
+
+ blockSignals( block );
+ }
+ else if ((selectionModeExt()==FileManager) && (d->selectedBySimpleMove))
+ {
+ d->selectedBySimpleMove=false;
+ d->selectedUsingMouse=true;
+ if (currentItem())
+ {
+ currentItem()->setSelected(false);
+ currentItem()->repaint();
+// emit selectionChanged();
+ }
+ }
+
+ QPoint p( contentsToViewport( e->pos() ) );
+ QListViewItem *at = itemAt (p);
+
+ // true if the root decoration of the item "at" was clicked (i.e. the +/- sign)
+ bool rootDecoClicked = at
+ && ( p.x() <= header()->cellPos( header()->mapToActual( 0 ) ) +
+ treeStepSize() * ( at->depth() + ( rootIsDecorated() ? 1 : 0) ) + itemMargin() )
+ && ( p.x() >= header()->cellPos( header()->mapToActual( 0 ) ) );
+
+ if (e->button() == LeftButton && !rootDecoClicked)
+ {
+ //Start a drag
+ d->startDragPos = e->pos();
+
+ if (at)
+ {
+ d->validDrag = true;
+ d->pressedOnSelected = at->isSelected();
+ }
+ }
+
+ QListView::contentsMousePressEvent( e );
+}
+
+void KListView::contentsMouseMoveEvent( QMouseEvent *e )
+{
+ if (!dragEnabled() || d->startDragPos.isNull() || !d->validDrag)
+ QListView::contentsMouseMoveEvent (e);
+
+ QPoint vp = contentsToViewport(e->pos());
+ QListViewItem *item = itemAt( vp );
+
+ //do we process cursor changes at all?
+ if ( item && d->bChangeCursorOverItem && d->bUseSingle )
+ {
+ //Cursor moved on a new item or in/out the execute area
+ if( (item != d->pCurrentItem) ||
+ (isExecuteArea(vp) != d->cursorInExecuteArea) )
+ {
+ d->cursorInExecuteArea = isExecuteArea(vp);
+
+ if( d->cursorInExecuteArea ) //cursor moved in execute area
+ viewport()->setCursor( KCursor::handCursor() );
+ else //cursor moved out of execute area
+ viewport()->unsetCursor();
+ }
+ }
+
+ bool dragOn = dragEnabled();
+ QPoint newPos = e->pos();
+ if (dragOn && d->validDrag &&
+ (newPos.x() > d->startDragPos.x()+d->dragDelay ||
+ newPos.x() < d->startDragPos.x()-d->dragDelay ||
+ newPos.y() > d->startDragPos.y()+d->dragDelay ||
+ newPos.y() < d->startDragPos.y()-d->dragDelay))
+ //(d->startDragPos - e->pos()).manhattanLength() > QApplication::startDragDistance())
+ {
+ QListView::contentsMouseReleaseEvent( 0 );
+ startDrag();
+ d->startDragPos = QPoint();
+ d->validDrag = false;
+ }
+}
+
+void KListView::contentsMouseReleaseEvent( QMouseEvent *e )
+{
+ if (e->button() == LeftButton)
+ {
+ // If the row was already selected, maybe we want to start an in-place editing
+ if ( d->pressedOnSelected && itemsRenameable() )
+ {
+ QPoint p( contentsToViewport( e->pos() ) );
+ QListViewItem *at = itemAt (p);
+ if ( at )
+ {
+ // true if the root decoration of the item "at" was clicked (i.e. the +/- sign)
+ bool rootDecoClicked =
+ ( p.x() <= header()->cellPos( header()->mapToActual( 0 ) ) +
+ treeStepSize() * ( at->depth() + ( rootIsDecorated() ? 1 : 0) ) + itemMargin() )
+ && ( p.x() >= header()->cellPos( header()->mapToActual( 0 ) ) );
+
+ if (!rootDecoClicked)
+ {
+ int col = header()->mapToLogical( header()->cellAt( p.x() ) );
+ if ( d->renameable.contains(col) )
+ rename(at, col);
+ }
+ }
+ }
+
+ d->pressedOnSelected = false;
+ d->validDrag = false;
+ d->startDragPos = QPoint();
+ }
+ QListView::contentsMouseReleaseEvent( e );
+}
+
+void KListView::contentsMouseDoubleClickEvent ( QMouseEvent *e )
+{
+ // We don't want to call the parent method because it does setOpen,
+ // whereas we don't do it in single click mode... (David)
+ //QListView::contentsMouseDoubleClickEvent( e );
+ if ( !e || e->button() != LeftButton )
+ return;
+
+ QPoint vp = contentsToViewport(e->pos());
+ QListViewItem *item = itemAt( vp );
+ emit QListView::doubleClicked( item ); // we do it now
+
+ int col = item ? header()->mapToLogical( header()->cellAt( vp.x() ) ) : -1;
+
+ if( item ) {
+ emit doubleClicked( item, e->globalPos(), col );
+
+ if( (e->button() == LeftButton) && !d->bUseSingle )
+ emitExecute( item, e->globalPos(), col );
+ }
+}
+
+void KListView::slotMouseButtonClicked( int btn, QListViewItem *item, const QPoint &pos, int c )
+{
+ if( (btn == LeftButton) && item )
+ emitExecute(item, pos, c);
+}
+
+void KListView::contentsDropEvent(QDropEvent* e)
+{
+ cleanDropVisualizer();
+ cleanItemHighlighter();
+ d->dragExpand.stop();
+
+ if (acceptDrag (e))
+ {
+ e->acceptAction();
+ QListViewItem *afterme;
+ QListViewItem *parent;
+
+ findDrop(e->pos(), parent, afterme);
+
+ if (e->source() == viewport() && itemsMovable())
+ movableDropEvent(parent, afterme);
+ else
+ {
+ emit dropped(e, afterme);
+ emit dropped(this, e, afterme);
+ emit dropped(e, parent, afterme);
+ emit dropped(this, e, parent, afterme);
+ }
+ }
+}
+
+void KListView::movableDropEvent (QListViewItem* parent, QListViewItem* afterme)
+{
+ QPtrList<QListViewItem> items, afterFirsts, afterNows;
+ QListViewItem *current=currentItem();
+ bool hasMoved=false;
+ for (QListViewItem *i = firstChild(), *iNext=0; i; i = iNext)
+ {
+ iNext=i->itemBelow();
+ if (!i->isSelected())
+ continue;
+
+ // don't drop an item after itself, or else
+ // it moves to the top of the list
+ if (i==afterme)
+ continue;
+
+ i->setSelected(false);
+
+ QListViewItem *afterFirst = i->itemAbove();
+
+ if (!hasMoved)
+ {
+ emit aboutToMove();
+ hasMoved=true;
+ }
+
+ moveItem(i, parent, afterme);
+
+ // ###### This should include the new parent !!! -> KDE 3.0
+ // If you need this right now, have a look at keditbookmarks.
+ emit moved(i, afterFirst, afterme);
+
+ items.append (i);
+ afterFirsts.append (afterFirst);
+ afterNows.append (afterme);
+
+ afterme = i;
+ }
+ clearSelection();
+ for (QListViewItem *i=items.first(); i; i=items.next() )
+ i->setSelected(true);
+ if (current)
+ setCurrentItem(current);
+
+ emit moved(items,afterFirsts,afterNows);
+
+ if (firstChild())
+ emit moved();
+}
+
+void KListView::contentsDragMoveEvent(QDragMoveEvent *event)
+{
+ if (acceptDrag(event))
+ {
+ event->acceptAction();
+ //Clean up the view
+
+ findDrop(event->pos(), d->parentItemDrop, d->afterItemDrop);
+ QPoint vp = contentsToViewport( event->pos() );
+ QListViewItem *item = isExecuteArea( vp ) ? itemAt( vp ) : 0L;
+
+ if ( item != d->dragOverItem )
+ {
+ d->dragExpand.stop();
+ d->dragOverItem = item;
+ d->dragOverPoint = vp;
+ if ( d->dragOverItem && d->dragOverItem->isExpandable() && !d->dragOverItem->isOpen() )
+ d->dragExpand.start( QApplication::startDragTime(), true );
+ }
+ if (dropVisualizer())
+ {
+ QRect tmpRect = drawDropVisualizer(0, d->parentItemDrop, d->afterItemDrop);
+ if (tmpRect != d->mOldDropVisualizer)
+ {
+ cleanDropVisualizer();
+ d->mOldDropVisualizer=tmpRect;
+ viewport()->repaint(tmpRect);
+ }
+ }
+ if (dropHighlighter())
+ {
+ QRect tmpRect = drawItemHighlighter(0, itemAt( vp ));
+ if (tmpRect != d->mOldDropHighlighter)
+ {
+ cleanItemHighlighter();
+ d->mOldDropHighlighter=tmpRect;
+ viewport()->repaint(tmpRect);
+ }
+ }
+ }
+ else
+ event->ignore();
+}
+
+void KListView::slotDragExpand()
+{
+ if ( itemAt( d->dragOverPoint ) == d->dragOverItem )
+ d->dragOverItem->setOpen( true );
+}
+
+void KListView::contentsDragLeaveEvent (QDragLeaveEvent*)
+{
+ d->dragExpand.stop();
+ cleanDropVisualizer();
+ cleanItemHighlighter();
+}
+
+void KListView::cleanDropVisualizer()
+{
+ if (d->mOldDropVisualizer.isValid())
+ {
+ QRect rect=d->mOldDropVisualizer;
+ d->mOldDropVisualizer = QRect();
+ viewport()->repaint(rect, true);
+ }
+}
+
+int KListView::depthToPixels( int depth )
+{
+ return treeStepSize() * ( depth + (rootIsDecorated() ? 1 : 0) ) + itemMargin();
+}
+
+void KListView::findDrop(const QPoint &pos, QListViewItem *&parent, QListViewItem *&after)
+{
+ QPoint p (contentsToViewport(pos));
+
+ // Get the position to put it in
+ QListViewItem *atpos = itemAt(p);
+
+ QListViewItem *above;
+ if (!atpos) // put it at the end
+ above = lastItem();
+ else
+ {
+ // Get the closest item before us ('atpos' or the one above, if any)
+ if (p.y() - itemRect(atpos).topLeft().y() < (atpos->height()/2))
+ above = atpos->itemAbove();
+ else
+ above = atpos;
+ }
+
+ if (above)
+ {
+ // if above has children, I might need to drop it as the first item there
+
+ if (above->firstChild() && above->isOpen())
+ {
+ parent = above;
+ after = 0;
+ return;
+ }
+
+ // Now, we know we want to go after "above". But as a child or as a sibling ?
+ // We have to ask the "above" item if it accepts children.
+ if (above->isExpandable())
+ {
+ // The mouse is sufficiently on the right ? - doesn't matter if 'above' has visible children
+ if (p.x() >= depthToPixels( above->depth() + 1 ) ||
+ (above->isOpen() && above->childCount() > 0) )
+ {
+ parent = above;
+ after = 0L;
+ return;
+ }
+ }
+
+ // Ok, there's one more level of complexity. We may want to become a new
+ // sibling, but of an upper-level group, rather than the "above" item
+ QListViewItem * betterAbove = above->parent();
+ QListViewItem * last = above;
+ while ( betterAbove )
+ {
+ // We are allowed to become a sibling of "betterAbove" only if we are
+ // after its last child
+ if ( !last->nextSibling() )
+ {
+ if (p.x() < depthToPixels ( betterAbove->depth() + 1 ))
+ above = betterAbove; // store this one, but don't stop yet, there may be a better one
+ else
+ break; // not enough on the left, so stop
+ last = betterAbove;
+ betterAbove = betterAbove->parent(); // up one level
+ } else
+ break; // we're among the child of betterAbove, not after the last one
+ }
+ }
+ // set as sibling
+ after = above;
+ parent = after ? after->parent() : 0L ;
+}
+
+QListViewItem* KListView::lastChild () const
+{
+ QListViewItem* lastchild = firstChild();
+
+ if (lastchild)
+ for (; lastchild->nextSibling(); lastchild = lastchild->nextSibling());
+
+ return lastchild;
+}
+
+QListViewItem *KListView::lastItem() const
+{
+ QListViewItem* last = lastChild();
+
+ for (QListViewItemIterator it (last); it.current(); ++it)
+ last = it.current();
+
+ return last;
+}
+
+KLineEdit *KListView::renameLineEdit() const
+{
+ return d->editor;
+}
+
+void KListView::startDrag()
+{
+ QDragObject *drag = dragObject();
+
+ if (!drag)
+ return;
+
+ if (drag->drag() && drag->target() != viewport())
+ emit moved();
+}
+
+QDragObject *KListView::dragObject()
+{
+ if (!currentItem())
+ return 0;
+
+
+ return new QStoredDrag("application/x-qlistviewitem", viewport());
+}
+
+void KListView::setItemsMovable(bool b)
+{
+ d->itemsMovable=b;
+}
+
+bool KListView::itemsMovable() const
+{
+ return d->itemsMovable;
+}
+
+void KListView::setItemsRenameable(bool b)
+{
+ d->itemsRenameable=b;
+}
+
+bool KListView::itemsRenameable() const
+{
+ return d->itemsRenameable;
+}
+
+
+void KListView::setDragEnabled(bool b)
+{
+ d->dragEnabled=b;
+}
+
+bool KListView::dragEnabled() const
+{
+ return d->dragEnabled;
+}
+
+void KListView::setAutoOpen(bool b)
+{
+ d->autoOpen=b;
+}
+
+bool KListView::autoOpen() const
+{
+ return d->autoOpen;
+}
+
+bool KListView::dropVisualizer() const
+{
+ return d->dropVisualizer;
+}
+
+void KListView::setDropVisualizer(bool b)
+{
+ d->dropVisualizer=b;
+}
+
+QPtrList<QListViewItem> KListView::selectedItems() const
+{
+ return selectedItems(true);
+}
+
+QPtrList<QListViewItem> KListView::selectedItems(bool includeHiddenItems) const
+{
+ QPtrList<QListViewItem> list;
+
+ // Using selectionMode() instead of selectionModeExt() since for the cases that
+ // we're interested in selectionMode() should work for either variety of the
+ // setSelectionMode().
+
+ switch(selectionMode())
+ {
+ case NoSelection:
+ break;
+ case Single:
+ if(selectedItem() && (includeHiddenItems || selectedItem()->isVisible()))
+ list.append(selectedItem());
+ break;
+ default:
+ {
+ int flags = QListViewItemIterator::Selected;
+ if (!includeHiddenItems)
+ {
+ flags |= QListViewItemIterator::Visible;
+ }
+
+ QListViewItemIterator it(const_cast<KListView *>(this), flags);
+
+ for(; it.current(); ++it)
+ list.append(it.current());
+
+ break;
+ }
+ }
+
+ return list;
+}
+
+
+void KListView::moveItem(QListViewItem *item, QListViewItem *parent, QListViewItem *after)
+{
+ // sanity check - don't move a item into its own child structure
+ QListViewItem *i = parent;
+ while(i)
+ {
+ if(i == item)
+ return;
+ i = i->parent();
+ }
+
+ if (after)
+ {
+ item->moveItem(after);
+ return;
+ }
+
+ // Basically reimplementing the QListViewItem(QListViewItem*, QListViewItem*) constructor
+ // in here, without ever deleting the item.
+ if (item->parent())
+ item->parent()->takeItem(item);
+ else
+ takeItem(item);
+
+ if (parent)
+ parent->insertItem(item);
+ else
+ insertItem(item);
+}
+
+void KListView::contentsDragEnterEvent(QDragEnterEvent *event)
+{
+ if (acceptDrag (event))
+ event->accept();
+}
+
+void KListView::setDropVisualizerWidth (int w)
+{
+ d->mDropVisualizerWidth = w > 0 ? w : 1;
+}
+
+QRect KListView::drawDropVisualizer(QPainter *p, QListViewItem *parent,
+ QListViewItem *after)
+{
+ QRect insertmarker;
+
+ if (!after && !parent)
+ insertmarker = QRect (0, 0, viewport()->width(), d->mDropVisualizerWidth/2);
+ else
+ {
+ int level = 0;
+ if (after)
+ {
+ QListViewItem* it = 0L;
+ if (after->isOpen())
+ {
+ // Look for the last child (recursively)
+ it = after->firstChild();
+ if (it)
+ while (it->nextSibling() || it->firstChild())
+ if ( it->nextSibling() )
+ it = it->nextSibling();
+ else
+ it = it->firstChild();
+ }
+
+ insertmarker = itemRect (it ? it : after);
+ level = after->depth();
+ }
+ else if (parent)
+ {
+ insertmarker = itemRect (parent);
+ level = parent->depth() + 1;
+ }
+ insertmarker.setLeft( treeStepSize() * ( level + (rootIsDecorated() ? 1 : 0) ) + itemMargin() );
+ insertmarker.setRight (viewport()->width());
+ insertmarker.setTop (insertmarker.bottom() - d->mDropVisualizerWidth/2 + 1);
+ insertmarker.setBottom (insertmarker.bottom() + d->mDropVisualizerWidth/2);
+ }
+
+ // This is not used anymore, at least by KListView itself (see viewportPaintEvent)
+ // Remove for KDE 4.0.
+ if (p)
+ p->fillRect(insertmarker, Dense4Pattern);
+
+ return insertmarker;
+}
+
+QRect KListView::drawItemHighlighter(QPainter *painter, QListViewItem *item)
+{
+ QRect r;
+
+ if (item)
+ {
+ r = itemRect(item);
+ r.setLeft(r.left()+(item->depth()+(rootIsDecorated() ? 1 : 0))*treeStepSize());
+ if (painter)
+ style().drawPrimitive(QStyle::PE_FocusRect, painter, r, colorGroup(),
+ QStyle::Style_FocusAtBorder, colorGroup().highlight());
+ }
+
+ return r;
+}
+
+void KListView::cleanItemHighlighter ()
+{
+ if (d->mOldDropHighlighter.isValid())
+ {
+ QRect rect=d->mOldDropHighlighter;
+ d->mOldDropHighlighter = QRect();
+ viewport()->repaint(rect, true);
+ }
+}
+
+void KListView::rename(QListViewItem *item, int c)
+{
+ if (d->renameable.contains(c))
+ {
+ ensureItemVisible(item);
+ d->editor->load(item,c);
+ }
+}
+
+bool KListView::isRenameable (int col) const
+{
+ return d->renameable.contains(col);
+}
+
+void KListView::setRenameable (int col, bool renameable)
+{
+ if (col>=header()->count()) return;
+
+ d->renameable.remove(col);
+ if (renameable)
+ d->renameable+=col;
+}
+
+void KListView::doneEditing(QListViewItem *item, int row)
+{
+ emit itemRenamed(item, item->text(row), row);
+ emit itemRenamed(item);
+}
+
+bool KListView::acceptDrag(QDropEvent* e) const
+{
+ return acceptDrops() && itemsMovable() && (e->source()==viewport());
+}
+
+void KListView::setCreateChildren(bool b)
+{
+ d->createChildren=b;
+}
+
+bool KListView::createChildren() const
+{
+ return d->createChildren;
+}
+
+
+int KListView::tooltipColumn() const
+{
+ return d->tooltipColumn;
+}
+
+void KListView::setTooltipColumn(int column)
+{
+ d->tooltipColumn=column;
+}
+
+void KListView::setDropHighlighter(bool b)
+{
+ d->dropHighlighter=b;
+}
+
+bool KListView::dropHighlighter() const
+{
+ return d->dropHighlighter;
+}
+
+bool KListView::showTooltip(QListViewItem *item, const QPoint &, int column) const
+{
+ return ((column==tooltipColumn()) && !tooltip(item, column).isEmpty());
+}
+
+QString KListView::tooltip(QListViewItem *item, int column) const
+{
+ return item->text(column);
+}
+
+void KListView::setTabOrderedRenaming(bool b)
+{
+ d->tabRename = b;
+}
+
+bool KListView::tabOrderedRenaming() const
+{
+ return d->tabRename;
+}
+
+void KListView::keyPressEvent (QKeyEvent* e)
+{
+ //don't we need a contextMenuModifier too ? (aleXXX)
+ if (e->key() == d->contextMenuKey)
+ {
+ emit menuShortCutPressed (this, currentItem());
+ return;
+ }
+
+ if (d->selectionMode != FileManager)
+ QListView::keyPressEvent (e);
+ else
+ fileManagerKeyPressEvent (e);
+}
+
+void KListView::activateAutomaticSelection()
+{
+ d->selectedBySimpleMove=true;
+ d->selectedUsingMouse=false;
+ if (currentItem())
+ {
+ currentItem()->setSelected(true);
+ currentItem()->repaint();
+ emit selectionChanged();
+ };
+}
+
+void KListView::deactivateAutomaticSelection()
+{
+ d->selectedBySimpleMove=false;
+}
+
+bool KListView::automaticSelection() const
+{
+ return d->selectedBySimpleMove;
+}
+
+void KListView::fileManagerKeyPressEvent (QKeyEvent* e)
+{
+ //don't care whether it's on the keypad or not
+ int e_state=(e->state() & ~Keypad);
+
+ int oldSelectionDirection(d->selectionDirection);
+
+ if ((e->key()!=Key_Shift) && (e->key()!=Key_Control)
+ && (e->key()!=Key_Meta) && (e->key()!=Key_Alt))
+ {
+ if ((e_state==ShiftButton) && (!d->wasShiftEvent) && (!d->selectedBySimpleMove))
+ selectAll(false);
+ d->selectionDirection=0;
+ d->wasShiftEvent = (e_state == ShiftButton);
+ };
+
+ //d->wasShiftEvent = (e_state == ShiftButton);
+
+
+ QListViewItem* item = currentItem();
+ if (!item) return;
+
+ QListViewItem* repaintItem1 = item;
+ QListViewItem* repaintItem2 = 0L;
+ QListViewItem* visItem = 0L;
+
+ QListViewItem* nextItem = 0L;
+ int items = 0;
+
+ bool shiftOrCtrl((e_state==ControlButton) || (e_state==ShiftButton));
+ int selectedItems(0);
+ for (QListViewItem *tmpItem=firstChild(); tmpItem; tmpItem=tmpItem->nextSibling())
+ if (tmpItem->isSelected()) selectedItems++;
+
+ if (((!selectedItems) || ((selectedItems==1) && (d->selectedUsingMouse)))
+ && (e_state==NoButton)
+ && ((e->key()==Key_Down)
+ || (e->key()==Key_Up)
+ || (e->key()==Key_Next)
+ || (e->key()==Key_Prior)
+ || (e->key()==Key_Home)
+ || (e->key()==Key_End)))
+ {
+ d->selectedBySimpleMove=true;
+ d->selectedUsingMouse=false;
+ }
+ else if (selectedItems>1)
+ d->selectedBySimpleMove=false;
+
+ bool emitSelectionChanged(false);
+
+ switch (e->key())
+ {
+ case Key_Escape:
+ selectAll(false);
+ emitSelectionChanged=true;
+ break;
+
+ case Key_Space:
+ //toggle selection of current item
+ if (d->selectedBySimpleMove)
+ d->selectedBySimpleMove=false;
+ item->setSelected(!item->isSelected());
+ emitSelectionChanged=true;
+ break;
+
+ case Key_Insert:
+ //toggle selection of current item and move to the next item
+ if (d->selectedBySimpleMove)
+ {
+ d->selectedBySimpleMove=false;
+ if (!item->isSelected()) item->setSelected(true);
+ }
+ else
+ {
+ item->setSelected(!item->isSelected());
+ };
+
+ nextItem=item->itemBelow();
+
+ if (nextItem)
+ {
+ repaintItem2=nextItem;
+ visItem=nextItem;
+ setCurrentItem(nextItem);
+ };
+ d->selectionDirection=1;
+ emitSelectionChanged=true;
+ break;
+
+ case Key_Down:
+ nextItem=item->itemBelow();
+ //toggle selection of current item and move to the next item
+ if (shiftOrCtrl)
+ {
+ d->selectionDirection=1;
+ if (d->selectedBySimpleMove)
+ d->selectedBySimpleMove=false;
+ else
+ {
+ if (oldSelectionDirection!=-1)
+ {
+ item->setSelected(!item->isSelected());
+ emitSelectionChanged=true;
+ };
+ };
+ }
+ else if ((d->selectedBySimpleMove) && (nextItem))
+ {
+ item->setSelected(false);
+ emitSelectionChanged=true;
+ };
+
+ if (nextItem)
+ {
+ if (d->selectedBySimpleMove)
+ nextItem->setSelected(true);
+ repaintItem2=nextItem;
+ visItem=nextItem;
+ setCurrentItem(nextItem);
+ };
+ break;
+
+ case Key_Up:
+ nextItem=item->itemAbove();
+ d->selectionDirection=-1;
+ //move to the prev. item and toggle selection of this one
+ // => No, can't select the last item, with this. For symmetry, let's
+ // toggle selection and THEN move up, just like we do in down (David)
+ if (shiftOrCtrl)
+ {
+ if (d->selectedBySimpleMove)
+ d->selectedBySimpleMove=false;
+ else
+ {
+ if (oldSelectionDirection!=1)
+ {
+ item->setSelected(!item->isSelected());
+ emitSelectionChanged=true;
+ };
+ }
+ }
+ else if ((d->selectedBySimpleMove) && (nextItem))
+ {
+ item->setSelected(false);
+ emitSelectionChanged=true;
+ };
+
+ if (nextItem)
+ {
+ if (d->selectedBySimpleMove)
+ nextItem->setSelected(true);
+ repaintItem2=nextItem;
+ visItem=nextItem;
+ setCurrentItem(nextItem);
+ };
+ break;
+
+ case Key_End:
+ //move to the last item and toggle selection of all items inbetween
+ nextItem=item;
+ if (d->selectedBySimpleMove)
+ item->setSelected(false);
+ if (shiftOrCtrl)
+ d->selectedBySimpleMove=false;
+
+ while(nextItem)
+ {
+ if (shiftOrCtrl)
+ nextItem->setSelected(!nextItem->isSelected());
+ if (!nextItem->itemBelow())
+ {
+ if (d->selectedBySimpleMove)
+ nextItem->setSelected(true);
+ repaintItem2=nextItem;
+ visItem=nextItem;
+ setCurrentItem(nextItem);
+ }
+ nextItem=nextItem->itemBelow();
+ }
+ emitSelectionChanged=true;
+ break;
+
+ case Key_Home:
+ // move to the first item and toggle selection of all items inbetween
+ nextItem = firstChild();
+ visItem = nextItem;
+ repaintItem2 = visItem;
+ if (d->selectedBySimpleMove)
+ item->setSelected(false);
+ if (shiftOrCtrl)
+ {
+ d->selectedBySimpleMove=false;
+
+ while ( nextItem != item )
+ {
+ nextItem->setSelected( !nextItem->isSelected() );
+ nextItem = nextItem->itemBelow();
+ }
+ item->setSelected( !item->isSelected() );
+ }
+ setCurrentItem( firstChild() );
+ emitSelectionChanged=true;
+ break;
+
+ case Key_Next:
+ items=visibleHeight()/item->height();
+ nextItem=item;
+ if (d->selectedBySimpleMove)
+ item->setSelected(false);
+ if (shiftOrCtrl)
+ {
+ d->selectedBySimpleMove=false;
+ d->selectionDirection=1;
+ };
+
+ for (int i=0; i<items; i++)
+ {
+ if (shiftOrCtrl)
+ nextItem->setSelected(!nextItem->isSelected());
+ //the end
+ if ((i==items-1) || (!nextItem->itemBelow()))
+
+ {
+ if (shiftOrCtrl)
+ nextItem->setSelected(!nextItem->isSelected());
+ if (d->selectedBySimpleMove)
+ nextItem->setSelected(true);
+ ensureItemVisible(nextItem);
+ setCurrentItem(nextItem);
+ update();
+ if ((shiftOrCtrl) || (d->selectedBySimpleMove))
+ {
+ emit selectionChanged();
+ }
+ return;
+ }
+ nextItem=nextItem->itemBelow();
+ }
+ break;
+
+ case Key_Prior:
+ items=visibleHeight()/item->height();
+ nextItem=item;
+ if (d->selectedBySimpleMove)
+ item->setSelected(false);
+ if (shiftOrCtrl)
+ {
+ d->selectionDirection=-1;
+ d->selectedBySimpleMove=false;
+ };
+
+ for (int i=0; i<items; i++)
+ {
+ if ((nextItem!=item) &&(shiftOrCtrl))
+ nextItem->setSelected(!nextItem->isSelected());
+ //the end
+ if ((i==items-1) || (!nextItem->itemAbove()))
+
+ {
+ if (d->selectedBySimpleMove)
+ nextItem->setSelected(true);
+ ensureItemVisible(nextItem);
+ setCurrentItem(nextItem);
+ update();
+ if ((shiftOrCtrl) || (d->selectedBySimpleMove))
+ {
+ emit selectionChanged();
+ }
+ return;
+ }
+ nextItem=nextItem->itemAbove();
+ }
+ break;
+
+ case Key_Minus:
+ if ( item->isOpen() )
+ setOpen( item, false );
+ break;
+ case Key_Plus:
+ if ( !item->isOpen() && (item->isExpandable() || item->childCount()) )
+ setOpen( item, true );
+ break;
+ default:
+ bool realKey = ((e->key()!=Key_Shift) && (e->key()!=Key_Control)
+ && (e->key()!=Key_Meta) && (e->key()!=Key_Alt));
+
+ bool selectCurrentItem = (d->selectedBySimpleMove) && (item->isSelected());
+ if (realKey && selectCurrentItem)
+ item->setSelected(false);
+ //this is mainly for the "goto filename beginning with pressed char" feature (aleXXX)
+ QListView::SelectionMode oldSelectionMode = selectionMode();
+ setSelectionMode (QListView::Multi);
+ QListView::keyPressEvent (e);
+ setSelectionMode (oldSelectionMode);
+ if (realKey && selectCurrentItem)
+ {
+ currentItem()->setSelected(true);
+ emitSelectionChanged=true;
+ }
+ repaintItem2=currentItem();
+ if (realKey)
+ visItem=currentItem();
+ break;
+ }
+
+ if (visItem)
+ ensureItemVisible(visItem);
+
+ QRect ir;
+ if (repaintItem1)
+ ir = ir.unite( itemRect(repaintItem1) );
+ if (repaintItem2)
+ ir = ir.unite( itemRect(repaintItem2) );
+
+ if ( !ir.isEmpty() )
+ { // rectangle to be repainted
+ if ( ir.x() < 0 )
+ ir.moveBy( -ir.x(), 0 );
+ viewport()->repaint( ir, false );
+ }
+ /*if (repaintItem1)
+ repaintItem1->repaint();
+ if (repaintItem2)
+ repaintItem2->repaint();*/
+ update();
+ if (emitSelectionChanged)
+ emit selectionChanged();
+}
+
+void KListView::setSelectionModeExt (SelectionModeExt mode)
+{
+ d->selectionMode = mode;
+
+ switch (mode)
+ {
+ case Single:
+ case Multi:
+ case Extended:
+ case NoSelection:
+ setSelectionMode (static_cast<QListView::SelectionMode>(static_cast<int>(mode)));
+ break;
+
+ case FileManager:
+ setSelectionMode (QListView::Extended);
+ break;
+
+ default:
+ kdWarning () << "Warning: illegal selection mode " << int(mode) << " set!" << endl;
+ break;
+ }
+}
+
+KListView::SelectionModeExt KListView::selectionModeExt () const
+{
+ return d->selectionMode;
+}
+
+int KListView::itemIndex( const QListViewItem *item ) const
+{
+ if ( !item )
+ return -1;
+
+ if ( item == firstChild() )
+ return 0;
+ else {
+ QListViewItemIterator it(firstChild());
+ uint j = 0;
+ for (; it.current() && it.current() != item; ++it, ++j );
+
+ if( !it.current() )
+ return -1;
+
+ return j;
+ }
+}
+
+QListViewItem* KListView::itemAtIndex(int index)
+{
+ if (index<0)
+ return 0;
+
+ int j(0);
+ for (QListViewItemIterator it=firstChild(); it.current(); ++it)
+ {
+ if (j==index)
+ return it.current();
+ ++j;
+ };
+ return 0;
+}
+
+
+void KListView::emitContextMenu (KListView*, QListViewItem* i)
+{
+ QPoint p;
+
+ if (i)
+ p = viewport()->mapToGlobal(itemRect(i).center());
+ else
+ p = mapToGlobal(rect().center());
+
+ emit contextMenu (this, i, p);
+}
+
+void KListView::emitContextMenu (QListViewItem* i, const QPoint& p, int)
+{
+ emit contextMenu (this, i, p);
+}
+
+void KListView::setAcceptDrops (bool val)
+{
+ QListView::setAcceptDrops (val);
+ viewport()->setAcceptDrops (val);
+}
+
+int KListView::dropVisualizerWidth () const
+{
+ return d->mDropVisualizerWidth;
+}
+
+
+void KListView::viewportPaintEvent(QPaintEvent *e)
+{
+ d->paintAbove = 0;
+ d->paintCurrent = 0;
+ d->paintBelow = 0;
+ d->painting = true;
+
+ QListView::viewportPaintEvent(e);
+
+ if (d->mOldDropVisualizer.isValid() && e->rect().intersects(d->mOldDropVisualizer))
+ {
+ QPainter painter(viewport());
+
+ // This is where we actually draw the drop-visualizer
+ painter.fillRect(d->mOldDropVisualizer, Dense4Pattern);
+ }
+ if (d->mOldDropHighlighter.isValid() && e->rect().intersects(d->mOldDropHighlighter))
+ {
+ QPainter painter(viewport());
+
+ // This is where we actually draw the drop-highlighter
+ style().drawPrimitive(QStyle::PE_FocusRect, &painter, d->mOldDropHighlighter, colorGroup(),
+ QStyle::Style_FocusAtBorder);
+ }
+ d->painting = false;
+}
+
+void KListView::setFullWidth()
+{
+ setFullWidth(true);
+}
+
+void KListView::setFullWidth(bool fullWidth)
+{
+ d->fullWidth = fullWidth;
+ header()->setStretchEnabled(fullWidth, columns()-1);
+}
+
+bool KListView::fullWidth() const
+{
+ return d->fullWidth;
+}
+
+int KListView::addColumn(const QString& label, int width)
+{
+ int result = QListView::addColumn(label, width);
+ if (d->fullWidth) {
+ header()->setStretchEnabled(false, columns()-2);
+ header()->setStretchEnabled(true, columns()-1);
+ }
+ return result;
+}
+
+int KListView::addColumn(const QIconSet& iconset, const QString& label, int width)
+{
+ int result = QListView::addColumn(iconset, label, width);
+ if (d->fullWidth) {
+ header()->setStretchEnabled(false, columns()-2);
+ header()->setStretchEnabled(true, columns()-1);
+ }
+ return result;
+}
+
+void KListView::removeColumn(int index)
+{
+ QListView::removeColumn(index);
+ if (d->fullWidth && index == columns()) header()->setStretchEnabled(true, columns()-1);
+}
+
+void KListView::viewportResizeEvent(QResizeEvent* e)
+{
+ QListView::viewportResizeEvent(e);
+}
+
+const QColor &KListView::alternateBackground() const
+{
+ return d->alternateBackground;
+}
+
+void KListView::setAlternateBackground(const QColor &c)
+{
+ d->alternateBackground = c;
+ repaint();
+}
+
+void KListView::setShadeSortColumn(bool shadeSortColumn)
+{
+ d->shadeSortColumn = shadeSortColumn;
+ repaint();
+}
+
+bool KListView::shadeSortColumn() const
+{
+ return d->shadeSortColumn;
+}
+
+void KListView::saveLayout(KConfig *config, const QString &group) const
+{
+ KConfigGroupSaver saver(config, group);
+ QStringList widths, order;
+
+ const int colCount = columns();
+ QHeader* const thisHeader = header();
+ for (int i = 0; i < colCount; ++i)
+ {
+ widths << QString::number(columnWidth(i));
+ order << QString::number(thisHeader->mapToIndex(i));
+ }
+ config->writeEntry("ColumnWidths", widths);
+ config->writeEntry("ColumnOrder", order);
+ config->writeEntry("SortColumn", d->sortColumn);
+ config->writeEntry("SortAscending", d->sortAscending);
+}
+
+void KListView::restoreLayout(KConfig *config, const QString &group)
+{
+ KConfigGroupSaver saver(config, group);
+ QStringList cols = config->readListEntry("ColumnWidths");
+ int i = 0;
+ { // scope the iterators
+ QStringList::ConstIterator it = cols.constBegin();
+ const QStringList::ConstIterator itEnd = cols.constEnd();
+ for (; it != itEnd; ++it)
+ setColumnWidth(i++, (*it).toInt());
+ }
+
+ // move sections in the correct sequence: from lowest to highest index position
+ // otherwise we move a section from an index, which modifies
+ // all index numbers to the right of the moved one
+ cols = config->readListEntry("ColumnOrder");
+ const int colCount = columns();
+ for (i = 0; i < colCount; ++i) // final index positions from lowest to highest
+ {
+ QStringList::ConstIterator it = cols.constBegin();
+ const QStringList::ConstIterator itEnd = cols.constEnd();
+
+ int section = 0;
+ for (; (it != itEnd) && ((*it).toInt() != i); ++it, ++section) ;
+
+ if ( it != itEnd ) {
+ // found the section to move to position i
+ header()->moveSection(section, i);
+ }
+ }
+
+ if (config->hasKey("SortColumn"))
+ setSorting(config->readNumEntry("SortColumn"), config->readBoolEntry("SortAscending", true));
+}
+
+void KListView::setSorting(int column, bool ascending)
+{
+ QListViewItem *selected = 0;
+
+ if (selectionMode() == QListView::Single) {
+ selected = selectedItem();
+ if (selected && !selected->isVisible())
+ selected = 0;
+ }
+ else if (selectionMode() != QListView::NoSelection) {
+ QListViewItem *item = firstChild();
+ while (item && !selected) {
+ if (item->isSelected() && item->isVisible())
+ selected = item;
+ item = item->itemBelow();
+ }
+ }
+
+ d->sortColumn = column;
+ d->sortAscending = ascending;
+ QListView::setSorting(column, ascending);
+
+ if (selected)
+ ensureItemVisible(selected);
+
+ QListViewItem* item = firstChild();
+ while ( item ) {
+ KListViewItem *kItem = dynamic_cast<KListViewItem*>(item);
+ if (kItem) kItem->m_known = false;
+ item = item->itemBelow();
+ }
+}
+
+int KListView::columnSorted(void) const
+{
+ return d->sortColumn;
+}
+
+bool KListView::ascendingSort(void) const
+{
+ return d->sortAscending;
+}
+
+void KListView::takeItem(QListViewItem *item)
+{
+ if(item && item == d->editor->currentItem())
+ d->editor->terminate();
+
+ QListView::takeItem(item);
+}
+
+void KListView::disableAutoSelection()
+{
+ if ( d->disableAutoSelection )
+ return;
+
+ d->disableAutoSelection = true;
+ d->autoSelect.stop();
+ d->autoSelectDelay = -1;
+}
+
+void KListView::resetAutoSelection()
+{
+ if ( !d->disableAutoSelection )
+ return;
+
+ d->disableAutoSelection = false;
+ d->autoSelectDelay = KGlobalSettings::autoSelectDelay();
+}
+
+void KListView::doubleClicked( QListViewItem *item, const QPoint &pos, int c )
+{
+ emit QListView::doubleClicked( item, pos, c );
+}
+
+KListViewItem::KListViewItem(QListView *parent)
+ : QListViewItem(parent)
+{
+ init();
+}
+
+KListViewItem::KListViewItem(QListViewItem *parent)
+ : QListViewItem(parent)
+{
+ init();
+}
+
+KListViewItem::KListViewItem(QListView *parent, QListViewItem *after)
+ : QListViewItem(parent, after)
+{
+ init();
+}
+
+KListViewItem::KListViewItem(QListViewItem *parent, QListViewItem *after)
+ : QListViewItem(parent, after)
+{
+ init();
+}
+
+KListViewItem::KListViewItem(QListView *parent,
+ QString label1, QString label2, QString label3, QString label4,
+ QString label5, QString label6, QString label7, QString label8)
+ : QListViewItem(parent, label1, label2, label3, label4, label5, label6, label7, label8)
+{
+ init();
+}
+
+KListViewItem::KListViewItem(QListViewItem *parent,
+ QString label1, QString label2, QString label3, QString label4,
+ QString label5, QString label6, QString label7, QString label8)
+ : QListViewItem(parent, label1, label2, label3, label4, label5, label6, label7, label8)
+{
+ init();
+}
+
+KListViewItem::KListViewItem(QListView *parent, QListViewItem *after,
+ QString label1, QString label2, QString label3, QString label4,
+ QString label5, QString label6, QString label7, QString label8)
+ : QListViewItem(parent, after, label1, label2, label3, label4, label5, label6, label7, label8)
+{
+ init();
+}
+
+KListViewItem::KListViewItem(QListViewItem *parent, QListViewItem *after,
+ QString label1, QString label2, QString label3, QString label4,
+ QString label5, QString label6, QString label7, QString label8)
+ : QListViewItem(parent, after, label1, label2, label3, label4, label5, label6, label7, label8)
+{
+ init();
+}
+
+KListViewItem::~KListViewItem()
+{
+ if(listView())
+ emit static_cast<KListView *>(listView())->itemRemoved(this);
+}
+
+void KListViewItem::init()
+{
+ m_odd = m_known = false;
+ KListView *lv = static_cast<KListView *>(listView());
+ setDragEnabled( dragEnabled() || lv->dragEnabled() );
+ emit lv->itemAdded(this);
+}
+
+void KListViewItem::insertItem(QListViewItem *item)
+{
+ QListViewItem::insertItem(item);
+ if(listView())
+ emit static_cast<KListView *>(listView())->itemAdded(item);
+}
+
+void KListViewItem::takeItem(QListViewItem *item)
+{
+ QListViewItem::takeItem(item);
+ if(listView())
+ emit static_cast<KListView *>(listView())->itemRemoved(item);
+}
+
+const QColor &KListViewItem::backgroundColor()
+{
+ if (isAlternate())
+ return static_cast< KListView* >(listView())->alternateBackground();
+ return listView()->viewport()->colorGroup().base();
+}
+
+QColor KListViewItem::backgroundColor(int column)
+{
+ KListView* view = static_cast< KListView* >(listView());
+ QColor color = isAlternate() ?
+ view->alternateBackground() :
+ view->viewport()->colorGroup().base();
+
+ // calculate a different color if the current column is sorted (only if more than 1 column)
+ if ( (view->columns() > 1) && view->shadeSortColumn() && (column == view->columnSorted()) )
+ {
+ if ( color == Qt::black )
+ color = QColor(55, 55, 55); // dark gray
+ else
+ {
+ int h,s,v;
+ color.hsv(&h, &s, &v);
+ if ( v > 175 )
+ color = color.dark(104);
+ else
+ color = color.light(120);
+ }
+ }
+
+ return color;
+}
+
+bool KListViewItem::isAlternate()
+{
+ KListView* const lv = static_cast<KListView *>(listView());
+ if (lv && lv->alternateBackground().isValid())
+ {
+ KListViewItem *above;
+
+ KListView::KListViewPrivate* const lvD = lv->d;
+
+ // Ok, there's some weirdness here that requires explanation as this is a
+ // speed hack. itemAbove() is a O(n) operation (though this isn't
+ // immediately clear) so we want to call it as infrequently as possible --
+ // especially in the case of painting a cell.
+ //
+ // So, in the case that we *are* painting a cell: (1) we're assuming that
+ // said painting is happening top to bottem -- this assumption is present
+ // elsewhere in the implementation of this class, (2) itemBelow() is fast --
+ // roughly constant time.
+ //
+ // Given these assumptions we can do a mixture of caching and telling the
+ // next item that the when that item is the current item that the now
+ // current item will be the item above it.
+ //
+ // Ideally this will make checking to see if the item above the current item
+ // is the alternate color a constant time operation rather than 0(n).
+
+ if (lvD->painting) {
+ if (lvD->paintCurrent != this)
+ {
+ lvD->paintAbove = lvD->paintBelow == this ? lvD->paintCurrent : itemAbove();
+ lvD->paintCurrent = this;
+ lvD->paintBelow = itemBelow();
+ }
+
+ above = dynamic_cast<KListViewItem *>(lvD->paintAbove);
+ }
+ else
+ {
+ above = dynamic_cast<KListViewItem *>(itemAbove());
+ }
+
+ m_known = above ? above->m_known : true;
+ if (m_known)
+ {
+ m_odd = above ? !above->m_odd : false;
+ }
+ else
+ {
+ KListViewItem *item;
+ bool previous = true;
+ if (parent())
+ {
+ item = dynamic_cast<KListViewItem *>(parent());
+ if (item)
+ previous = item->m_odd;
+ item = dynamic_cast<KListViewItem *>(parent()->firstChild());
+ }
+ else
+ {
+ item = dynamic_cast<KListViewItem *>(lv->firstChild());
+ }
+
+ while(item)
+ {
+ previous = !previous;
+ item->m_odd = previous;
+ item->m_known = true;
+ item = dynamic_cast<KListViewItem *>(item->nextSibling());
+ }
+ }
+ return m_odd;
+ }
+ return false;
+}
+
+void KListViewItem::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment)
+{
+ QColorGroup _cg = cg;
+ QListView* lv = listView();
+ const QPixmap *pm = lv->viewport()->backgroundPixmap();
+
+ if (pm && !pm->isNull())
+ {
+ _cg.setBrush(QColorGroup::Base, QBrush(backgroundColor(column), *pm));
+ QPoint o = p->brushOrigin();
+ p->setBrushOrigin( o.x()-lv->contentsX(), o.y()-lv->contentsY() );
+ }
+ else
+ {
+ _cg.setColor((lv->viewport()->backgroundMode() == Qt::FixedColor) ?
+ QColorGroup::Background : QColorGroup::Base,
+ backgroundColor(column));
+ }
+ QListViewItem::paintCell(p, _cg, column, width, alignment);
+}
+
+void KListView::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "klistview.moc"
+#include "klistviewlineedit.moc"
+
+// vim: noet
diff --git a/kdeui/klistview.h b/kdeui/klistview.h
new file mode 100644
index 000000000..a2300f02e
--- /dev/null
+++ b/kdeui/klistview.h
@@ -0,0 +1,1085 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2000 Charles Samuels <charles@kde.org>
+ Copyright (C) 2000 Peter Putzer <putzer@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef KLISTVIEW_H
+#define KLISTVIEW_H
+
+#include <qlistview.h>
+
+#include <qptrlist.h>
+#include <kdelibs_export.h>
+
+class QDragObject;
+class KConfig;
+class KLineEdit;
+/**
+ * This Widget extends the functionality of QListView to honor the system
+ * wide settings for Single Click/Double Click mode, AutoSelection and
+ * ChangeCursorOverLink (TM).
+ *
+ * There is a new signal executed(). It gets connected to either
+ * QListView::clicked() or QListView::doubleClicked() depending on the KDE
+ * wide Single Click/Double Click settings. It is strongly recommended that
+ * you use this signal instead of the above mentioned. This way you don´t
+ * need to care about the current settings.
+ * If you want to get informed when the user selects something connect to the
+ * QListView::selectionChanged() signal.
+ *
+ * Drag-and-Drop is supported with the signal dropped(), just setAcceptDrops(true)
+ * and connect it to a suitable slot.
+ * To see where you are dropping, setDropVisualizer(true).
+ * And also you'll need acceptDrag(QDropEvent*)
+ *
+ * KListView is drag-enabled, too: to benefit from that you have to derive from it.
+ * Reimplement dragObject() and (possibly) startDrag(),
+ * and setDragEnabled(true).
+ */
+class KDEUI_EXPORT KListView : public QListView
+{
+ friend class KListViewItem;
+
+ Q_OBJECT
+ Q_ENUMS( SelectionModeExt )
+ Q_PROPERTY( bool fullWidth READ fullWidth WRITE setFullWidth )
+ Q_PROPERTY( bool itemsMovable READ itemsMovable WRITE setItemsMovable )
+ Q_PROPERTY( bool itemsRenameable READ itemsRenameable WRITE setItemsRenameable )
+ Q_PROPERTY( bool dragEnabled READ dragEnabled WRITE setDragEnabled )
+ Q_PROPERTY( bool autoOpen READ autoOpen WRITE setAutoOpen )
+ Q_PROPERTY( bool dropVisualizer READ dropVisualizer WRITE setDropVisualizer )
+ Q_PROPERTY( int tooltipColumn READ tooltipColumn WRITE setTooltipColumn )
+ Q_PROPERTY( int dropVisualizerWidth READ dropVisualizerWidth WRITE setDropVisualizerWidth )
+ Q_PROPERTY( QColor alternateBackground READ alternateBackground WRITE setAlternateBackground )
+ Q_PROPERTY( bool shadeSortColumn READ shadeSortColumn WRITE setShadeSortColumn )
+
+ Q_OVERRIDE( SelectionModeExt selectionMode READ selectionModeExt WRITE setSelectionModeExt )
+
+public:
+ /**
+ * Possible selection modes.
+ *
+ * The first four correspond directly to QListView::SelectionMode, while
+ * the FileManager selection mode is defined as follows:
+ * @li home: move to the first
+ * @li end: move to the last
+ * @li PgUp/PgDn: move one page up/down
+ * @li up/down: move one item up/down
+ * @li insert: toggle selection of current and move to the next
+ * @li space: toggle selection of the current
+ * @li CTRL+up: move to the previous item and toggle selection of this one
+ * @li CTRL+down: toggle selection of the current item and move to the next
+ * @li CTRL+end: toggle selection from (including) the current
+ * item to (including) the last item
+ * @li CTRL+home: toggle selection from (including) the current
+ * item to the (including) the first item
+ * @li CTRL+PgDn: toggle selection from (including) the current
+ * item to (excluding) the item one page down
+ * @li CTRL+PgUp: toggle selection from (excluding) the current
+ * item to (including) the item one page up
+ *
+ * The combinations work the same with SHIFT instead of CTRL, except
+ * that if you start selecting something using SHIFT everything selected
+ * before will be deselected first.
+ *
+ * Additionally the current item is always selected automatically when
+ * navigating using the keyboard, except other items were selected explicitly.
+ *
+ * This way e.g. SHIFT+up/PgUp then SHIFT+down/PgDn leaves no item selected
+ */
+ enum SelectionModeExt {
+ Single = QListView::Single,
+ Multi = QListView::Multi,
+ Extended = QListView::Extended,
+ NoSelection = QListView::NoSelection,
+ FileManager
+ };
+
+ /**
+ * Constructor.
+ *
+ * The parameters @p parent and @p name are handled by
+ * QListView, as usual.
+ */
+ KListView (QWidget *parent = 0, const char *name = 0);
+
+ /**
+ * Destructor.
+ */
+ virtual ~KListView();
+
+ /**
+ * Reimplemented for internal reasons.
+ * Further reimplementations should call this function or else
+ * some features may not work correctly.
+ *
+ * The API is unaffected.
+ */
+ virtual void setAcceptDrops (bool);
+
+ /**
+ * This function determines whether the given coordinates are within the
+ * execute area. The execute area is the part of a QListViewItem where mouse
+ * clicks or double clicks respectively generate a executed() signal.
+ * Depending on QListView::allColumnsShowFocus() this is either the
+ * whole item or only the first column.
+ * @return true if point is inside execute area of an item, false in all
+ * other cases including the case that it is over the viewport.
+ */
+ virtual bool isExecuteArea( const QPoint& point );
+
+ /**
+ * Same thing, but from an x coordinate only. This only checks if x is in
+ * the first column (if all columns don't show focus), without testing if
+ * the y coordinate is over an item or not.
+ */
+ bool isExecuteArea( int x );
+
+ /**
+ * @return a list containing the currently selected items.
+ *
+ * @deprecated
+ */
+ QPtrList<QListViewItem> selectedItems() const;
+
+ /**
+ * @return a list containing the currently selected items.
+ *
+ * @param includeHiddenItems Set to true to return all items regardless of
+ * visibility. Set to false to only return items that are isVisible().
+ *
+ * @return a list of all selected listview items
+ *
+ * @since 3.4
+ */
+ QPtrList<QListViewItem> selectedItems(bool includeHiddenItems) const; // ### BIC: KDE 4: use an implicitly shared class! (QValutList?) and merge with above, default to true
+
+ /**
+ * Arbitrarily move @p item to @p parent, positioned immediately after item @p after.
+ * If after is 0, @p item is made the first child of @p parent.
+ *
+ * (Un-deprecated in kde-3.4)
+ */
+ void moveItem(QListViewItem *item, QListViewItem *parent, QListViewItem *after);
+
+ /**
+ * @return the last item (not child!) of this listview.
+ *
+ * @see lastChild()
+ */
+ QListViewItem *lastItem() const;
+
+ /**
+ * @return the last child of this listview.
+ *
+ * @see lastItem()
+ */
+ QListViewItem* lastChild () const;
+
+ /**
+ * @return the lineedit used for inline renaming.
+ * Use that to setup a KCompletion or QValidator for the lineedit
+ *
+ * @since 3.2
+ */
+ KLineEdit* renameLineEdit() const;
+
+ /**
+ * @returns if it is legal to move items in the list view. True by default.
+ *
+ * @see setDragEnabled()
+ * @see setItemsMovable()
+ */
+ bool itemsMovable() const;
+
+ /**
+ * @return whether inplace-renaming has been enabled. False by default.
+ *
+ * @see setItemsRenameable()
+ */
+ bool itemsRenameable() const;
+
+ /**
+ * @return whether dragging is enabled. False by default.
+ *
+ * @see setDragEnabled()
+ */
+ bool dragEnabled() const;
+
+ /**
+ * @return true if AutoOpen is enabled (not implemented currently).
+ *
+ * @see setAutoOpen()
+ */
+ bool autoOpen() const;
+
+ /**
+ * @return true if @p column is renamable.
+ *
+ * @see setRenameable()
+ */
+ bool isRenameable (int column) const;
+
+ /**
+ * @return true if drawing of the drop-visualizer has been enabled. True by default.
+ *
+ * @see setDropVisualizer()
+ */
+ bool dropVisualizer() const;
+
+ /**
+ * @return the column for which tooltips are displayed (or -1 if none set).
+ *
+ * @see setTooltipColumn()
+ */
+ int tooltipColumn() const;
+
+ /**
+ * For future expansions.
+ *
+ * Do not use.
+ * @deprecated
+ */
+ bool createChildren() const KDE_DEPRECATED;
+
+ /**
+ * @return true if drawing of the drop-highlighter has been enabled. False by default.
+ *
+ * @see setDropHighlighter()
+ */
+ bool dropHighlighter() const;
+
+ /**
+ * The dropVisualizerWidth defaults to 4.
+ *
+ * @see setDropVisualizerWidth()
+ * @return the current width of the drop-visualizer.
+ */
+ int dropVisualizerWidth () const;
+
+ /**
+ * @return the "extended" selection mode of this listview.
+ *
+ * @see SelectionModeExt
+ * @see setSelectionModeExt
+ */
+ SelectionModeExt selectionModeExt () const;
+
+ /**
+ * Returns the index of @p item within the item tree or -1 if
+ * @p item doesn't exist in this list view. This function takes
+ * all items into account not only the visible ones.
+ */
+ int itemIndex( const QListViewItem *item ) const;
+
+ /**
+ * Returns the item of @p index within the item tree or 0 if
+ * @p index doesn't exist in this list view. This function takes
+ * all items into account not only the visible ones.
+ */
+ QListViewItem* itemAtIndex(int index);
+
+ /**
+ * @deprecated
+ * @see setFullWidth()
+ */
+ void setFullWidth() KDE_DEPRECATED;
+
+ /**
+ * Let the last column fit exactly all the available width.
+ *
+ * @see fullWidth()
+ */
+ void setFullWidth(bool fullWidth);
+
+ /**
+ * Returns whether the last column is set to fit the available width.
+ *
+ * @see setFullWidth()
+ */
+ bool fullWidth() const;
+
+ /**
+ * Reimplemented for full width support
+ *
+ * @see removeColumn()
+ */
+ virtual int addColumn(const QString& label, int width = -1);
+ /**
+ * Reimplemented for full width support
+ */
+ virtual int addColumn(const QIconSet& iconset, const QString& label, int width = -1);
+ /**
+ * Reimplemented for full width support
+ *
+ * @see addColumn()
+ */
+ virtual void removeColumn(int index);
+
+ /**
+ * sets the alternate background background color.
+ * This only has an effect if the items are KListViewItems
+ *
+ * @param c the color to use for every other item. Set to an invalid
+ * color to disable alternate colors.
+ *
+ * @see alternateBackground()
+ **/
+ void setAlternateBackground(const QColor &c);
+ /**
+ * @return the alternate background color
+ *
+ * @see setAlternateBackground()
+ */
+ const QColor &alternateBackground() const;
+
+ /**
+ * Saves the list view's layout (column widtsh, column order, sort column)
+ * to a KConfig group
+ *
+ * @param config the KConfig object to write to
+ * @param group the config group to use
+ */
+ void saveLayout(KConfig *config, const QString &group) const;
+ /**
+ * Reads the list view's layout from a KConfig group as stored with
+ * saveLayout
+ *
+ * @param config the KConfig object to read from
+ * @param group the config group to use
+ */
+ void restoreLayout(KConfig *config, const QString &group);
+ /**
+ * Reimplemented to remember the current sort column and order.
+ * @param column is the column to be sorted, or -1 to sort in order of
+ * insertion
+ * @param ascending whether to sort ascending (or descending)
+ */
+ virtual void setSorting(int column, bool ascending = true);
+
+ /**
+ * @return the currently sorted column, or -1 if none is sorted
+ */
+ int columnSorted(void) const;
+
+ /**
+ * @return whether the current sort is ascending (or descending)
+ */
+ bool ascendingSort(void) const;
+
+ /**
+ * Reimplemented for internal reasons.
+ */
+ virtual void takeItem(QListViewItem *i);
+
+ /**
+ * Set to true if the currently sorted column should be drawn shaded. Defaults to true
+ * @param shadeSortColumn True if sort column should be shaded.
+ *
+ * @since 3.4
+ */
+ void setShadeSortColumn(bool shadeSortColumn);
+
+ /**
+ * See if the sort column should be drawn shaded
+ * @return true if the sort column should be shaded
+ *
+ * @since 3.4
+ */
+ bool shadeSortColumn(void) const;
+signals:
+
+ /**
+ * This signal is emitted whenever the user executes an listview item.
+ * That means depending on the KDE wide Single Click/Double Click
+ * setting the user clicked or double clicked on that item.
+ * @param item is the pointer to the executed listview item.
+ *
+ * Note that you may not delete any QListViewItem objects in slots
+ * connected to this signal.
+ */
+ void executed( QListViewItem *item );
+
+ /**
+ * This signal is emitted whenever the user executes an listview item.
+ * That means depending on the KDE wide Single Click/Double Click
+ * setting the user clicked or double clicked on that item.
+ * @param item is the pointer to the executed listview item.
+ * @param pos is the position where the user has clicked
+ * @param c is the column into which the user clicked.
+ *
+ * Note that you may not delete any QListViewItem objects in slots
+ * connected to this signal.
+ */
+ void executed( QListViewItem *item, const QPoint &pos, int c );
+
+ /**
+ * This signal gets emitted whenever something acceptable is
+ * dropped onto the listview.
+ *
+ * @param e is the drop event itself (it has already been accepted)
+ * @param after is the item after which the drop occurred (or 0L, if
+ * the drop was above all items)
+ *
+ * @see acceptDrop()
+ */
+ void dropped (QDropEvent * e, QListViewItem *after);
+
+ /**
+ * This signal gets emitted whenever something acceptable is
+ * dropped onto the listview.
+ *
+ * This is an overloaded version of the above (provided to simplify
+ * processing drops outside of the class).
+ *
+ * @param list is the listview
+ * @param e is the drop event itself (it has already been accepted)
+ * @param after is the item after which the drop occurred (or 0L, if
+ * the drop was above all items
+ */
+ void dropped (KListView* list, QDropEvent* e, QListViewItem* after);
+
+ /**
+ * This signal gets emitted whenever something acceptable is
+ * dropped onto the listview.
+ *
+ * This function also provides a parent, in the event that your listview
+ * is a tree
+ * @param list is the listview
+ * @param e is the drop event itself (it has already been accepted)
+ * @param parent the item that is to be the parent of the new item
+ * @param after is the item after which the drop occurred (or 0L, if
+ * the drop was above all items
+ */
+ void dropped (KListView* list, QDropEvent* e, QListViewItem* parent, QListViewItem* after);
+
+ /**
+ * This signal gets emitted whenever something acceptable is
+ * dropped onto the listview.
+ *
+ * This function also provides a parent, in the event that your listview
+ * is a tree
+ * @param e is the drop event itself (it has already been accepted)
+ * @param parent the item that is to be the parent of the new item
+ * @param after is the item after which the drop occurred (or 0L, if
+ * the drop was above all items
+ */
+ void dropped (QDropEvent* e, QListViewItem* parent, QListViewItem* after);
+
+ /**
+ * This signal is emitted when ever the user moves an item in the list via
+ * DnD.
+ * If more than one item is moved at the same time, this signal is only emitted
+ * once.
+ */
+ void moved();
+
+ /**
+ * Connect to this signal if you want to do some preprocessing before
+ * a move is made, for example, to disable sorting
+ *
+ * This is sent only once per each groups of moves. That is, for each
+ * drop that is a move this will be emitted once, before KListView calls
+ * @see moveItem()
+ */
+ void aboutToMove();
+
+ /**
+ * This signal is emitted when ever the user moves an item in the list via
+ * DnD.
+ * If more than one item is moved at the same time, @p afterFirst and
+ * @p afterNow will reflect what was true before the move.
+ * This differs from moved(), so be careful. All the items will have been
+ * moved before moved() is emitted, which is not true in this method. // FIXME
+ * @param item the item that was moved
+ * @param afterFirst the item that parameter item was in before the move, in the list
+ * @param afterNow the item it's currently after.
+ */
+ void moved (QListViewItem *item, QListViewItem *afterFirst, QListViewItem *afterNow);
+
+
+ /**
+ * This signal is emitted after all the items have been moved. It reports info for
+ * each and every item moved, in order. The first element in @p items associates
+ * with the first of afterFirst and afterNow.
+ */
+ void moved(QPtrList<QListViewItem> &items, QPtrList<QListViewItem> &afterFirst, QPtrList<QListViewItem> &afterNow);
+
+ /**
+ * This signal gets emitted when an item is renamed via in-place renaming.
+ *
+ * @param item is the renamed item.
+ * @param str is the new value of column @p col.
+ * @param col is the renamed column.
+ */
+ void itemRenamed(QListViewItem* item, const QString &str, int col);
+
+ /**
+ * Same as above, but without the extra information.
+ */
+ void itemRenamed(QListViewItem* item);
+
+ /**
+ * This signal is emitted when the shortcut key for popup-menus is pressed.
+ *
+ * Normally you should not use this, just connect a slot to signal
+ * contextMenu (KListView*, QListViewItem*, const QPoint&) to correctly
+ * handle showing context menus regardless of settings.
+ *
+ * @param list is this listview.
+ * @param item is the currentItem() at the time the key was pressed. May be 0L.
+ */
+ void menuShortCutPressed (KListView* list, QListViewItem* item);
+
+ /**
+ * This signal is emitted whenever a context-menu should be shown for item @p i.
+ * It automatically adjusts for all settings involved (Menu key, showMenuOnPress/Click).
+ *
+ * @param l is this listview.
+ * @param i is the item for which the menu should be shown. May be 0L.
+ * @param p is the point at which the menu should be shown.
+ */
+ void contextMenu (KListView* l, QListViewItem* i, const QPoint& p);
+
+ void itemAdded(QListViewItem *item);
+ void itemRemoved(QListViewItem *item);
+
+public slots:
+ /**
+ * Rename column @p c of @p item.
+ */
+ virtual void rename(QListViewItem *item, int c);
+
+ /**
+ * By default, if you called setItemsRenameable(true),
+ * only the first column is renameable.
+ * Use this function to enable the feature on other columns.
+ *
+ * If you want more intelligent (dynamic) selection,
+ * you'll have to derive from KListView,
+ * and override rename() and call only call it
+ * if you want the item to be renamed.
+ */
+ void setRenameable (int column, bool yesno=true);
+
+ /**
+ * Set whether items in the list view can be moved.
+ * It is enabled by default.
+ *
+ * @see itemsMovable()
+ */
+ virtual void setItemsMovable(bool b);
+
+ /**
+ * Enables inplace-renaming of items.
+ * It is disabled by default.
+ *
+ * @see itemsRenameable()
+ * @see setRenameable()
+ */
+ virtual void setItemsRenameable(bool b);
+
+ /**
+ * Enable/Disable the dragging of items.
+ * It is disabled by default.
+ */
+ virtual void setDragEnabled(bool b);
+
+ /**
+ * Enable/Disable AutoOpen (not implemented currently).
+ */
+ virtual void setAutoOpen(bool b);
+
+ /**
+ * Enable/Disable the drawing of a drop-visualizer
+ * (a bar that shows where a dropped item would be inserted).
+ * It is enabled by default, if dragging is enabled
+ */
+ virtual void setDropVisualizer(bool b);
+
+ /**
+ * Set the width of the (default) drop-visualizer.
+ * If you don't call this method, the width is set to 4.
+ */
+ void setDropVisualizerWidth (int w);
+
+ /**
+ * Set which column should be used for automatic tooltips.
+ *
+ * @param column is the column for which tooltips will be shown.
+ * Set -1 to disable this feature.
+ */
+ virtual void setTooltipColumn(int column);
+
+ /**
+ * Enable/Disable the drawing of a drop-highlighter
+ * (a rectangle around the item under the mouse cursor).
+ * It is disabled by default.
+ */
+ virtual void setDropHighlighter(bool b);
+
+ /**
+ * For future expansions.
+ *
+ * Do not use.
+ * @deprecated
+ */
+ virtual void setCreateChildren(bool b) KDE_DEPRECATED;
+
+ /**
+ * Set the selection mode.
+ *
+ * A different name was chosen to avoid API-clashes with QListView::setSelectionMode().
+ */
+ void setSelectionModeExt (SelectionModeExt mode);
+
+ /**
+ * Enable/disable tabbing between editable cells
+ * @since 3.1
+ */
+ void setTabOrderedRenaming(bool b);
+
+ /**
+ * Returns whether tab ordered renaming is enabled
+ * @since 3.1
+ */
+ bool tabOrderedRenaming() const;
+
+protected:
+ /**
+ * Determine whether a drop on position @p p would count as
+ * being above or below the QRect @p rect.
+ *
+ * @param rect is the rectangle we examine.
+ * @param p is the point located in the rectangle, p is assumed to be in
+ * viewport coordinates.
+ */
+ inline bool below (const QRect& rect, const QPoint& p)
+ {
+ return (p.y() > (rect.top() + (rect.bottom() - rect.top())/2));
+ }
+
+ /**
+ * An overloaded version of below(const QRect&, const QPoint&).
+ *
+ * It differs from the above only in what arguments it takes.
+ *
+ * @param i the item whose rect() is passed to the above function.
+ * @param p is translated from contents coordinates to viewport coordinates
+ * before being passed to the above function.
+ */
+ inline bool below (QListViewItem* i, const QPoint& p)
+ {
+ return below (itemRect(i), contentsToViewport(p));
+ }
+
+ /**
+ * Reimplemented to reload the alternate background in palette changes.
+ * @internal
+ */
+ virtual bool event( QEvent * );
+
+ /**
+ * Emit signal executed.
+ * @internal
+ */
+ void emitExecute( QListViewItem *item, const QPoint &pos, int c );
+
+ /**
+ * Reimplemented for internal reasons.
+ * Further reimplementations should call this function or else
+ * some features may not work correctly.
+ *
+ * The API is unaffected.
+ */
+ virtual void focusInEvent(QFocusEvent* fe);
+
+ /**
+ * Reimplemented for internal reasons.
+ * Further reimplementations should call this function or else
+ * some features may not work correctly.
+ *
+ * The API is unaffected.
+ */
+ virtual void focusOutEvent( QFocusEvent *fe );
+
+ /**
+ * Reimplemented for internal reasons.
+ * Further reimplementations should call this function or else
+ * some features may not work correctly.
+ *
+ * The API is unaffected.
+ */
+ virtual void leaveEvent( QEvent *e );
+
+ /**
+ * @return the tooltip for @p column of @p item.
+ */
+ virtual QString tooltip(QListViewItem* item, int column) const;
+
+ /**
+ * @return whether the tooltip for @p column of @p item shall be shown at point @p pos.
+ */
+ virtual bool showTooltip(QListViewItem *item, const QPoint &pos, int column) const;
+
+ /**
+ * Reimplemented for internal reasons.
+ * Further reimplementations should call this function or else
+ * some features may not work correctly.
+ *
+ * The API is unaffected.
+ */
+ virtual void contentsDragMoveEvent (QDragMoveEvent *event);
+
+ /**
+ * Reimplemented for internal reasons.
+ * Further reimplementations should call this function or else
+ * some features may not work correctly.
+ *
+ * The API is unaffected.
+ */
+ virtual void contentsMousePressEvent( QMouseEvent *e );
+
+ /**
+ * Reimplemented for internal reasons.
+ * Further reimplementations should call this function or else
+ * some features may not work correctly.
+ *
+ * The API is unaffected.
+ */
+ virtual void contentsMouseMoveEvent( QMouseEvent *e );
+
+ /**
+ * Reimplemented for internal reasons.
+ * Further reimplementations should call this function or else
+ * some features may not work correctly.
+ *
+ * The API is unaffected.
+ */
+ virtual void contentsMouseDoubleClickEvent ( QMouseEvent *e );
+
+ /**
+ * Reimplemented for internal reasons.
+ * Further reimplementations should call this function or else
+ * some features may not work correctly.
+ *
+ * The API is unaffected.
+ */
+ virtual void contentsDragLeaveEvent (QDragLeaveEvent *event);
+
+ /**
+ * Reimplemented for internal reasons.
+ * Further reimplementations should call this function or else
+ * some features may not work correctly.
+ *
+ * The API is unaffected.
+ */
+ virtual void contentsMouseReleaseEvent (QMouseEvent*);
+
+ /**
+ * Reimplemented for internal reasons.
+ * Further reimplementations should call this function or else
+ * some features may not work correctly.
+ *
+ * The API is unaffected.
+ */
+ virtual void contentsDropEvent (QDropEvent*);
+
+ /**
+ * Reimplemented for internal reasons.
+ * Further reimplementations should call this function or else
+ * some features may not work correctly.
+ *
+ * The API is unaffected.
+ */
+ virtual void contentsDragEnterEvent (QDragEnterEvent *);
+
+ /**
+ * @return a dragobject encoding the current selection.
+ *
+ * @see setDragEnabled()
+ */
+ virtual QDragObject *dragObject();
+
+ /**
+ * @return true if the @p event provides some acceptable
+ * format.
+ * A common mistake is to forget the "const" in your reimplementation
+ */
+ virtual bool acceptDrag (QDropEvent* event) const;
+
+ /**
+ * Paint the drag line. If painter is null, don't try to :)
+ *
+ * If after == 0 then the marker should be drawn at the top.
+ *
+ * @return the rectangle that you painted to.
+ */
+ virtual QRect drawDropVisualizer (QPainter *p, QListViewItem *parent, QListViewItem *after);
+
+ /**
+ * Paint the drag rectangle. If painter is null, don't try to :)
+ *
+ *
+ * @return the rectangle that you painted to.
+ */
+ virtual QRect drawItemHighlighter(QPainter *painter, QListViewItem *item);
+
+ /**
+ * This method calls dragObject() and starts the drag.
+ *
+ * Reimplement it to do fancy stuff like setting a pixmap or
+ * using a non-default DragMode
+ */
+ virtual void startDrag();
+
+ /**
+ * Reimplemented for internal reasons.
+ * Further reimplementations should call this function or else
+ * some features may not work correctly.
+ *
+ * The API is unaffected.
+ */
+ virtual void keyPressEvent (QKeyEvent*);
+
+ /**
+ * Reimplemented for internal reasons.
+ * Further reimplementations should call this function or else
+ * some features may not work correctly.
+ *
+ * The API is unaffected.
+ */
+ virtual void viewportPaintEvent(QPaintEvent*);
+
+ /**
+ * In FileManager selection mode: explicitly activate the mode
+ * in which the current item is automatically selected.
+ */
+ void activateAutomaticSelection();
+ /**
+ * In FileManager selection mode: explicitly deactivate the mode
+ * in which the current item is automatically selected.
+ */
+ void deactivateAutomaticSelection();
+ /**
+ * In FileManager selection mode: return whether it is currently in the mode
+ * where the current item is selected automatically.
+ * Returns false if items were selected explicitly, e.g. using the mouse.
+ */
+ bool automaticSelection() const;
+
+ /**
+ * Reimplemented for setFullWidth()
+ */
+ virtual void viewportResizeEvent(QResizeEvent* e);
+
+ /**
+ * Disable AutoSelection. This overrides the system wide setting for
+ * AutoSelection. Please don't call this unless you have good reasons to
+ * override the system wide setting for AutoSelection.
+ * @see resetAutoSelection()
+ * @since 3.2
+ */
+ void disableAutoSelection();
+
+ /**
+ * Reset AutoSelection to the system wide setting.
+ * @see disableAutoSelection()
+ * @since 3.2
+ */
+ void resetAutoSelection();
+
+ /**
+ * @deprecated This is just here for binary compatibility. Use the signal
+ * in QListView instead.
+ */
+ // KDE 4: remove
+ void doubleClicked( QListViewItem *item, const QPoint &pos, int c );
+
+protected slots:
+ /**
+ * Update internal settings whenever the global ones change.
+ * @internal
+ */
+ void slotSettingsChanged(int);
+
+ void slotMouseButtonClicked( int btn, QListViewItem *item, const QPoint &pos, int c );
+ void doneEditing(QListViewItem *item, int row);
+
+ /**
+ * Repaint the rect where I was drawing the drop line.
+ */
+ void cleanDropVisualizer();
+
+ /**
+ * Repaint the rect where I was drawing the drop rectangle.
+ */
+ void cleanItemHighlighter();
+
+ /**
+ * Emit the contextMenu signal. This slot is for mouse actions.
+ */
+ void emitContextMenu (QListViewItem*, const QPoint&, int);
+
+ /**
+ * Emit the contextMenu signal. This slot is for key presses.
+ */
+ void emitContextMenu (KListView*, QListViewItem*);
+
+ /**
+ * Accessory slot for AutoSelect
+ * @internal
+ */
+ void slotOnItem( QListViewItem *item );
+
+ /**
+ * Accessory slot for AutoSelect/ChangeCursorOverItem
+ * @internal
+ */
+ void slotOnViewport();
+
+ /**
+ * Process AutoSelection.
+ * @internal
+ */
+ void slotAutoSelect();
+
+ void slotDragExpand();
+
+ /**
+ * Reacts to header changes in full width mode
+ * @internal
+ */
+ void slotHeaderChanged();
+
+protected:
+ /**
+ * Handle dropEvent when itemsMovable() is set to true.
+ */
+ virtual void movableDropEvent (QListViewItem* parent, QListViewItem* afterme);
+
+ /**
+ * Where is the nearest QListViewItem that I'm going to drop?
+ *
+ * FIXME KDE 4.0: Make this method const so it can be called from an
+ * acceptDrag method without ugly casts
+ */
+ virtual void findDrop(const QPoint &pos, QListViewItem *&parent, QListViewItem *&after);
+
+ /**
+ * A special keyPressEvent (for FileManager selection mode).
+ */
+ void fileManagerKeyPressEvent (QKeyEvent*);
+
+ /**
+ * Convert the depth of an item into its indentation in pixels
+ */
+ int depthToPixels( int depth );
+
+private:
+ class Tooltip;
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KListViewPrivate;
+ KListViewPrivate* const d;
+ bool isExecuteArea( int x, QListViewItem* item );
+};
+
+/**
+ * A listview item with support for alternate background colors. It is
+ * a drop-in replacement for QListViewItem
+ *
+ * @short listview item with alternate background color support
+ */
+class KDEUI_EXPORT KListViewItem : public QListViewItem
+{
+ friend class KListView;
+public:
+ /**
+ * constructors. The semantics remain as in QListViewItem.
+ * Although they accept a QListViewItem as parent, please
+ * don't mix KListViewItem (or subclasses) with QListViewItem
+ * (or subclasses).
+ */
+ KListViewItem(QListView *parent);
+ KListViewItem(QListViewItem *parent);
+ KListViewItem(QListView *parent, QListViewItem *after);
+ KListViewItem(QListViewItem *parent, QListViewItem *after);
+
+ KListViewItem(QListView *parent,
+ QString, QString = QString::null,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null, QString = QString::null);
+
+ KListViewItem(QListViewItem *parent,
+ QString, QString = QString::null,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null, QString = QString::null);
+
+ KListViewItem(QListView *parent, QListViewItem *after,
+ QString, QString = QString::null,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null, QString = QString::null);
+
+ KListViewItem(QListViewItem *parent, QListViewItem *after,
+ QString, QString = QString::null,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null, QString = QString::null,
+ QString = QString::null, QString = QString::null);
+
+ virtual ~KListViewItem();
+
+ virtual void insertItem(QListViewItem *item);
+ virtual void takeItem(QListViewItem *item);
+ /**
+ * returns true if this item is to be drawn with the alternate background
+ */
+ bool isAlternate();
+ /**
+ * returns the background color for this item
+ */
+ const QColor &backgroundColor() KDE_DEPRECATED; // #### should be removed in 4.0; use below instead
+
+ /**
+ * returns the background color for this item at given column
+ * This can be different in the column which is sorted due to shading
+ * ### could be merged with above (column = -1) to be source compatible
+ * ### but will only work if sort-shading is not used or the listView has
+ * ### only 1 column
+ * @since 3.4
+ */
+ QColor backgroundColor(int column);
+
+ virtual void paintCell(QPainter *p, const QColorGroup &cg,
+ int column, int width, int alignment);
+
+private:
+ void init();
+
+private:
+ uint m_odd : 1;
+ uint m_known : 1;
+ uint m_unused : 30;
+};
+
+#endif
+
+// vim: ts=2 sw=2 et
diff --git a/kdeui/klistviewlineedit.h b/kdeui/klistviewlineedit.h
new file mode 100644
index 000000000..1fe56e202
--- /dev/null
+++ b/kdeui/klistviewlineedit.h
@@ -0,0 +1,65 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Charles Samuels <charles@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef KLISTVIEWLINEEDIT_H
+#define KLISTVIEWLINEEDIT_H
+
+#include <klineedit.h>
+#include <klistview.h>
+
+/**
+ * the editor for a KListView. please don't use this.
+ * @internal
+ **/
+class KDEUI_EXPORT KListViewLineEdit : public KLineEdit
+{
+Q_OBJECT
+public:
+ KListViewLineEdit(KListView *parent);
+ ~KListViewLineEdit();
+
+ QListViewItem *currentItem() const;
+
+signals:
+ void done(QListViewItem*, int);
+
+public slots:
+ void terminate();
+ void load(QListViewItem *i, int c);
+
+protected:
+ virtual void focusOutEvent(QFocusEvent *);
+ virtual void keyPressEvent(QKeyEvent *e);
+ virtual void paintEvent(QPaintEvent *e);
+ virtual bool event (QEvent *pe);
+
+ /// @since 3.1
+ void selectNextCell (QListViewItem *pi, int column, bool forward);
+ void terminate(bool commit);
+ QListViewItem *item;
+ int col;
+ KListView* const p;
+
+protected slots:
+ void slotSelectionChanged();
+
+ /// @since 3.5.4
+ void slotItemRemoved(QListViewItem *i);
+
+};
+
+#endif
diff --git a/kdeui/klistviewsearchline.cpp b/kdeui/klistviewsearchline.cpp
new file mode 100644
index 000000000..e3f9271eb
--- /dev/null
+++ b/kdeui/klistviewsearchline.cpp
@@ -0,0 +1,501 @@
+/* This file is part of the KDE libraries
+ Copyright (c) 2003 Scott Wheeler <wheeler@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "klistviewsearchline.h"
+
+#include <klistview.h>
+#include <kiconloader.h>
+#include <ktoolbar.h>
+#include <ktoolbarbutton.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+#include <qapplication.h>
+#include <qtimer.h>
+#include <qpopupmenu.h>
+#include <qlabel.h>
+#include <qheader.h>
+
+#define KLISTVIEWSEARCHLINE_ALLVISIBLECOLUMNS_ID 2004
+
+class KListViewSearchLine::KListViewSearchLinePrivate
+{
+public:
+ KListViewSearchLinePrivate() :
+ listView(0),
+ caseSensitive(false),
+ activeSearch(false),
+ keepParentsVisible(true),
+ queuedSearches(0) {}
+
+ KListView *listView;
+ bool caseSensitive;
+ bool activeSearch;
+ bool keepParentsVisible;
+ QString search;
+ int queuedSearches;
+ QValueList<int> searchColumns;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// public methods
+////////////////////////////////////////////////////////////////////////////////
+
+KListViewSearchLine::KListViewSearchLine(QWidget *parent, KListView *listView, const char *name) :
+ KLineEdit(parent, name)
+{
+ d = new KListViewSearchLinePrivate;
+
+ d->listView = listView;
+
+ connect(this, SIGNAL(textChanged(const QString &)),
+ this, SLOT(queueSearch(const QString &)));
+
+ if(listView) {
+ connect(listView, SIGNAL(destroyed()),
+ this, SLOT(listViewDeleted()));
+
+ connect(listView, SIGNAL(itemAdded(QListViewItem *)),
+ this, SLOT(itemAdded(QListViewItem *)));
+ }
+ else
+ setEnabled(false);
+}
+
+KListViewSearchLine::KListViewSearchLine(QWidget *parent, const char *name) :
+ KLineEdit(parent, name)
+{
+ d = new KListViewSearchLinePrivate;
+
+ d->listView = 0;
+
+ connect(this, SIGNAL(textChanged(const QString &)),
+ this, SLOT(queueSearch(const QString &)));
+
+ setEnabled(false);
+}
+
+KListViewSearchLine::~KListViewSearchLine()
+{
+ delete d;
+}
+
+bool KListViewSearchLine::caseSensitive() const
+{
+ return d->caseSensitive;
+}
+
+QValueList<int> KListViewSearchLine::searchColumns() const
+{
+ return d->searchColumns;
+}
+
+bool KListViewSearchLine::keepParentsVisible() const
+{
+ return d->keepParentsVisible;
+}
+
+KListView *KListViewSearchLine::listView() const
+{
+ return d->listView;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// public slots
+////////////////////////////////////////////////////////////////////////////////
+
+void KListViewSearchLine::updateSearch(const QString &s)
+{
+ if(!d->listView)
+ return;
+
+ d->search = s.isNull() ? text() : s;
+
+ // If there's a selected item that is visible, make sure that it's visible
+ // when the search changes too (assuming that it still matches).
+
+ QListViewItem *currentItem = 0;
+
+ switch(d->listView->selectionMode())
+ {
+ case KListView::NoSelection:
+ break;
+ case KListView::Single:
+ currentItem = d->listView->selectedItem();
+ break;
+ default:
+ {
+ int flags = QListViewItemIterator::Selected | QListViewItemIterator::Visible;
+ for(QListViewItemIterator it(d->listView, flags);
+ it.current() && !currentItem;
+ ++it)
+ {
+ if(d->listView->itemRect(it.current()).isValid())
+ currentItem = it.current();
+ }
+ }
+ }
+
+ if(d->keepParentsVisible)
+ checkItemParentsVisible(d->listView->firstChild());
+ else
+ checkItemParentsNotVisible();
+
+ if(currentItem)
+ d->listView->ensureItemVisible(currentItem);
+}
+
+void KListViewSearchLine::setCaseSensitive(bool cs)
+{
+ d->caseSensitive = cs;
+}
+
+void KListViewSearchLine::setKeepParentsVisible(bool v)
+{
+ d->keepParentsVisible = v;
+}
+
+void KListViewSearchLine::setSearchColumns(const QValueList<int> &columns)
+{
+ d->searchColumns = columns;
+}
+
+void KListViewSearchLine::setListView(KListView *lv)
+{
+ if(d->listView) {
+ disconnect(d->listView, SIGNAL(destroyed()),
+ this, SLOT(listViewDeleted()));
+
+ disconnect(d->listView, SIGNAL(itemAdded(QListViewItem *)),
+ this, SLOT(itemAdded(QListViewItem *)));
+ }
+
+ d->listView = lv;
+
+ if(lv) {
+ connect(d->listView, SIGNAL(destroyed()),
+ this, SLOT(listViewDeleted()));
+
+ connect(d->listView, SIGNAL(itemAdded(QListViewItem *)),
+ this, SLOT(itemAdded(QListViewItem *)));
+ }
+
+ setEnabled(bool(lv));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// protected members
+////////////////////////////////////////////////////////////////////////////////
+
+bool KListViewSearchLine::itemMatches(const QListViewItem *item, const QString &s) const
+{
+ if(s.isEmpty())
+ return true;
+
+ // If the search column list is populated, search just the columns
+ // specifified. If it is empty default to searching all of the columns.
+
+ if(!d->searchColumns.isEmpty()) {
+ QValueList<int>::ConstIterator it = d->searchColumns.begin();
+ for(; it != d->searchColumns.end(); ++it) {
+ if(*it < item->listView()->columns() &&
+ item->text(*it).find(s, 0, d->caseSensitive) >= 0)
+ return true;
+ }
+ }
+ else {
+ for(int i = 0; i < item->listView()->columns(); i++) {
+ if(item->listView()->columnWidth(i) > 0 &&
+ item->text(i).find(s, 0, d->caseSensitive) >= 0)
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+QPopupMenu *KListViewSearchLine::createPopupMenu()
+{
+ QPopupMenu *popup = KLineEdit::createPopupMenu();
+
+ if (d->listView->columns()>1) {
+ QPopupMenu *subMenu = new QPopupMenu(popup);
+ connect(subMenu, SIGNAL(activated(int)), this, SLOT(searchColumnsMenuActivated(int)));
+
+ popup->insertSeparator();
+ popup->insertItem(i18n("Search Columns"), subMenu);
+
+ subMenu->insertItem(i18n("All Visible Columns"), KLISTVIEWSEARCHLINE_ALLVISIBLECOLUMNS_ID);
+ subMenu->insertSeparator();
+
+ bool allColumnsAreSearchColumns = true;
+ // TODO Make the entry order match the actual column order
+ QHeader* const header = d->listView->header();
+ int visibleColumns = 0;
+ for(int i = 0; i < d->listView->columns(); i++) {
+ if(d->listView->columnWidth(i)>0) {
+ QString columnText = d->listView->columnText(i);
+ if(columnText.isEmpty()) {
+ int visiblePosition=1;
+ for(int j = 0; j < header->mapToIndex(i); j++)
+ if(d->listView->columnWidth(header->mapToSection(j))>0)
+ visiblePosition++;
+ columnText = i18n("Column number %1","Column No. %1").arg(visiblePosition);
+ }
+ subMenu->insertItem(columnText, visibleColumns);
+ if(d->searchColumns.isEmpty() || d->searchColumns.find(i) != d->searchColumns.end())
+ subMenu->setItemChecked(visibleColumns, true);
+ else
+ allColumnsAreSearchColumns = false;
+ visibleColumns++;
+ }
+ }
+ subMenu->setItemChecked(KLISTVIEWSEARCHLINE_ALLVISIBLECOLUMNS_ID, allColumnsAreSearchColumns);
+
+ // searchColumnsMenuActivated() relies on one possible "all" representation
+ if(allColumnsAreSearchColumns && !d->searchColumns.isEmpty())
+ d->searchColumns.clear();
+ }
+
+ return popup;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// protected slots
+////////////////////////////////////////////////////////////////////////////////
+
+void KListViewSearchLine::queueSearch(const QString &search)
+{
+ d->queuedSearches++;
+ d->search = search;
+ QTimer::singleShot(200, this, SLOT(activateSearch()));
+}
+
+void KListViewSearchLine::activateSearch()
+{
+ --(d->queuedSearches);
+
+ if(d->queuedSearches == 0)
+ updateSearch(d->search);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// private slots
+////////////////////////////////////////////////////////////////////////////////
+
+void KListViewSearchLine::itemAdded(QListViewItem *item) const
+{
+ item->setVisible(itemMatches(item, text()));
+}
+
+void KListViewSearchLine::listViewDeleted()
+{
+ d->listView = 0;
+ setEnabled(false);
+}
+
+void KListViewSearchLine::searchColumnsMenuActivated(int id)
+{
+ if(id == KLISTVIEWSEARCHLINE_ALLVISIBLECOLUMNS_ID) {
+ if(d->searchColumns.isEmpty())
+ d->searchColumns.append(0);
+ else
+ d->searchColumns.clear();
+ }
+ else {
+ if(d->searchColumns.find(id) != d->searchColumns.end())
+ d->searchColumns.remove(id);
+ else {
+ if(d->searchColumns.isEmpty()) {
+ for(int i = 0; i < d->listView->columns(); i++) {
+ if(i != id)
+ d->searchColumns.append(i);
+ }
+ }
+ else
+ d->searchColumns.append(id);
+ }
+ }
+ updateSearch();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// private methods
+////////////////////////////////////////////////////////////////////////////////
+
+void KListViewSearchLine::checkItemParentsNotVisible()
+{
+ QListViewItemIterator it(d->listView);
+ for(; it.current(); ++it)
+ {
+ QListViewItem *item = it.current();
+ if(itemMatches(item, d->search))
+ item->setVisible(true);
+ else
+ item->setVisible(false);
+ }
+}
+
+#include <kdebug.h>
+
+/** Check whether \p item, its siblings and their descendents should be shown. Show or hide the items as necessary.
+ *
+ * \p item The list view item to start showing / hiding items at. Typically, this is the first child of another item, or the
+ * the first child of the list view.
+ * \p highestHiddenParent The highest (closest to root) ancestor of \p item which is hidden. If 0, all parents of
+ * \p item must be visible.
+ * \return \c true if an item which should be visible is found, \c false if all items found should be hidden. If this function
+ * returns true and \p highestHiddenParent was not 0, highestHiddenParent will have been shown.
+ */
+bool KListViewSearchLine::checkItemParentsVisible(QListViewItem *item, QListViewItem *highestHiddenParent)
+{
+ bool visible = false;
+ QListViewItem * first = item;
+ for(; item; item = item->nextSibling())
+ {
+ //What we pass to our children as highestHiddenParent:
+ QListViewItem * hhp = highestHiddenParent ? highestHiddenParent : item->isVisible() ? 0L : item;
+ bool childMatch = false;
+ if(item->firstChild() && checkItemParentsVisible(item->firstChild(), hhp))
+ childMatch = true;
+ // Should this item be shown? It should if any children should be, or if it matches.
+ if(childMatch || itemMatches(item, d->search))
+ {
+ visible = true;
+ if (highestHiddenParent)
+ {
+ highestHiddenParent->setVisible(true);
+ // Calling setVisible on our ancestor will unhide all its descendents. Hide the ones
+ // before us that should not be shown.
+ for(QListViewItem *hide = first; hide != item; hide = hide->nextSibling())
+ hide->setVisible(false);
+ highestHiddenParent = 0;
+ // If we matched, than none of our children matched, yet the setVisible() call on our
+ // ancestor unhid them, undo the damage:
+ if(!childMatch)
+ for(QListViewItem *hide = item->firstChild(); hide; hide = hide->nextSibling())
+ hide->setVisible(false);
+ }
+ else
+ item->setVisible(true);
+ }
+ else
+ item->setVisible(false);
+ }
+ return visible;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// KListViewSearchLineWidget
+////////////////////////////////////////////////////////////////////////////////
+
+class KListViewSearchLineWidget::KListViewSearchLineWidgetPrivate
+{
+public:
+ KListViewSearchLineWidgetPrivate() : listView(0), searchLine(0), clearButton(0) {}
+ KListView *listView;
+ KListViewSearchLine *searchLine;
+ QToolButton *clearButton;
+};
+
+KListViewSearchLineWidget::KListViewSearchLineWidget(KListView *listView,
+ QWidget *parent,
+ const char *name) :
+ QHBox(parent, name)
+{
+ d = new KListViewSearchLineWidgetPrivate;
+ d->listView = listView;
+
+ setSpacing(5);
+
+ QTimer::singleShot(0, this, SLOT(createWidgets()));
+}
+
+KListViewSearchLineWidget::~KListViewSearchLineWidget()
+{
+ delete d;
+}
+
+KListViewSearchLine *KListViewSearchLineWidget::createSearchLine(KListView *listView)
+{
+ if(!d->searchLine)
+ d->searchLine = new KListViewSearchLine(this, listView);
+ return d->searchLine;
+}
+
+void KListViewSearchLineWidget::createWidgets()
+{
+ positionInToolBar();
+
+ if(!d->clearButton) {
+ d->clearButton = new QToolButton(this);
+ QIconSet icon = SmallIconSet(QApplication::reverseLayout() ? "clear_left" : "locationbar_erase");
+ d->clearButton->setIconSet(icon);
+ }
+
+ d->clearButton->show();
+
+ QLabel *label = new QLabel(i18n("S&earch:"), this, "kde toolbar widget");
+
+ d->searchLine = createSearchLine(d->listView);
+ d->searchLine->show();
+
+ label->setBuddy(d->searchLine);
+ label->show();
+
+ connect(d->clearButton, SIGNAL(clicked()), d->searchLine, SLOT(clear()));
+}
+
+KListViewSearchLine *KListViewSearchLineWidget::searchLine() const
+{
+ return d->searchLine;
+}
+
+void KListViewSearchLineWidget::positionInToolBar()
+{
+ KToolBar *toolBar = dynamic_cast<KToolBar *>(parent());
+
+ if(toolBar) {
+
+ // Here we have The Big Ugly. Figure out how many widgets are in the
+ // and do a hack-ish iteration over them to find this widget so that we
+ // can insert the clear button before it.
+
+ int widgetCount = toolBar->count();
+
+ for(int index = 0; index < widgetCount; index++) {
+ int id = toolBar->idAt(index);
+ if(toolBar->getWidget(id) == this) {
+ toolBar->setItemAutoSized(id);
+ if(!d->clearButton) {
+ QString icon = QApplication::reverseLayout() ? "clear_left" : "locationbar_erase";
+ d->clearButton = new KToolBarButton(icon, 2005, toolBar);
+ }
+ toolBar->insertWidget(2005, d->clearButton->width(), d->clearButton, index);
+ break;
+ }
+ }
+ }
+
+ if(d->searchLine)
+ d->searchLine->show();
+}
+
+#include "klistviewsearchline.moc"
diff --git a/kdeui/klistviewsearchline.h b/kdeui/klistviewsearchline.h
new file mode 100644
index 000000000..e8f5e9e2a
--- /dev/null
+++ b/kdeui/klistviewsearchline.h
@@ -0,0 +1,264 @@
+/* This file is part of the KDE libraries
+ Copyright (c) 2003 Scott Wheeler <wheeler@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KLISTVIEWSEARCHLINE_H
+#define KLISTVIEWSEARCHLINE_H
+
+#include <klineedit.h>
+#include <qhbox.h>
+
+class KListView;
+class QListViewItem;
+class QToolButton;
+
+/**
+ * This class makes it easy to add a search line for filtering the items in a
+ * listview based on a simple text search.
+ *
+ * No changes to the application other than instantiating this class with an
+ * appropriate KListView should be needed.
+ *
+ * If you want the clear button and the search label, you should take a look at
+ * the KListViewSearchLineWidget
+ *
+ * @note { When iterating over items in the KListView, make sure that
+ * the iterator only includes visible items (for example, by adding
+ * QListViewItemIterator::Visible to the iterator flags). Otherwise,
+ * actions (such as deletion) may be taken on items that have been
+ * hidden by the search function. }
+ * @since 3.3
+ */
+
+class KDEUI_EXPORT KListViewSearchLine : public KLineEdit
+{
+ Q_OBJECT
+
+public:
+
+ /**
+ * Constructs a KListViewSearchLine with \a listView being the KListView to
+ * be filtered.
+ *
+ * If \a listView is null then the widget will be disabled until a listview
+ * is set with setListView().
+ */
+ KListViewSearchLine(QWidget *parent = 0, KListView *listView = 0, const char *name = 0);
+
+ /**
+ * Constructs a KListViewSearchLine without any KListView to filter. The
+ * KListView object has to be set later with setListView().
+ */
+ KListViewSearchLine(QWidget *parent, const char *name);
+
+ /**
+ * Destroys the KListViewSearchLine.
+ */
+ virtual ~KListViewSearchLine();
+
+ /**
+ * Returns true if the search is case sensitive. This defaults to false.
+ *
+ * @see setCaseSensitive()
+ */
+ bool caseSensitive() const;
+
+ /**
+ * Returns the current list of columns that will be searched. If the
+ * returned list is empty all visible columns will be searched.
+ *
+ * @see setSearchColumns
+ */
+ QValueList<int> searchColumns() const;
+
+ /**
+ * If this is true (the default) then the parents of matched items will also
+ * be shown.
+ *
+ * @see setKeepParentsVisible()
+ */
+ bool keepParentsVisible() const;
+
+ /**
+ * Returns the listview that is currently filtered by the search.
+ *
+ * @see setListView()
+ */
+ KListView *listView() const;
+
+public slots:
+ /**
+ * Updates search to only make visible the items that match \a s. If
+ * \a s is null then the line edit's text will be used.
+ */
+ virtual void updateSearch(const QString &s = QString::null);
+
+ /**
+ * Make the search case sensitive or case insensitive.
+ *
+ * @see caseSenstive()
+ */
+ void setCaseSensitive(bool cs);
+
+ /**
+ * When a search is active on a list that's organized into a tree view if
+ * a parent or ancesestor of an item is does not match the search then it
+ * will be hidden and as such so too will any children that match.
+ *
+ * If this is set to true (the default) then the parents of matching items
+ * will be shown.
+ *
+ * @see keepParentsVisible
+ */
+ void setKeepParentsVisible(bool v);
+
+ /**
+ * Sets the list of columns to be searched. The default is to search all,
+ * visible columns which can be restored by passing \a columns as an empty
+ * list.
+ *
+ * @see searchColumns
+ */
+ void setSearchColumns(const QValueList<int> &columns);
+
+ /**
+ * Sets the KListView that is filtered by this search line. If \a lv is null
+ * then the widget will be disabled.
+ *
+ * @see listView()
+ */
+ void setListView(KListView *lv);
+
+protected:
+
+ /**
+ * Returns true if \a item matches the search \a s. This will be evaluated
+ * based on the value of caseSensitive(). This can be overridden in
+ * subclasses to implement more complicated matching schemes.
+ */
+ virtual bool itemMatches(const QListViewItem *item, const QString &s) const;
+
+ /**
+ * Re-implemented for internal reasons. API not affected.
+ *
+ * See QLineEdit::mousePressEvent().
+ */
+ virtual QPopupMenu *createPopupMenu();
+
+protected slots:
+ /**
+ * When keys are pressed a new search string is created and a timer is
+ * activated. The most recent search is activated when this timer runs out
+ * if another key has not yet been pressed.
+ *
+ * This method makes @param search the most recent search and starts the
+ * timer.
+ *
+ * Together with activateSearch() this makes it such that searches are not
+ * started until there is a short break in the users typing.
+ *
+ * @see activateSearch()
+ */
+ void queueSearch(const QString &search);
+
+ /**
+ * When the timer started with queueSearch() expires this slot is called.
+ * If there has been another timer started then this slot does nothing.
+ * However if there are no other pending searches this starts the list view
+ * search.
+ *
+ * @see queueSearch()
+ */
+ void activateSearch();
+
+private:
+
+ /**
+ * This is used in case parent items of matching items shouldn't be
+ * visible. It hides all items that don't match the search string.
+ */
+ void checkItemParentsNotVisible();
+
+ /**
+ * This is used in case parent items of matching items should be visible.
+ * It makes a recursive call to all children. It returns true if at least
+ * one item in the subtree with the given root item is visible.
+ */
+ bool checkItemParentsVisible(QListViewItem *item, QListViewItem *highestHiddenParent = 0);
+
+private slots:
+ void itemAdded(QListViewItem *item) const;
+ void listViewDeleted();
+ void searchColumnsMenuActivated(int);
+
+private:
+ class KListViewSearchLinePrivate;
+ KListViewSearchLinePrivate *d;
+};
+
+/**
+ * Creates a widget featuring a KListViewSearchLine, a label with the text
+ * "Search" and a button to clear the search.
+ *
+ * @since 3.4
+ */
+class KDEUI_EXPORT KListViewSearchLineWidget : public QHBox
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Creates a KListViewSearchLineWidget for \a listView with \a parent as the
+ * parent with and \a name.
+ */
+ KListViewSearchLineWidget(KListView *listView = 0, QWidget *parent = 0,
+ const char *name = 0);
+
+ /**
+ * Destroys the KListViewSearchLineWidget
+ */
+ ~KListViewSearchLineWidget();
+
+ /**
+ * Creates the search line. This can be useful to reimplement in cases where
+ * a KListViewSearchLine subclass is used.
+ */
+ virtual KListViewSearchLine *createSearchLine(KListView *listView);
+
+ /**
+ * Returns a pointer to the search line.
+ */
+ KListViewSearchLine *searchLine() const;
+
+protected slots:
+ /**
+ * Creates the widgets inside of the widget. This is called from the
+ * constructor via a single shot timer so that it it guaranteed to run
+ * after construction is complete. This makes it suitable for overriding in
+ * subclasses.
+ */
+ virtual void createWidgets();
+
+private slots:
+ void positionInToolBar();
+
+private:
+ class KListViewSearchLineWidgetPrivate;
+ KListViewSearchLineWidgetPrivate *d;
+};
+
+#endif
diff --git a/kdeui/kmainwindow.cpp b/kdeui/kmainwindow.cpp
new file mode 100644
index 000000000..119ff4a7e
--- /dev/null
+++ b/kdeui/kmainwindow.cpp
@@ -0,0 +1,1249 @@
+ /* This file is part of the KDE libraries
+ Copyright
+ (C) 2000 Reginald Stadlbauer (reggie@kde.org)
+ (C) 1997 Stephan Kulow (coolo@kde.org)
+ (C) 1997-2000 Sven Radej (radej@kde.org)
+ (C) 1997-2000 Matthias Ettrich (ettrich@kde.org)
+ (C) 1999 Chris Schlaeger (cs@kde.org)
+ (C) 2002 Joseph Wenninger (jowenn@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+#include "config.h"
+
+#include "kmainwindow.h"
+#include "kmainwindowiface.h"
+#include "ktoolbarhandler.h"
+#include "kwhatsthismanager_p.h"
+#include <qsessionmanager.h>
+#include <qobjectlist.h>
+#include <qstyle.h>
+#include <qlayout.h>
+#include <qwidgetlist.h>
+#include <qtimer.h>
+
+#include <kaccel.h>
+#include <kaction.h>
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <khelpmenu.h>
+#include <kmenubar.h>
+#include <kstatusbar.h>
+#include <kwin.h>
+#include <kedittoolbar.h>
+#include <kmainwindow.h>
+
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <kstaticdeleter.h>
+#if defined Q_WS_X11
+#include <netwm.h>
+#endif
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <assert.h>
+
+class KMainWindowPrivate {
+public:
+ bool showHelpMenu:1;
+
+ bool autoSaveSettings:1;
+ bool settingsDirty:1;
+ bool autoSaveWindowSize:1;
+ bool care_about_geometry:1;
+ bool shuttingDown:1;
+ QString autoSaveGroup;
+ KAccel * kaccel;
+ KMainWindowInterface *m_interface;
+ KDEPrivate::ToolBarHandler *toolBarHandler;
+ QTimer* settingsTimer;
+ KToggleAction *showStatusBarAction;
+ QRect defaultWindowSize;
+ QPtrList<QDockWindow> hiddenDockWindows;
+};
+
+QPtrList<KMainWindow>* KMainWindow::memberList = 0L;
+static bool no_query_exit = false;
+static KMWSessionManaged* ksm = 0;
+static KStaticDeleter<KMWSessionManaged> ksmd;
+
+class KMWSessionManaged : public KSessionManaged
+{
+public:
+ KMWSessionManaged()
+ {
+ }
+ ~KMWSessionManaged()
+ {
+ }
+ bool saveState( QSessionManager& )
+ {
+ KConfig* config = KApplication::kApplication()->sessionConfig();
+ if ( KMainWindow::memberList->first() ){
+ // According to Jochen Wilhelmy <digisnap@cs.tu-berlin.de>, this
+ // hook is useful for better document orientation
+ KMainWindow::memberList->first()->saveGlobalProperties(config);
+ }
+
+ QPtrListIterator<KMainWindow> it(*KMainWindow::memberList);
+ int n = 0;
+ for (it.toFirst(); it.current(); ++it){
+ n++;
+ it.current()->savePropertiesInternal(config, n);
+ }
+ config->setGroup(QString::fromLatin1("Number"));
+ config->writeEntry(QString::fromLatin1("NumberOfWindows"), n );
+ return true;
+ }
+
+ bool commitData( QSessionManager& sm )
+ {
+ // not really a fast method but the only compatible one
+ if ( sm.allowsInteraction() ) {
+ bool canceled = false;
+ QPtrListIterator<KMainWindow> it(*KMainWindow::memberList);
+ ::no_query_exit = true;
+ for (it.toFirst(); it.current() && !canceled;){
+ KMainWindow *window = *it;
+ ++it; // Update now, the current window might get deleted
+ if ( !window->testWState( Qt::WState_ForceHide ) ) {
+ QCloseEvent e;
+ QApplication::sendEvent( window, &e );
+ canceled = !e.isAccepted();
+ /* Don't even think_about deleting widgets with
+ Qt::WDestructiveClose flag set at this point. We
+ are faking a close event, but we are *not*_
+ closing the window. The purpose of the faked
+ close event is to prepare the application so it
+ can safely be quit without the user losing data
+ (possibly showing a message box "do you want to
+ save this or that?"). It is possible that the
+ session manager quits the application later
+ (emitting QApplication::aboutToQuit() when this
+ happens), but it is also possible that the user
+ cancels the shutdown, so the application will
+ continue to run.
+ */
+ }
+ }
+ ::no_query_exit = false;
+ if (canceled)
+ return false;
+
+ KMainWindow* last = 0;
+ for (it.toFirst(); it.current() && !canceled; ++it){
+ KMainWindow *window = *it;
+ if ( !window->testWState( Qt::WState_ForceHide ) ) {
+ last = window;
+ }
+ }
+ if ( last )
+ return last->queryExit();
+ // else
+ return true;
+ }
+
+ // the user wants it, the user gets it
+ return true;
+ }
+};
+
+static bool being_first = true;
+
+KMainWindow::KMainWindow( QWidget* parent, const char *name, WFlags f )
+ : QMainWindow( parent, name, f ), KXMLGUIBuilder( this ), helpMenu2( 0 ), factory_( 0 )
+{
+ initKMainWindow(name, 0);
+}
+
+KMainWindow::KMainWindow( int cflags, QWidget* parent, const char *name, WFlags f )
+ : QMainWindow( parent, name, f ), KXMLGUIBuilder( this ), helpMenu2( 0 ), factory_( 0 )
+{
+ initKMainWindow(name, cflags);
+}
+
+void KMainWindow::initKMainWindow(const char *name, int cflags)
+{
+ KWhatsThisManager::init ();
+ setDockMenuEnabled( false );
+ mHelpMenu = 0;
+ kapp->setTopWidget( this );
+ actionCollection()->setWidget( this );
+ connect(kapp, SIGNAL(shutDown()), this, SLOT(shuttingDown()));
+ if( !memberList )
+ memberList = new QPtrList<KMainWindow>;
+
+ if ( !ksm )
+ ksm = ksmd.setObject(ksm, new KMWSessionManaged());
+ // set a unique object name. Required by session management.
+ QCString objname;
+ QCString s;
+ int unusedNumber;
+ if ( !name )
+ { // no name given
+ objname = kapp->instanceName() + "-mainwindow#";
+ s = objname + '1'; // start adding number immediately
+ unusedNumber = 1;
+ }
+ else if( name[0] != '\0' && name[ strlen( name ) - 1 ] == '#' )
+ { // trailing # - always add a number
+ objname = name;
+ s = objname + '1'; // start adding number immediately
+ unusedNumber = 1;
+ }
+ else
+ {
+ objname = name;
+ s = objname;
+ unusedNumber = 0; // add numbers only when needed
+ }
+ for(;;) {
+ QWidgetList* list = kapp->topLevelWidgets();
+ QWidgetListIt it( *list );
+ bool found = false;
+ for( QWidget* w = it.current();
+ w != NULL;
+ ++it, w = it.current())
+ if( w != this && w->name() == s )
+ {
+ found = true;
+ break;
+ }
+ delete list;
+ if( !found )
+ break;
+ s.setNum( ++unusedNumber );
+ s = objname + s;
+ }
+ setName( s );
+
+ memberList->append( this );
+
+ d = new KMainWindowPrivate;
+ d->showHelpMenu = true;
+ d->settingsDirty = false;
+ d->autoSaveSettings = false;
+ d->autoSaveWindowSize = true; // for compatibility
+ d->kaccel = actionCollection()->kaccel();
+ d->toolBarHandler = 0;
+ d->settingsTimer = 0;
+ d->showStatusBarAction = NULL;
+ d->shuttingDown = false;
+ if ((d->care_about_geometry = being_first)) {
+ being_first = false;
+ if ( kapp->geometryArgument().isNull() ) // if there is no geometry, it doesn't mater
+ d->care_about_geometry = false;
+ else
+ parseGeometry(false);
+ }
+
+ setCaption( kapp->caption() );
+ if ( cflags & NoDCOPObject)
+ d->m_interface = 0;
+ else
+ d->m_interface = new KMainWindowInterface(this);
+
+ if (!kapp->authorize("movable_toolbars"))
+ setDockWindowsMovable(false);
+}
+
+KAction *KMainWindow::toolBarMenuAction()
+{
+ if ( !d->toolBarHandler )
+ return 0;
+
+ return d->toolBarHandler->toolBarMenuAction();
+}
+
+
+void KMainWindow::setupToolbarMenuActions()
+{
+ if ( d->toolBarHandler )
+ d->toolBarHandler->setupActions();
+}
+
+void KMainWindow::parseGeometry(bool parsewidth)
+{
+ assert ( !kapp->geometryArgument().isNull() );
+ assert ( d->care_about_geometry );
+
+#if defined Q_WS_X11
+ int x, y;
+ int w, h;
+ int m = XParseGeometry( kapp->geometryArgument().latin1(), &x, &y, (unsigned int*)&w, (unsigned int*)&h);
+ if (parsewidth) {
+ QSize minSize = minimumSize();
+ QSize maxSize = maximumSize();
+ if ( !(m & WidthValue) )
+ w = width();
+ if ( !(m & HeightValue) )
+ h = height();
+ w = QMIN(w,maxSize.width());
+ h = QMIN(h,maxSize.height());
+ w = QMAX(w,minSize.width());
+ h = QMAX(h,minSize.height());
+ resize(w, h);
+ } else {
+ if ( parsewidth && !(m & XValue) )
+ x = geometry().x();
+ if ( parsewidth && !(m & YValue) )
+ y = geometry().y();
+ if ( (m & XNegative) )
+ x = KApplication::desktop()->width() + x - w;
+ if ( (m & YNegative) )
+ y = KApplication::desktop()->height() + y - h;
+ move(x, y);
+ }
+#endif
+}
+
+KMainWindow::~KMainWindow()
+{
+ delete d->settingsTimer;
+ QMenuBar* mb = internalMenuBar();
+ delete mb;
+ delete d->m_interface;
+ delete d;
+ memberList->remove( this );
+}
+
+KPopupMenu* KMainWindow::helpMenu( const QString &aboutAppText, bool showWhatsThis )
+{
+ if( !mHelpMenu ) {
+ if ( aboutAppText.isEmpty() )
+ mHelpMenu = new KHelpMenu( this, instance()->aboutData(), showWhatsThis);
+ else
+ mHelpMenu = new KHelpMenu( this, aboutAppText, showWhatsThis );
+
+ if ( !mHelpMenu )
+ return 0;
+ connect( mHelpMenu, SIGNAL( showAboutApplication() ),
+ this, SLOT( showAboutApplication() ) );
+ }
+
+ return mHelpMenu->menu();
+}
+
+KPopupMenu* KMainWindow::customHelpMenu( bool showWhatsThis )
+{
+ if( !mHelpMenu ) {
+ mHelpMenu = new KHelpMenu( this, QString::null, showWhatsThis );
+ connect( mHelpMenu, SIGNAL( showAboutApplication() ),
+ this, SLOT( showAboutApplication() ) );
+ }
+
+ return mHelpMenu->menu();
+}
+
+bool KMainWindow::canBeRestored( int number )
+{
+ if ( !kapp->isRestored() )
+ return false;
+ KConfig *config = kapp->sessionConfig();
+ if ( !config )
+ return false;
+ config->setGroup( QString::fromLatin1("Number") );
+ int n = config->readNumEntry( QString::fromLatin1("NumberOfWindows") , 1 );
+ return number >= 1 && number <= n;
+}
+
+const QString KMainWindow::classNameOfToplevel( int number )
+{
+ if ( !kapp->isRestored() )
+ return QString::null;
+ KConfig *config = kapp->sessionConfig();
+ if ( !config )
+ return QString::null;
+ QString s;
+ s.setNum( number );
+ s.prepend( QString::fromLatin1("WindowProperties") );
+ config->setGroup( s );
+ if ( !config->hasKey( QString::fromLatin1("ClassName") ) )
+ return QString::null;
+ else
+ return config->readEntry( QString::fromLatin1("ClassName") );
+}
+
+void KMainWindow::show()
+{
+ QMainWindow::show();
+
+ for ( QPtrListIterator<QDockWindow> it( d->hiddenDockWindows ); it.current(); ++it )
+ it.current()->show();
+
+ d->hiddenDockWindows.clear();
+}
+
+void KMainWindow::hide()
+{
+ if ( isVisible() ) {
+
+ d->hiddenDockWindows.clear();
+
+ QObjectList *list = queryList( "QDockWindow" );
+ for( QObjectListIt it( *list ); it.current(); ++it ) {
+ QDockWindow *dw = (QDockWindow*)it.current();
+ if ( dw->isTopLevel() && dw->isVisible() ) {
+ d->hiddenDockWindows.append( dw );
+ dw->hide();
+ }
+ }
+ delete list;
+ }
+
+ QWidget::hide();
+}
+
+bool KMainWindow::restore( int number, bool show )
+{
+ if ( !canBeRestored( number ) )
+ return false;
+ KConfig *config = kapp->sessionConfig();
+ if ( readPropertiesInternal( config, number ) ){
+ if ( show )
+ KMainWindow::show();
+ return false;
+ }
+ return false;
+}
+
+KXMLGUIFactory *KMainWindow::guiFactory()
+{
+ if ( !factory_ )
+ factory_ = new KXMLGUIFactory( this, this, "guifactory" );
+ return factory_;
+}
+
+int KMainWindow::configureToolbars()
+{
+ saveMainWindowSettings(KGlobal::config());
+ KEditToolbar dlg(actionCollection(), xmlFile(), true, this);
+ connect(&dlg, SIGNAL(newToolbarConfig()), SLOT(saveNewToolbarConfig()));
+ return dlg.exec();
+}
+
+void KMainWindow::saveNewToolbarConfig()
+{
+ createGUI(xmlFile());
+ applyMainWindowSettings( KGlobal::config() );
+}
+
+void KMainWindow::setupGUI( int options, const QString & xmlfile ) {
+ setupGUI(QSize(), options, xmlfile);
+}
+
+void KMainWindow::setupGUI( QSize defaultSize, int options, const QString & xmlfile ) {
+ if( options & Keys ){
+ KStdAction::keyBindings(guiFactory(),
+ SLOT(configureShortcuts()), actionCollection());
+ }
+
+ if( (options & StatusBar) && internalStatusBar() ){
+ createStandardStatusBarAction();
+ }
+
+ if( options & ToolBar ){
+ setStandardToolBarMenuEnabled( true );
+ KStdAction::configureToolbars(this,
+ SLOT(configureToolbars() ), actionCollection());
+ }
+
+ if( options & Create ){
+ createGUI(xmlfile,false);
+ }
+
+ if( options & Save ){
+ // setupGUI() is typically called in the constructor before show(),
+ // so the default window size will be incorrect unless the application
+ // hard coded the size which they should try not to do (i.e. use
+ // size hints).
+ if(initialGeometrySet())
+ {
+ // Do nothing...
+ }
+ else if(defaultSize.isValid())
+ {
+ resize(defaultSize);
+ }
+ else if(!isShown())
+ {
+ adjustSize();
+ }
+ setAutoSaveSettings();
+ }
+
+}
+
+void KMainWindow::createGUI( const QString &xmlfile, bool _conserveMemory )
+{
+ // disabling the updates prevents unnecessary redraws
+ setUpdatesEnabled( false );
+
+ // just in case we are rebuilding, let's remove our old client
+ guiFactory()->removeClient( this );
+
+ // make sure to have an empty GUI
+ QMenuBar* mb = internalMenuBar();
+ if ( mb )
+ mb->clear();
+
+ (void)toolBarIterator(); // make sure toolbarList is most-up-to-date
+ toolbarList.setAutoDelete( true );
+ toolbarList.clear();
+ toolbarList.setAutoDelete( false );
+
+ // don't build a help menu unless the user ask for it
+ if (d->showHelpMenu) {
+ // we always want a help menu
+ if (!helpMenu2)
+ helpMenu2 = new KHelpMenu(this, instance()->aboutData(), true,
+ actionCollection());
+ }
+
+ // we always want to load in our global standards file
+ setXMLFile( locate( "config", "ui/ui_standards.rc", instance() ) );
+
+ // now, merge in our local xml file. if this is null, then that
+ // means that we will be only using the global file
+ if ( !xmlfile.isNull() ) {
+ setXMLFile( xmlfile, true );
+ } else {
+ QString auto_file(instance()->instanceName() + "ui.rc");
+ setXMLFile( auto_file, true );
+ }
+
+ // make sure we don't have any state saved already
+ setXMLGUIBuildDocument( QDomDocument() );
+
+ // do the actual GUI building
+ guiFactory()->addClient( this );
+
+ // try and get back *some* of our memory
+ if ( _conserveMemory )
+ {
+ // before freeing the memory allocated by the DOM document we also
+ // free all memory allocated internally in the KXMLGUIFactory for
+ // the menubar and the toolbars . This however implies that we
+ // have to take care of deleting those widgets ourselves. For
+ // destruction this is no problem, but when rebuilding we have
+ // to take care of that (and we want to rebuild the GUI when
+ // using stuff like the toolbar editor ).
+ // In addition we have to take care of not removing containers
+ // like popupmenus, defined in the XML document.
+ // this code should probably go into a separate method in KMainWindow.
+ // there's just one problem: I'm bad in finding names ;-) , so
+ // I skipped this ;-)
+
+ QDomDocument doc = domDocument();
+
+ for( QDomNode n = doc.documentElement().firstChild();
+ !n.isNull(); n = n.nextSibling())
+ {
+ QDomElement e = n.toElement();
+
+ if ( e.tagName().lower() == "toolbar" )
+ factory_->resetContainer( e.attribute( "name" ) );
+ else if ( e.tagName().lower() == "menubar" )
+ factory_->resetContainer( e.tagName(), true );
+ }
+
+ conserveMemory();
+ }
+
+ setUpdatesEnabled( true );
+ updateGeometry();
+}
+
+void KMainWindow::setHelpMenuEnabled(bool showHelpMenu)
+{
+ d->showHelpMenu = showHelpMenu;
+}
+
+bool KMainWindow::isHelpMenuEnabled()
+{
+ return d->showHelpMenu;
+}
+
+void KMainWindow::setCaption( const QString &caption )
+{
+ setPlainCaption( kapp->makeStdCaption(caption) );
+}
+
+void KMainWindow::setCaption( const QString &caption, bool modified )
+{
+ setPlainCaption( kapp->makeStdCaption(caption, true, modified) );
+}
+
+void KMainWindow::setPlainCaption( const QString &caption )
+{
+ QMainWindow::setCaption( caption );
+#if defined Q_WS_X11
+ NETWinInfo info( qt_xdisplay(), winId(), qt_xrootwin(), 0 );
+ info.setName( caption.utf8().data() );
+#endif
+}
+
+void KMainWindow::appHelpActivated( void )
+{
+ if( !mHelpMenu ) {
+ mHelpMenu = new KHelpMenu( this );
+ if ( !mHelpMenu )
+ return;
+ }
+ mHelpMenu->appHelpActivated();
+}
+
+void KMainWindow::slotStateChanged(const QString &newstate)
+{
+ stateChanged(newstate, KXMLGUIClient::StateNoReverse);
+}
+
+/*
+ * Get rid of this for KDE 4.0
+ */
+void KMainWindow::slotStateChanged(const QString &newstate,
+ KXMLGUIClient::ReverseStateChange reverse)
+{
+ stateChanged(newstate, reverse);
+}
+
+/*
+ * Enable this for KDE 4.0
+ */
+// void KMainWindow::slotStateChanged(const QString &newstate,
+// bool reverse)
+// {
+// stateChanged(newstate,
+// reverse ? KXMLGUIClient::StateReverse : KXMLGUIClient::StateNoReverse);
+// }
+
+void KMainWindow::closeEvent ( QCloseEvent *e )
+{
+ // Save settings if auto-save is enabled, and settings have changed
+ if (d->settingsDirty && d->autoSaveSettings)
+ saveAutoSaveSettings();
+
+ if (queryClose()) {
+ e->accept();
+
+ int not_withdrawn = 0;
+ QPtrListIterator<KMainWindow> it(*KMainWindow::memberList);
+ for (it.toFirst(); it.current(); ++it){
+ if ( !it.current()->isHidden() && it.current()->isTopLevel() && it.current() != this )
+ not_withdrawn++;
+ }
+
+ if ( !no_query_exit && not_withdrawn <= 0 ) { // last window close accepted?
+ if ( queryExit() && !kapp->sessionSaving() && !d->shuttingDown ) { // Yes, Quit app?
+ // don't call queryExit() twice
+ disconnect(kapp, SIGNAL(shutDown()), this, SLOT(shuttingDown()));
+ d->shuttingDown = true;
+ kapp->deref(); // ...and quit application.
+ } else {
+ // cancel closing, it's stupid to end up with no windows at all....
+ e->ignore();
+ }
+ }
+ }
+}
+
+bool KMainWindow::queryExit()
+{
+ return true;
+}
+
+bool KMainWindow::queryClose()
+{
+ return true;
+}
+
+void KMainWindow::saveGlobalProperties( KConfig* )
+{
+}
+
+void KMainWindow::readGlobalProperties( KConfig* )
+{
+}
+
+#if defined(KDE_COMPAT)
+void KMainWindow::updateRects()
+{
+}
+#endif
+
+void KMainWindow::showAboutApplication()
+{
+}
+
+void KMainWindow::savePropertiesInternal( KConfig *config, int number )
+{
+ bool oldASWS = d->autoSaveWindowSize;
+ d->autoSaveWindowSize = true; // make saveMainWindowSettings save the window size
+
+ QString s;
+ s.setNum(number);
+ s.prepend(QString::fromLatin1("WindowProperties"));
+ config->setGroup(s);
+
+ // store objectName, className, Width and Height for later restoring
+ // (Only useful for session management)
+ config->writeEntry(QString::fromLatin1("ObjectName"), name());
+ config->writeEntry(QString::fromLatin1("ClassName"), className());
+
+ saveMainWindowSettings(config); // Menubar, statusbar and Toolbar settings.
+
+ s.setNum(number);
+ config->setGroup(s);
+ saveProperties(config);
+
+ d->autoSaveWindowSize = oldASWS;
+}
+
+void KMainWindow::saveMainWindowSettings(KConfig *config, const QString &configGroup)
+{
+ kdDebug(200) << "KMainWindow::saveMainWindowSettings " << configGroup << endl;
+ QString oldGroup;
+
+ if (!configGroup.isEmpty())
+ {
+ oldGroup = config->group();
+ config->setGroup(configGroup);
+ }
+
+ // Called by session management - or if we want to save the window size anyway
+ if ( d->autoSaveWindowSize )
+ saveWindowSize( config );
+
+ QStatusBar* sb = internalStatusBar();
+ if (sb) {
+ if(!config->hasDefault("StatusBar") && !sb->isHidden() )
+ config->revertToDefault("StatusBar");
+ else
+ config->writeEntry("StatusBar", sb->isHidden() ? "Disabled" : "Enabled");
+ }
+
+ QMenuBar* mb = internalMenuBar();
+ if (mb) {
+ QString MenuBar = QString::fromLatin1("MenuBar");
+ if(!config->hasDefault("MenuBar") && !mb->isHidden() )
+ config->revertToDefault("MenuBar");
+ else
+ config->writeEntry("MenuBar", mb->isHidden() ? "Disabled" : "Enabled");
+ }
+
+ int n = 1; // Toolbar counter. toolbars are counted from 1,
+ KToolBar *toolbar = 0;
+ QPtrListIterator<KToolBar> it( toolBarIterator() );
+ while ( ( toolbar = it.current() ) ) {
+ ++it;
+ QString group;
+ if (!configGroup.isEmpty())
+ {
+ // Give a number to the toolbar, but prefer a name if there is one,
+ // because there's no real guarantee on the ordering of toolbars
+ group = (!::qstrcmp(toolbar->name(), "unnamed") ? QString::number(n) : QString(" ")+toolbar->name());
+ group.prepend(" Toolbar");
+ group.prepend(configGroup);
+ }
+ toolbar->saveSettings(config, group);
+ n++;
+ }
+ if (!configGroup.isEmpty())
+ config->setGroup(oldGroup);
+}
+
+void KMainWindow::setStandardToolBarMenuEnabled( bool enable )
+{
+ if ( enable ) {
+ if ( d->toolBarHandler )
+ return;
+
+ d->toolBarHandler = new KDEPrivate::ToolBarHandler( this );
+
+ if ( factory() )
+ factory()->addClient( d->toolBarHandler );
+ } else {
+ if ( !d->toolBarHandler )
+ return;
+
+ if ( factory() )
+ factory()->removeClient( d->toolBarHandler );
+
+ delete d->toolBarHandler;
+ d->toolBarHandler = 0;
+ }
+}
+
+bool KMainWindow::isStandardToolBarMenuEnabled() const
+{
+ return ( d->toolBarHandler );
+}
+
+void KMainWindow::createStandardStatusBarAction(){
+ if(!d->showStatusBarAction){
+ d->showStatusBarAction = KStdAction::showStatusbar(this, SLOT(setSettingsDirty()), actionCollection());
+ KStatusBar *sb = statusBar(); // Creates statusbar if it doesn't exist already.
+ connect(d->showStatusBarAction, SIGNAL(toggled(bool)), sb, SLOT(setShown(bool)));
+ d->showStatusBarAction->setChecked(sb->isHidden());
+ }
+}
+
+bool KMainWindow::readPropertiesInternal( KConfig *config, int number )
+{
+ if ( number == 1 )
+ readGlobalProperties( config );
+
+ // in order they are in toolbar list
+ QString s;
+ s.setNum(number);
+ s.prepend(QString::fromLatin1("WindowProperties"));
+
+ config->setGroup(s);
+
+ // restore the object name (window role)
+ if ( config->hasKey(QString::fromLatin1("ObjectName" )) )
+ setName( config->readEntry(QString::fromLatin1("ObjectName")).latin1()); // latin1 is right here
+
+ applyMainWindowSettings(config); // Menubar, statusbar and toolbar settings.
+
+ s.setNum(number);
+ config->setGroup(s);
+ readProperties(config);
+ return true;
+}
+
+void KMainWindow::applyMainWindowSettings(KConfig *config, const QString &configGroup)
+{
+ return applyMainWindowSettings(config,configGroup,false);
+}
+
+void KMainWindow::applyMainWindowSettings(KConfig *config, const QString &configGroup,bool force)
+{
+ kdDebug(200) << "KMainWindow::applyMainWindowSettings" << endl;
+
+ KConfigGroupSaver saver( config, configGroup.isEmpty() ? config->group() : configGroup );
+
+ restoreWindowSize(config);
+
+ QStatusBar* sb = internalStatusBar();
+ if (sb) {
+ QString entry = config->readEntry("StatusBar", "Enabled");
+ if ( entry == "Disabled" )
+ sb->hide();
+ else
+ sb->show();
+ if(d->showStatusBarAction)
+ d->showStatusBarAction->setChecked(!sb->isHidden());
+ }
+
+ QMenuBar* mb = internalMenuBar();
+ if (mb) {
+ QString entry = config->readEntry ("MenuBar", "Enabled");
+ if ( entry == "Disabled" )
+ mb->hide();
+ else
+ mb->show();
+ }
+
+ int n = 1; // Toolbar counter. toolbars are counted from 1,
+ KToolBar *toolbar;
+ QPtrListIterator<KToolBar> it( toolBarIterator() ); // must use own iterator
+
+ for ( ; it.current(); ++it) {
+ toolbar= it.current();
+ QString group;
+ if (!configGroup.isEmpty())
+ {
+ // Give a number to the toolbar, but prefer a name if there is one,
+ // because there's no real guarantee on the ordering of toolbars
+ group = (!::qstrcmp(toolbar->name(), "unnamed") ? QString::number(n) : QString(" ")+toolbar->name());
+ group.prepend(" Toolbar");
+ group.prepend(configGroup);
+ }
+ toolbar->applySettings(config, group, force);
+ n++;
+ }
+
+ finalizeGUI( true );
+}
+
+void KMainWindow::finalizeGUI( bool force )
+{
+ //kdDebug(200) << "KMainWindow::finalizeGUI force=" << force << endl;
+ // The whole reason for this is that moveToolBar relies on the indexes
+ // of the other toolbars, so in theory it should be called only once per
+ // toolbar, but in increasing order of indexes.
+ // Since we can't do that immediately, we move them, and _then_
+ // we call positionYourself again for each of them, but this time
+ // the toolbariterator should give them in the proper order.
+ // Both the XMLGUI and applySettings call this, hence "force" for the latter.
+ QPtrListIterator<KToolBar> it( toolBarIterator() );
+ for ( ; it.current() ; ++it ) {
+ it.current()->positionYourself( force );
+ }
+
+ d->settingsDirty = false;
+}
+
+void KMainWindow::saveWindowSize( KConfig * config ) const
+{
+ int scnum = QApplication::desktop()->screenNumber(parentWidget());
+ QRect desk = QApplication::desktop()->screenGeometry(scnum);
+ int w, h;
+#if defined Q_WS_X11
+ // save maximalization as desktop size + 1 in that direction
+ KWin::WindowInfo info = KWin::windowInfo( winId(), NET::WMState );
+ w = info.state() & NET::MaxHoriz ? desk.width() + 1 : width();
+ h = info.state() & NET::MaxVert ? desk.height() + 1 : height();
+#else
+ if (isMaximized()) {
+ w = desk.width() + 1;
+ h = desk.height() + 1;
+ }
+ //TODO: add "Maximized" property instead "+1" hack
+#endif
+ QRect size( desk.width(), w, desk.height(), h );
+ bool defaultSize = (size == d->defaultWindowSize);
+ QString widthString = QString::fromLatin1("Width %1").arg(desk.width());
+ QString heightString = QString::fromLatin1("Height %1").arg(desk.height());
+ if (!config->hasDefault(widthString) && defaultSize)
+ config->revertToDefault(widthString);
+ else
+ config->writeEntry(widthString, w );
+
+ if (!config->hasDefault(heightString) && defaultSize)
+ config->revertToDefault(heightString);
+ else
+ config->writeEntry(heightString, h );
+}
+
+void KMainWindow::restoreWindowSize( KConfig * config )
+{
+ if (d->care_about_geometry) {
+ parseGeometry(true);
+ } else {
+ // restore the size
+ int scnum = QApplication::desktop()->screenNumber(parentWidget());
+ QRect desk = QApplication::desktop()->screenGeometry(scnum);
+ if ( d->defaultWindowSize.isNull() ) // only once
+ d->defaultWindowSize = QRect(desk.width(), width(), desk.height(), height()); // store default values
+ QSize size( config->readNumEntry( QString::fromLatin1("Width %1").arg(desk.width()), 0 ),
+ config->readNumEntry( QString::fromLatin1("Height %1").arg(desk.height()), 0 ) );
+ if (size.isEmpty()) {
+ // try the KDE 2.0 way
+ size = QSize( config->readNumEntry( QString::fromLatin1("Width"), 0 ),
+ config->readNumEntry( QString::fromLatin1("Height"), 0 ) );
+ if (!size.isEmpty()) {
+ // make sure the other resolutions don't get old settings
+ config->writeEntry( QString::fromLatin1("Width"), 0 );
+ config->writeEntry( QString::fromLatin1("Height"), 0 );
+ }
+ }
+ if ( !size.isEmpty() ) {
+#ifdef Q_WS_X11
+ int state = ( size.width() > desk.width() ? NET::MaxHoriz : 0 )
+ | ( size.height() > desk.height() ? NET::MaxVert : 0 );
+ if(( state & NET::Max ) == NET::Max )
+ ; // no resize
+ else if(( state & NET::MaxHoriz ) == NET::MaxHoriz )
+ resize( width(), size.height());
+ else if(( state & NET::MaxVert ) == NET::MaxVert )
+ resize( size.width(), height());
+ else
+ resize( size );
+ // QWidget::showMaximized() is both insufficient and broken
+ KWin::setState( winId(), state );
+#else
+ if (size.width() > desk.width() || size.height() > desk.height())
+ setWindowState( WindowMaximized );
+ else
+ resize( size );
+#endif
+ }
+ }
+}
+
+bool KMainWindow::initialGeometrySet() const
+{
+ return d->care_about_geometry;
+}
+
+void KMainWindow::ignoreInitialGeometry()
+{
+ d->care_about_geometry = false;
+}
+
+void KMainWindow::setSettingsDirty()
+{
+ //kdDebug(200) << "KMainWindow::setSettingsDirty" << endl;
+ d->settingsDirty = true;
+ if ( d->autoSaveSettings )
+ {
+ // Use a timer to save "immediately" user-wise, but not too immediately
+ // (to compress calls and save only once, in case of multiple changes)
+ if ( !d->settingsTimer )
+ {
+ d->settingsTimer = new QTimer( this );
+ connect( d->settingsTimer, SIGNAL( timeout() ), SLOT( saveAutoSaveSettings() ) );
+ }
+ d->settingsTimer->start( 500, true );
+ }
+}
+
+bool KMainWindow::settingsDirty() const
+{
+ return d->settingsDirty;
+}
+
+QString KMainWindow::settingsGroup() const
+{
+ return d->autoSaveGroup;
+}
+
+void KMainWindow::setAutoSaveSettings( const QString & groupName, bool saveWindowSize )
+{
+ d->autoSaveSettings = true;
+ d->autoSaveGroup = groupName;
+ d->autoSaveWindowSize = saveWindowSize;
+ // Get notified when the user moves a toolbar around
+ disconnect( this, SIGNAL( dockWindowPositionChanged( QDockWindow * ) ),
+ this, SLOT( setSettingsDirty() ) );
+ connect( this, SIGNAL( dockWindowPositionChanged( QDockWindow * ) ),
+ this, SLOT( setSettingsDirty() ) );
+
+ // Now read the previously saved settings
+ applyMainWindowSettings( KGlobal::config(), groupName );
+}
+
+void KMainWindow::resetAutoSaveSettings()
+{
+ d->autoSaveSettings = false;
+ if ( d->settingsTimer )
+ d->settingsTimer->stop();
+}
+
+bool KMainWindow::autoSaveSettings() const
+{
+ return d->autoSaveSettings;
+}
+
+QString KMainWindow::autoSaveGroup() const
+{
+ return d->autoSaveGroup;
+}
+
+void KMainWindow::saveAutoSaveSettings()
+{
+ Q_ASSERT( d->autoSaveSettings );
+ //kdDebug(200) << "KMainWindow::saveAutoSaveSettings -> saving settings" << endl;
+ saveMainWindowSettings( KGlobal::config(), d->autoSaveGroup );
+ KGlobal::config()->sync();
+ d->settingsDirty = false;
+ if ( d->settingsTimer )
+ d->settingsTimer->stop();
+}
+
+void KMainWindow::resizeEvent( QResizeEvent * )
+{
+ if ( d->autoSaveWindowSize )
+ setSettingsDirty();
+}
+
+bool KMainWindow::hasMenuBar()
+{
+ return (internalMenuBar());
+}
+
+KMenuBar *KMainWindow::menuBar()
+{
+ KMenuBar * mb = internalMenuBar();
+ if ( !mb ) {
+ mb = new KMenuBar( this );
+ // trigger a re-layout and trigger a call to the private
+ // setMenuBar method.
+ QMainWindow::menuBar();
+ }
+ return mb;
+}
+
+KStatusBar *KMainWindow::statusBar()
+{
+ KStatusBar * sb = internalStatusBar();
+ if ( !sb ) {
+ sb = new KStatusBar( this );
+ // trigger a re-layout and trigger a call to the private
+ // setStatusBar method.
+ QMainWindow::statusBar();
+ }
+ return sb;
+}
+
+void KMainWindow::shuttingDown()
+{
+ // Needed for Qt <= 3.0.3 at least to prevent reentrancy
+ // when queryExit() shows a dialog. Check before removing!
+ static bool reentrancy_protection = false;
+ if (!reentrancy_protection)
+ {
+ reentrancy_protection = true;
+ // call the virtual queryExit
+ queryExit();
+ reentrancy_protection = false;
+ }
+
+}
+
+KMenuBar *KMainWindow::internalMenuBar()
+{
+ QObjectList *l = queryList( "KMenuBar", 0, false, false );
+ if ( !l || !l->first() ) {
+ delete l;
+ return 0;
+ }
+
+ KMenuBar *m = (KMenuBar*)l->first();
+ delete l;
+ return m;
+}
+
+KStatusBar *KMainWindow::internalStatusBar()
+{
+ QObjectList *l = queryList( "KStatusBar", 0, false, false );
+ if ( !l || !l->first() ) {
+ delete l;
+ return 0;
+ }
+
+ KStatusBar *s = (KStatusBar*)l->first();
+ delete l;
+ return s;
+}
+
+void KMainWindow::childEvent( QChildEvent* e)
+{
+ QMainWindow::childEvent( e );
+}
+
+KToolBar *KMainWindow::toolBar( const char * name )
+{
+ if (!name)
+ name = "mainToolBar";
+ KToolBar *tb = (KToolBar*)child( name, "KToolBar" );
+ if ( tb )
+ return tb;
+ bool honor_mode = (!strcmp(name, "mainToolBar"));
+
+ if ( builderClient() )
+ return new KToolBar(this, name, honor_mode); // XMLGUI constructor
+ else
+ return new KToolBar(this, DockTop, false, name, honor_mode ); // non-XMLGUI
+}
+
+QPtrListIterator<KToolBar> KMainWindow::toolBarIterator()
+{
+ toolbarList.clear();
+ QPtrList<QToolBar> lst;
+ for ( int i = (int)QMainWindow::DockUnmanaged; i <= (int)DockMinimized; ++i ) {
+ lst = toolBars( (ToolBarDock)i );
+ for ( QToolBar *tb = lst.first(); tb; tb = lst.next() ) {
+ if ( !tb->inherits( "KToolBar" ) )
+ continue;
+ toolbarList.append( (KToolBar*)tb );
+ }
+ }
+ return QPtrListIterator<KToolBar>( toolbarList );
+}
+
+KAccel * KMainWindow::accel()
+{
+ if ( !d->kaccel )
+ d->kaccel = new KAccel( this, "kmw-kaccel" );
+ return d->kaccel;
+}
+
+void KMainWindow::paintEvent( QPaintEvent * pe )
+{
+ QMainWindow::paintEvent(pe); //Upcall to handle SH_MainWindow_SpaceBelowMenuBar rendering
+}
+
+QSize KMainWindow::sizeForCentralWidgetSize(QSize size)
+{
+ KToolBar *tb = (KToolBar*)child( "mainToolBar", "KToolBar" );
+ if (tb && !tb->isHidden()) {
+ switch( tb->barPos() )
+ {
+ case KToolBar::Top:
+ case KToolBar::Bottom:
+ size += QSize(0, tb->sizeHint().height());
+ break;
+
+ case KToolBar::Left:
+ case KToolBar::Right:
+ size += QSize(toolBar()->sizeHint().width(), 0);
+ break;
+
+ case KToolBar::Flat:
+ size += QSize(0, 3+kapp->style().pixelMetric( QStyle::PM_DockWindowHandleExtent ));
+ break;
+
+ default:
+ break;
+ }
+ }
+ KMenuBar *mb = internalMenuBar();
+ if (mb && !mb->isHidden()) {
+ size += QSize(0,mb->heightForWidth(size.width()));
+ if (style().styleHint(QStyle::SH_MainWindow_SpaceBelowMenuBar, this))
+ size += QSize( 0, dockWindowsMovable() ? 1 : 2);
+ }
+ QStatusBar *sb = internalStatusBar();
+ if( sb && !sb->isHidden() )
+ size += QSize(0, sb->sizeHint().height());
+
+ return size;
+}
+
+#if KDE_IS_VERSION( 3, 9, 0 )
+#ifdef __GNUC__
+#warning Remove, should be in Qt
+#endif
+#endif
+void KMainWindow::setIcon( const QPixmap& p )
+{
+ QMainWindow::setIcon( p );
+#ifdef Q_WS_X11
+ // Qt3 doesn't support _NET_WM_ICON, but KApplication::setTopWidget(), which
+ // is used by KMainWindow, sets it
+ KWin::setIcons( winId(), p, QPixmap());
+#endif
+}
+
+QPtrList<KMainWindow>* KMainWindow::getMemberList() { return memberList; }
+
+// why do we support old gcc versions? using KXMLGUIBuilder::finalizeGUI;
+// DF: because they compile KDE much faster :)
+void KMainWindow::finalizeGUI( KXMLGUIClient *client )
+{ KXMLGUIBuilder::finalizeGUI( client ); }
+
+void KMainWindow::virtual_hook( int id, void* data )
+{ KXMLGUIBuilder::virtual_hook( id, data );
+ KXMLGUIClient::virtual_hook( id, data ); }
+
+
+
+#include "kmainwindow.moc"
+
diff --git a/kdeui/kmainwindow.h b/kdeui/kmainwindow.h
new file mode 100644
index 000000000..00d3aaee6
--- /dev/null
+++ b/kdeui/kmainwindow.h
@@ -0,0 +1,1067 @@
+/*
+ This file is part of the KDE libraries
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+
+*/
+
+#ifndef KMAINWINDOW_H
+#define KMAINWINDOW_H
+
+#include "kxmlguifactory.h"
+#include "kxmlguiclient.h"
+#include "kxmlguibuilder.h"
+#include <qmainwindow.h>
+#include <qmetaobject.h>
+#include <ktoolbar.h>
+
+class KPopupMenu;
+class KXMLGUIFactory;
+class KConfig;
+class KHelpMenu;
+class KStatusBar;
+class QStatusBar;
+class KMenuBar;
+class KMWSessionManaged;
+class KMainWindowPrivate;
+class KAccel;
+class KToolBarMenuAction;
+class DCOPObject;
+
+#define KDE_DEFAULT_WINDOWFLAGS WType_TopLevel | WDestructiveClose
+
+
+/**
+ * @short %KDE top level main window
+ *
+ * Top level widget that provides toolbars, a status line and a frame.
+ *
+ * It should be used as a top level (parent-less) widget.
+ * It manages the geometry for all its children, including your
+ * main widget.
+ *
+ * Normally, you will inherit from KMainWindow,
+ * then construct (or use some existing) widget as
+ * your main view. You can set only one main view.
+ *
+ * You can add as many toolbars as you like. There can be only one menubar
+ * and only one statusbar.
+ *
+ * The toolbars, menubar, and statusbar can be created by the
+ * KMainWindow and - unlike the old KMainWindow - may, but do not
+ * have to, be deleted by you. KMainWindow will handle that internally.
+ *
+ * Height and width can be operated independently from each other. Simply
+ * define the minimum/maximum height/width of your main widget and
+ * KMainWindow will take this into account. For fixed size windows set
+ * your main widget to a fixed size.
+ *
+ * Fixed aspect ratios (heightForWidth()) and fixed width widgets are
+ * not supported.
+*
+ * KMainWindow will set icon, mini icon and caption, which it gets
+ * from KApplication. It provides full session management, and
+ * will save its position, geometry and positions of toolbars and
+ * menubar on logout. If you want to save additional data, reimplement
+ * saveProperties() and (to read them again on next login)
+ * readProperties(). To save special data about your data, reimplement
+ * saveGlobalProperties(). To warn user that application or
+ * windows have unsaved data on close or logout, reimplement
+ * queryClose() and/or queryExit().
+ *
+ * There are also kRestoreMainWindows convenience functions which
+ * can restore all your windows on next login.
+ *
+ * Note that a KMainWindow per-default is created with the
+ * WDestructiveClose flag, i.e. it is automatically destroyed when the
+ * window is closed. If you do not want this behavior, specify 0 as
+ * widget flag in the constructor.
+ *
+ * @see KApplication
+ * @author Reginald Stadlbauer (reggie@kde.org) Stephan Kulow (coolo@kde.org), Matthias Ettrich (ettrich@kde.org), Chris Schlaeger (cs@kde.org), Sven Radej (radej@kde.org). Maintained by Sven Radej (radej@kde.org)
+
+ */
+
+class KDEUI_EXPORT KMainWindow : public QMainWindow, public KXMLGUIBuilder, virtual public KXMLGUIClient
+{
+ friend class KMWSessionManaged;
+ Q_OBJECT
+
+public:
+ /**
+ * Construct a main window.
+ *
+ * @param parent The widget parent. This is usually 0 but it may also be the window
+ * group leader. In that case, the KMainWindow becomes sort of a
+ * secondary window.
+ *
+ * @param name The object name. For session management and window management to work
+ * properly, all main windows in the application should have a
+ * different name. When passing 0 (the default), KMainWindow will create
+ * a unique name, but it's recommended to explicitly pass a window name that will
+ * also describe the type of the window. If there can be several windows of the same
+ * type, append '#' (hash) to the name, and KMainWindow will append numbers to make
+ * the names unique. For example, for a mail client which has one main window showing
+ * the mails and folders, and which can also have one or more windows for composing
+ * mails, the name for the folders window should be e.g. "mainwindow" and
+ * for the composer windows "composer#".
+ *
+ * @param f Specify the widget flags. The default is
+ * WType_TopLevel and WDestructiveClose. TopLevel indicates that a
+ * main window is a toplevel window, regardless of whether it has a
+ * parent or not. DestructiveClose indicates that a main window is
+ * automatically destroyed when its window is closed. Pass 0 if
+ * you do not want this behavior.
+ *
+ * @see http://doc.trolltech.com/3.2/qt.html#WidgetFlags-enum
+ *
+ * KMainWindows must be created on the heap with 'new', like:
+ * \code
+ * KMainWindow *kmw = new KMainWindow (...);
+ * \endcode
+ **/
+ KMainWindow( QWidget* parent = 0, const char *name = 0, WFlags f = WType_TopLevel | WDestructiveClose );
+
+ /**
+ * Flags that can be passed in an argument to the constructor to
+ * change the behavior.
+ *
+ * NoDCOPObject tells KMainWindow not to create a KMainWindowInterface.
+ * This can be useful in particular for inherited classes, which
+ * might want to create more specific dcop interfaces. It's a good
+ * idea to use KMainWindowInterface as the base class for such interfaces
+ * though (to provide the standard mainwindow functionality via DCOP).
+ */
+ enum CreationFlags
+ {
+ NoDCOPObject = 1
+ };
+
+ /**
+ * Overloaded constructor which allows passing some KMainWindow::CreationFlags.
+ *
+ * @since 3.2
+ */
+ KMainWindow( int cflags, QWidget* parent = 0, const char *name = 0, WFlags f = WType_TopLevel | WDestructiveClose );
+
+ /**
+ * \brief Destructor.
+ *
+ * Will also destroy the toolbars, and menubar if
+ * needed.
+ */
+ virtual ~KMainWindow();
+
+ /**
+ * Retrieve the standard help menu.
+ *
+ * It contains entires for the
+ * help system (activated by F1), an optional "What's This?" entry
+ * (activated by Shift F1), an application specific dialog box,
+ * and an "About KDE" dialog box.
+ *
+ * Example (adding a standard help menu to your application):
+ * \code
+ * KPopupMenu *help = helpMenu( <myTextString> );
+ * menuBar()->insertItem( i18n("&Help"), help );
+ * \endcode
+ *
+ * @param aboutAppText The string that is used in the application
+ * specific dialog box. If you leave this string empty the
+ * information in the global KAboutData of the
+ * application will be used to make a standard dialog box.
+ *
+ * @param showWhatsThis Set this to false if you do not want to include
+ * the "What's This" menu entry.
+ *
+ * @return A standard help menu.
+ */
+ KPopupMenu* helpMenu( const QString &aboutAppText = QString::null,
+ bool showWhatsThis = true );
+
+ /**
+ * Returns the help menu. Creates a standard help menu if none exists yet.
+ *
+ * It contains entries for the
+ * help system (activated by F1), an optional "What's This?" entry
+ * (activated by Shift F1), an application specific dialog box,
+ * and an "About KDE" dialog box. You must create the application
+ * specific dialog box yourself. When the "About application"
+ * menu entry is activated, a signal will trigger the
+ * showAboutApplication slot. See showAboutApplication for more
+ * information.
+ *
+ * Example (adding a help menu to your application):
+ * \code
+ * menuBar()->insertItem( i18n("&Help"), customHelpMenu() );
+ * \endcode
+ *
+ * @param showWhatsThis Set this to @p false if you do not want to include
+ * the "What's This" menu entry.
+ *
+ * @return A standard help menu.
+ */
+ KPopupMenu* customHelpMenu( bool showWhatsThis = true );
+
+ /**
+ * <b>Session Management</b>
+ *
+ * Try to restore the toplevel widget as defined by the number (1..X).
+ *
+ * If the session did not contain so high a number, the configuration
+ * is not changed and @p false returned.
+ *
+ * That means clients could simply do the following:
+ * \code
+ * if (kapp->isRestored()){
+ * int n = 1;
+ * while (KMainWindow::canBeRestored(n)){
+ * (new childMW)->restore(n);
+ * n++;
+ * }
+ * } else {
+ * // create default application as usual
+ * }
+ * \endcode
+ * Note that QWidget::show() is called implicitly in restore.
+ *
+ * With this you can easily restore all toplevel windows of your
+ * application.
+ *
+ * If your application uses different kinds of toplevel
+ * windows, then you can use KMainWindow::classNameOfToplevel(n)
+ * to determine the exact type before calling the childMW
+ * constructor in the example from above.
+ *
+ * If your client has only one kind of toplevel widgets (which
+ * should be pretty usual) then you should use the RESTORE-macro
+ * for backwards compatibility with 3.1 and 3.0 branches:
+ *
+ * \code
+ * if (kapp->isRestored())
+ * RESTORE(childMW)
+ * else {
+ * // create default application as usual
+ * }
+ * \endcode
+ *
+ * The macro expands to the term above but is easier to use and
+ * less code to write.
+ *
+ * For new code or if you have more than one kind of toplevel
+ * widget (each derived from KMainWindow, of course), you can
+ * use the templated kRestoreMainWindows global functions:
+ *
+ * \code
+ * if (kapp->isRestored())
+ * kRestoreMainWindows< childMW1, childMW2, childMW3 >();
+ * else {
+ * // create default application as usual
+ * }
+ * \endcode
+ *
+ * Currently, these functions are provided for up to three
+ * template arguments. If you need more, tell us. To help you in
+ * deciding whether or not you can use kRestoreMainWindows, a
+ * define KDE_RESTORE_MAIN_WINDOWS_NUM_TEMPLATE_ARGS is provided.
+ *
+ * @see restore()
+ * @see classNameOfToplevel()
+ *
+ **/
+ static bool canBeRestored( int number );
+
+ /**
+ * Returns the className() of the @p number of the toplevel window which
+ * should be restored.
+ *
+ * This is only useful if your application uses
+ * different kinds of toplevel windows.
+ */
+ // KDE 4 return QCString - QObject::className() returns const char*
+ static const QString classNameOfToplevel( int number );
+
+ /**
+ * Reimplementation of QMainWindow::show()
+ */
+ // KDE4 remove this method if this has been fixed in Qt
+ virtual void show();
+
+ /**
+ * Reimplementation of QMainWindow::hide()
+ */
+ // KDE4 remove this method if this has been fixed in Qt
+ virtual void hide();
+
+ /**
+ * Restore the session specified by @p number.
+ *
+ * Returns @p false if this
+ * fails, otherwise returns @p true and shows the window.
+ * You should call canBeRestored() first.
+ * If @p show is true (default), this widget will be shown automatically.
+ */
+ bool restore( int number, bool show = true );
+
+ virtual KXMLGUIFactory *guiFactory();
+
+ /**
+ * Create a GUI given a local XML file.
+ *
+ * If @p xmlfile is NULL,
+ * then it will try to construct a local XML filename like
+ * appnameui.rc where 'appname' is your app's name. If that file
+ * does not exist, then the XML UI code will only use the global
+ * (standard) XML file for the layout purposes.
+ *
+ * Note that when passing true for the conserveMemory argument subsequent
+ * calls to guiFactory()->addClient/removeClient may not work as expected.
+ * Also retrieving references to containers like popup menus or toolbars using
+ * the container method will not work.
+ *
+ * @param xmlfile The local xmlfile (relative or absolute)
+ * @param _conserveMemory Specify whether createGUI() should call
+ * KXMLGUIClient::conserveMemory() to free all memory
+ * allocated by the QDomDocument and by the KXMLGUIFactory.
+ */
+ void createGUI( const QString &xmlfile = QString::null, bool _conserveMemory = true );
+
+ /**
+ * Enables the build of a standard help menu when calling createGUI().
+ *
+ * The default behavior is to build one, you must call this function
+ * to disable it
+ */
+ void setHelpMenuEnabled(bool showHelpMenu = true);
+
+ /**
+ * Return @p true when the help menu is enabled
+ */
+ bool isHelpMenuEnabled();
+
+
+ /**
+ * Returns true, if there is a menubar
+ * @since 3.1
+ */
+ bool hasMenuBar();
+
+ /**
+ * Returns a pointer to the menu bar.
+ *
+ * If there is no menu bar yet one will be created.
+ **/
+ KMenuBar *menuBar();
+
+ /**
+ * Returns a pointer to the status bar.
+ *
+ * If there is no status bar yet, one will be created.
+ *
+ * Note that tooltips for kactions in actionCollection() are not
+ * automatically connected to this statusBar.
+ * See the KActionCollection documentation for more details.
+ *
+ * @see KActionCollection
+ */
+ KStatusBar *statusBar();
+
+ /**
+ * List of members of KMainWindow class.
+ */
+ static QPtrList<KMainWindow>* memberList;
+
+ //KDE4: replace with memberList() and make memberList member private
+ /**
+ * List of members of KMainWindow class.
+ * @since 3.4
+ */
+ static QPtrList<KMainWindow>* getMemberList();
+
+ /**
+ * Returns a pointer to the toolbar with the specified name.
+ * This refers to toolbars created dynamically from the XML UI
+ * framework. If the toolbar does not exist one will be created.
+ *
+ * @param name The internal name of the toolbar. If no name is
+ * specified "mainToolBar" is assumed.
+ *
+ * @return A pointer to the toolbar
+ **/
+ KToolBar *toolBar( const char *name=0 );
+
+ /**
+ * @return An iterator over the list of all toolbars for this window.
+ */
+ QPtrListIterator<KToolBar> toolBarIterator();
+
+ /**
+ * @return A KAccel instance bound to this mainwindow. Used automatically
+ * by KAction to make keybindings work in all cases.
+ */
+ KAccel *accel();
+
+ void setFrameBorderWidth( int ) {}
+
+ /**
+ * Call this to enable "auto-save" of toolbar/menubar/statusbar settings
+ * (and optionally window size).
+ * If the *bars were moved around/shown/hidden when the window is closed,
+ * saveMainWindowSettings( KGlobal::config(), groupName ) will be called.
+ *
+ * @param groupName a name that identifies this "type of window".
+ * You can have several types of window in the same application.
+ *
+ * @param saveWindowSize set it to true to include the window size
+ * when saving.
+ *
+ * Typically, you will call setAutoSaveSettings() in your
+ * KMainWindow-inherited class constructor, and it will take care
+ * of restoring and saving automatically. Make sure you call this
+ * _after all_ your *bars have been created.
+ *
+ * To make sure that KMainWindow propertly obtains the default
+ * size of the window you should do the following:
+ * - Remove hard coded resize() calls in the constructor or main, they
+ * should be removed in favor of letting the automatic resizing
+ * determine the default window size. Hard coded window sizes will
+ * be wrong for users that have big fonts, use different styles,
+ * long/small translations, large toolbars, and other factors.
+ * - Put the setAutoSaveSettings ( or setupGUI() ) call after all widgets
+ * have been created and placed inside the main window (i.e. for 99% of
+ * apps setCentralWidget())
+ * - Widgets that inherit from QWidget (like game boards) should overload
+ * "virtual QSize sizeHint() const;" to specify a default size rather
+ * than letting QWidget::adjust use the default size of 0x0.
+ */
+ void setAutoSaveSettings( const QString & groupName = QString::fromLatin1("MainWindow"),
+ bool saveWindowSize = true );
+
+ /**
+ * Disable the auto-save-settings feature.
+ * You don't normally need to call this, ever.
+ */
+ void resetAutoSaveSettings();
+
+ /**
+ * @return the current autosave setting, i.e. true if setAutoSaveSettings() was called,
+ * false by default or if resetAutoSaveSettings() was called.
+ * @since 3.1
+ */
+ bool autoSaveSettings() const;
+
+ /**
+ * @return the group used for setting-autosaving.
+ * Only meaningful if setAutoSaveSettings() was called.
+ * This can be useful for forcing a save or an apply, e.g. before and after
+ * using KEditToolbar.
+ * @since 3.1
+ */
+ QString autoSaveGroup() const;
+
+ /**
+ * Read settings for statusbar, menubar and toolbar from their respective
+ * groups in the config file and apply them.
+ *
+ * @param config Config file to read the settings from.
+ * @param groupName Group name to use. If not specified, the last used
+ * group name is used.
+ * @param force if set, even default settings are re-applied
+ */
+ void applyMainWindowSettings(KConfig *config, const QString &groupName, bool force);
+ // KDE4 merge with force=false
+ void applyMainWindowSettings(KConfig *config, const QString &groupName = QString::null);
+
+ /**
+ * Save settings for statusbar, menubar and toolbar to their respective
+ * groups in the config file @p config.
+ *
+ * @param config Config file to save the settings to.
+ * @param groupName Group name to use. If not specified, the last used
+ * group name is used
+ */
+ void saveMainWindowSettings(KConfig *config, const QString &groupName = QString::null);
+
+ /**
+ * Sets whether KMainWindow should provide a menu that allows showing/hiding
+ * the available toolbars ( using KToggleToolBarAction ) . In case there
+ * is only one toolbar configured a simple 'Show \<toolbar name here\>' menu item
+ * is shown.
+ *
+ * The menu / menu item is implemented using xmlgui. It will be inserted in your
+ * menu structure in the 'Settings' menu.
+ *
+ * If your application uses a non-standard xmlgui resource file then you can
+ * specify the exact position of the menu / menu item by adding a
+ * &lt;Merge name="StandardToolBarMenuHandler" /&gt;
+ * line to the settings menu section of your resource file ( usually appname.rc ).
+ *
+ * Note that you should enable this feature before calling createGUI() ( or similar ) .
+ * You enable/disable it anytime if you pass false to the conserveMemory argument of createGUI.
+ * @since 3.1
+ */
+ void setStandardToolBarMenuEnabled( bool enable );
+ /// @since 3.1
+ bool isStandardToolBarMenuEnabled() const;
+
+
+ /**
+ * Sets whether KMainWindow should provide a menu that allows showing/hiding
+ * of the statusbar ( using KToggleStatusBarAction ).
+ *
+ * The menu / menu item is implemented using xmlgui. It will be inserted
+ * in your menu structure in the 'Settings' menu.
+ *
+ * Note that you should enable this feature before calling createGUI()
+ * ( or similar ).
+ *
+ * If an application maintains the action on its own (i.e. never calls
+ * this function) a connection needs to be made to let KMainWindow
+ * know when that status (hidden/shown) of the statusbar has changed.
+ * For example:
+ * connect(action, SIGNAL(activated()),
+ * kmainwindow, SLOT(setSettingsDirty()));
+ * Otherwise the status (hidden/show) of the statusbar might not be saved
+ * by KMainWindow.
+ * @since 3.2
+ */
+ void createStandardStatusBarAction();
+
+ /**
+ * @see setupGUI()
+ */
+ enum StandardWindowOptions
+ {
+ /**
+ * adds action to show/hide the toolbar(s) and adds
+ * action to configure the toolbar(s).
+ * @see setStandardToolBarMenuEnabled
+ */
+ ToolBar = 1,
+
+ /**
+ * adds action to show the key configure action.
+ */
+ Keys = 2,
+
+ /**
+ * adds action to show/hide the statusbar if the
+ * statusbar exists. See createStandardStatusBarAction
+ */
+ StatusBar = 4,
+
+ /**
+ * auto-saves (and loads) the toolbar/menubar/statusbar settings and
+ * window size using the default name. See setAutoSaveSettings
+ *
+ * Typically you want to let the default window size be determined by
+ * the widgets size hints. Make sure that setupGUI() is called after
+ * all the widgets are created ( including setCentralWidget ) so the
+ * default size's will be correct. See setAutoSaveSettings for
+ * more information on this topic.
+ */
+ Save = 8,
+
+ /**
+ * calls createGUI() once ToolBar, Keys and Statusbar have been
+ * taken care of. See createGUI
+ */
+ Create = 16
+ };
+
+ /**
+ * Configures the current windows and its actions in the typical KDE
+ * fashion. The options are all enabled by default but can be turned
+ * off if desired through the params or if the prereqs don't exists.
+ *
+ * Typically this function replaces createGUI().
+ *
+ * @see StandardWindowOptions
+ *
+ * @since 3.3
+ */
+ void setupGUI( int options = ToolBar | Keys | StatusBar | Save | Create, const QString& xmlfile = QString::null );
+
+ /**
+ * Configures the current windows and its actions in the typical KDE
+ * fashion. The options are all enabled by default but can be turned
+ * off if desired through the params or if the prereqs don't exists.
+ *
+ * @p defaultSize The default size of the window
+ *
+ * Typically this function replaces createGUI().
+ *
+ * @see StandardWindowOptions
+ *
+ * @since 3.5
+ */
+ void setupGUI( QSize defaultSize, int options = ToolBar | Keys | StatusBar | Save | Create, const QString& xmlfile = QString::null );
+
+ /**
+ * Returns a pointer to the mainwindows action responsible for the toolbars menu
+ * @since 3.1
+ */
+ KAction *toolBarMenuAction();
+
+ /**
+ * @internal for KToolBar
+ * @since 3.3.1
+ */
+ void setupToolbarMenuActions();
+
+ // why do we support old gcc versions? using KXMLGUIBuilder::finalizeGUI;
+ /// @since 3.1
+ virtual void finalizeGUI( KXMLGUIClient *client );
+
+ /**
+ * @internal
+ */
+ void finalizeGUI( bool force );
+
+ /**
+ * @return true if a -geometry argument was given on the command line,
+ * and this is the first window created (the one on which this option applies)
+ */
+ bool initialGeometrySet() const;
+
+ /**
+ * @internal
+ * Used from Konqueror when reusing the main window.
+ */
+ void ignoreInitialGeometry();
+
+ /**
+ * @return the size the mainwindow should have so that the central
+ * widget will be of @p size.
+ *
+ * @deprecated You normally don't need this, the recommended way to achieve a
+ * certain central widget size is as follows:
+ * @li Override sizeHint() in the central widget so that it
+ * returns the desired size.
+ * @li Call updateGeometry() in the central widget whenever the
+ * desired size changes. This ensures that the new sizeHint() is properly
+ * propagated to any parent layout.
+ * @li Now call adjustSize() in the mainwindow to resize the
+ * mainwindow such that the central widget will become the desired size.
+ *
+ */
+ // KDE4 to be removed
+ QSize sizeForCentralWidgetSize(QSize size) KDE_DEPRECATED;
+
+ /**
+ * @internal
+ */
+ // KDE4 remove
+ virtual void setIcon( const QPixmap & );
+
+public slots:
+ /**
+ * Show a standard configure toolbar dialog.
+ *
+ * This slot can be connected dirrectly to the action to configure shortcuts.
+ * This is very simple to do that by adding a single line
+ * \code
+ * KStdAction::configureToolbars( guiFactory(), SLOT( configureToolbars() ),
+ * actionCollection() );
+ * \endcode
+ *
+ * @since 3.3
+ */
+ int configureToolbars(); // TODO KDE4: make virtual and reimplement in KParts::MainWindow
+
+ /**
+ * Makes a KDE compliant caption.
+ *
+ * @param caption Your caption. @em Do @em not include the application name
+ * in this string. It will be added automatically according to the KDE
+ * standard.
+ */
+ virtual void setCaption( const QString &caption );
+ /**
+ * Makes a KDE compliant caption.
+ *
+ * @param caption Your caption. @em Do @em not include the application name
+ * in this string. It will be added automatically according to the KDE
+ * standard.
+ * @param modified Specify whether the document is modified. This displays
+ * an additional sign in the title bar, usually "**".
+ */
+ virtual void setCaption( const QString &caption, bool modified );
+
+ /**
+ * Make a plain caption without any modifications.
+ *
+ * @param caption Your caption. This is the string that will be
+ * displayed in the window title.
+ */
+ virtual void setPlainCaption( const QString &caption );
+
+ /**
+ * Open the help page for the application.
+ *
+ * The application name is
+ * used as a key to determine what to display and the system will attempt
+ * to open \<appName\>/index.html.
+ *
+ * This method is intended for use by a help button in the toolbar or
+ * components outside the regular help menu. Use helpMenu() when you
+ * want to provide access to the help system from the help menu.
+ *
+ * Example (adding a help button to the first toolbar):
+ *
+ * \code
+ * KIconLoader &loader = *KGlobal::iconLoader();
+ * QPixmap pixmap = loader.loadIcon( "help" );
+ * toolBar(0)->insertButton( pixmap, 0, SIGNAL(clicked()),
+ * this, SLOT(appHelpActivated()), true, i18n("Help") );
+ * \endcode
+ *
+ */
+ void appHelpActivated( void );
+
+ /**
+ * Apply a state change
+ *
+ * Enable and disable actions as defined in the XML rc file
+ * @since 3.1
+ */
+ virtual void slotStateChanged(const QString &newstate);
+
+ /**
+ * Apply a state change
+ *
+ * Enable and disable actions as defined in the XML rc file,
+ * can "reverse" the state (disable the actions which should be
+ * enabled, and vice-versa) if specified.
+ * @since 3.1
+ */
+ void slotStateChanged(const QString &newstate,
+ KXMLGUIClient::ReverseStateChange); // KDE 4.0: remove this
+
+
+ /**
+ * Apply a state change
+ *
+ * Enable and disable actions as defined in the XML rc file,
+ * can "reverse" the state (disable the actions which should be
+ * enabled, and vice-versa) if specified.
+ */
+// void slotStateChanged(const QString &newstate,
+// bool reverse); // KDE 4.0: enable this
+
+ /**
+ * Tell the main window that it should save its settings when being closed.
+ * This is part of the auto-save-settings feature.
+ * For everything related to toolbars this happens automatically,
+ * but you have to call setSettingsDirty() in the slot that toggles
+ * the visibility of the statusbar.
+ */
+ void setSettingsDirty();
+
+protected:
+ void paintEvent( QPaintEvent* e );
+ void childEvent( QChildEvent* e);
+ void resizeEvent( QResizeEvent* e);
+ /**
+ * Reimplemented to call the queryClose() and queryExit() handlers.
+ *
+ * We recommend that you reimplement the handlers rather than closeEvent().
+ * If you do it anyway, ensure to call the base implementation to keep
+ * queryExit() running.
+ */
+ virtual void closeEvent ( QCloseEvent *);
+
+ // KDE4 This seems to be flawed to me. Either the app has only one
+ // mainwindow, so queryClose() is enough, or if it can have more of them,
+ // then the windows should take care of themselves, and queryExit()
+ // would be useful only for the annoying 'really quit' dialog, which
+ // also doesn't make sense in apps with multiple mainwindows.
+ // And saving configuration in something called queryExit()? IMHO
+ // one can e.g. use KApplication::shutDown(), which if nothing else
+ // has at least better fitting name.
+ // See also KApplication::sessionSaving().
+ // This stuff should get changed somehow, so that it at least doesn't
+ // mess with session management.
+ /**
+ Called before the very last window is closed, either by the
+ user or indirectly by the session manager.
+
+ It is not recommended to do any user interaction in this
+ function other than indicating severe errors. Better ask the
+ user on queryClose() (see below).
+
+ A typical usage of queryExit() is to write configuration data back.
+ Note that the application may continue to run after queryExit()
+ (the user may have canceled a shutdown), so you should not do any cleanups
+ here. The purpose of queryExit() is purely to prepare the application
+ (with possible user interaction) so it can safely be closed later (without
+ user interaction).
+
+ If you need to do serious things on exit (like shutting a
+ dial-up connection down), connect to the signal
+ KApplication::shutDown().
+
+ Default implementation returns @p true. Returning @p false will
+ cancel the exiting. In the latter case, the last window will
+ remain visible. If KApplication::sessionSaving() is true, refusing
+ the exit will also cancel KDE logout.
+
+ @see queryClose()
+ @see KApplication::sessionSaving()
+ */
+ virtual bool queryExit();
+
+ /**
+ Called before the window is closed, either by the user or indirectly by
+ the session manager.
+
+ The purpose of this function is to prepare the window in a way that it is
+ safe to close it, i.e. without the user losing some data.
+
+ Default implementation returns true. Returning @p false will cancel
+ the closing, and, if KApplication::sessionSaving() is true, it will also
+ cancel KDE logout.
+
+ Reimplement this function to prevent the user from losing data.
+ Example:
+ \code
+ switch ( KMessageBox::warningYesNoCancel( this,
+ i18n("Save changes to document foo?")) ) {
+ case KMessageBox::Yes :
+ // save document here. If saving fails, return false;
+ return true;
+ case KMessageBox::No :
+ return true;
+ default: // cancel
+ return false;
+ \endcode
+
+ Note that you should probably @em not actually close the document from
+ within this method, as it may be called by the session manager before the
+ session is saved. If the document is closed before the session save occurs,
+ its location might not be properly saved. In addition, the session shutdown
+ may be canceled, in which case the document should remain open.
+
+ @see queryExit()
+ @see KApplication::sessionSaving()
+ */
+ virtual bool queryClose();
+
+ /**
+ * Save your instance-specific properties. The function is
+ * invoked when the session manager requests your application
+ * to save its state.
+ *
+ * You @em must @em not change the group of the @p kconfig object, since
+ * KMainWindow uses one group for each window. Please
+ * reimplement these function in childclasses.
+ *
+ * Note: No user interaction is allowed
+ * in this function!
+ *
+ */
+ virtual void saveProperties( KConfig* ) {}
+
+ /**
+ * Read your instance-specific properties.
+ */
+ virtual void readProperties( KConfig* ) {}
+
+ /**
+ * Save your application-wide properties. The function is
+ * invoked when the session manager requests your application
+ * to save its state.
+ *
+ * This function is similar to saveProperties() but is only called for
+ * the very first main window, regardless how many main window are open.
+
+ * Override it if you need to save other data about your documents on
+ * session end. sessionConfig is a config to which that data should be
+ * saved. Normally, you don't need this function. But if you want to save
+ * data about your documents that are not in opened windows you might need
+ * it.
+ *
+ * Default implementation does nothing.
+ */
+ virtual void saveGlobalProperties( KConfig* sessionConfig );
+
+ /**
+ * The counterpart of saveGlobalProperties().
+ *
+ * Read the application-specific properties in again.
+ */
+ virtual void readGlobalProperties( KConfig* sessionConfig );
+ void savePropertiesInternal( KConfig*, int );
+ bool readPropertiesInternal( KConfig*, int );
+
+ /**
+ * For inherited classes
+ */
+ bool settingsDirty() const;
+ /**
+ * For inherited classes
+ */
+ QString settingsGroup() const;
+ /**
+ * For inherited classes
+ * Note that the group must be set before calling
+ */
+ void saveWindowSize( KConfig * config ) const;
+ /**
+ * For inherited classes
+ * Note that the group must be set before calling, and that
+ * a -geometry on the command line has priority.
+ */
+ void restoreWindowSize( KConfig * config );
+
+ /// parse the geometry from the geometry command line argument
+ void parseGeometry(bool parsewidth);
+
+protected slots:
+ /**
+ * Rebuilds the GUI after KEditToolbar changed the toolbar layout.
+ * @see configureToolbars()
+ */
+ void saveNewToolbarConfig(); // TODO KDE4: make virtual and reimplement in KParts::MainWindow
+
+ /**
+ * This slot does nothing.
+ *
+ * It must be reimplemented if you want
+ * to use a custom About Application dialog box. This slot is
+ * connected to the About Application entry in the menu returned
+ * by customHelpMenu.
+ *
+ * Example:
+ * \code
+ *
+ * void MyMainLevel::setupInterface()
+ * {
+ * ..
+ * menuBar()->insertItem( i18n("&Help"), customHelpMenu() );
+ * ..
+ * }
+ *
+ * void MyMainLevel::showAboutApplication()
+ * {
+ * <activate your custom dialog>
+ * }
+ * \endcode
+ */
+ virtual void showAboutApplication();
+
+ /**
+ * This slot should only be called in case you reimplement closeEvent() and
+ * if you are using the "auto-save" feature. In all other cases,
+ * setSettingsDirty() should be called instead to benefit from the delayed
+ * saving.
+ *
+ * @see setAutoSaveSettings
+ * @see setSettingsDirty
+ *
+ * @since 3.2
+ *
+ * Example:
+ * \code
+ *
+ * void MyMainWindow::closeEvent( QCloseEvent *e )
+ * {
+ * // Save settings if auto-save is enabled, and settings have changed
+ * if ( settingsDirty() && autoSaveSettings() )
+ * saveAutoSaveSettings();
+ * ..
+ * }
+ * \endcode
+ */
+ void saveAutoSaveSettings();
+
+private slots:
+ /**
+ * Called when the app is shutting down.
+ */
+ void shuttingDown();
+
+private:
+ KMenuBar *internalMenuBar();
+ KStatusBar *internalStatusBar();
+ KHelpMenu *mHelpMenu, *helpMenu2;
+ KXMLGUIFactory *factory_;
+ QPtrList<KToolBar> toolbarList;
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KMainWindowPrivate *d;
+ void initKMainWindow(const char *name, int cflags);
+};
+
+#define RESTORE(type) { int n = 1;\
+ while (KMainWindow::canBeRestored(n)){\
+ (new type)->restore(n);\
+ n++;}}
+
+#define KDE_RESTORE_MAIN_WINDOWS_NUM_TEMPLATE_ARGS 3
+
+/**
+ * These global convenience functions (that come with a varying
+ * number of template arguments) are a replacement for the RESTORE
+ * macro provided in earlier versions of KDE. The old RESTORE macro
+ * is still provided for backwards compatibility. See
+ * KMainWindow documentation for more.
+ *
+ * \since KDE 3.2
+ *
+ **/
+template <typename T>
+inline void kRestoreMainWindows() {
+ for ( int n = 1 ; KMainWindow::canBeRestored( n ) ; ++n ) {
+ const QString className = KMainWindow::classNameOfToplevel( n );
+ if ( className == QString::fromLatin1( T::staticMetaObject()->className() ) )
+ (new T)->restore( n );
+ }
+}
+
+template <typename T0, typename T1>
+inline void kRestoreMainWindows() {
+ const char * classNames[2];
+ classNames[0] = T0::staticMetaObject()->className();
+ classNames[1] = T1::staticMetaObject()->className();
+ for ( int n = 1 ; KMainWindow::canBeRestored( n ) ; ++n ) {
+ const QString className = KMainWindow::classNameOfToplevel( n );
+ if ( className == QString::fromLatin1( classNames[0] ) )
+ (new T0)->restore( n );
+ else if ( className == QString::fromLatin1( classNames[1] ) )
+ (new T1)->restore( n );
+ }
+}
+
+template <typename T0, typename T1, typename T2>
+inline void kRestoreMainWindows() {
+ const char * classNames[3];
+ classNames[0] = T0::staticMetaObject()->className();
+ classNames[1] = T1::staticMetaObject()->className();
+ classNames[2] = T2::staticMetaObject()->className();
+ for ( int n = 1 ; KMainWindow::canBeRestored( n ) ; ++n ) {
+ const QString className = KMainWindow::classNameOfToplevel( n );
+ if ( className == QString::fromLatin1( classNames[0] ) )
+ (new T0)->restore( n );
+ else if ( className == QString::fromLatin1( classNames[1] ) )
+ (new T1)->restore( n );
+ else if ( className == QString::fromLatin1( classNames[2] ) )
+ (new T2)->restore( n );
+ }
+}
+
+#endif
diff --git a/kdeui/kmainwindowiface.cpp b/kdeui/kmainwindowiface.cpp
new file mode 100644
index 000000000..ce653bb6d
--- /dev/null
+++ b/kdeui/kmainwindowiface.cpp
@@ -0,0 +1,194 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Ian Reinhart Geiser <geiseri@yahoo.com>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the Lesser 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 Lesser GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kmainwindowiface.h"
+
+#include <dcopclient.h>
+#include <kapplication.h>
+#include <kdcopactionproxy.h>
+#include <kdcoppropertyproxy.h>
+#include <kmainwindow.h>
+#include <kaction.h>
+#include <qclipboard.h>
+
+
+KMainWindowInterface::KMainWindowInterface(KMainWindow * mainWindow)
+ : DCOPObject( mainWindow->name())
+{
+ m_MainWindow = mainWindow;
+ m_dcopActionProxy = new KDCOPActionProxy( m_MainWindow->actionCollection(), this );
+ m_dcopPropertyProxy = new KDCOPPropertyProxy(m_MainWindow);
+}
+
+KMainWindowInterface::~KMainWindowInterface()
+{
+ delete m_dcopActionProxy;
+ delete m_dcopPropertyProxy;
+}
+
+QCStringList KMainWindowInterface::actions()
+{
+ delete m_dcopActionProxy;
+ m_dcopActionProxy = new KDCOPActionProxy( m_MainWindow->actionCollection(), this );
+ QCStringList tmp_actions;
+ QValueList<KAction *> lst = m_dcopActionProxy->actions();
+ QValueList<KAction *>::ConstIterator it = lst.begin();
+ QValueList<KAction *>::ConstIterator end = lst.end();
+ for (; it != end; ++it )
+ if ((*it)->isPlugged())
+ tmp_actions.append( (QCString)(*it)->name() );
+ return tmp_actions;
+}
+bool KMainWindowInterface::activateAction( QCString action)
+{
+ delete m_dcopActionProxy;
+ m_dcopActionProxy = new KDCOPActionProxy( m_MainWindow->actionCollection(), this );
+ KAction *tmp_Action = m_dcopActionProxy->action(action);
+ if (tmp_Action)
+ {
+ tmp_Action->activate();
+ return true;
+ }
+ else
+ return false;
+}
+bool KMainWindowInterface::disableAction( QCString action)
+{
+ delete m_dcopActionProxy;
+ m_dcopActionProxy = new KDCOPActionProxy( m_MainWindow->actionCollection(), this );
+ KAction *tmp_Action = m_dcopActionProxy->action(action);
+ if (tmp_Action)
+ {
+ tmp_Action->setEnabled(false);
+ return true;
+ }
+ else
+ return false;
+}
+bool KMainWindowInterface::enableAction( QCString action)
+{
+ delete m_dcopActionProxy;
+ m_dcopActionProxy = new KDCOPActionProxy( m_MainWindow->actionCollection(), this );
+ KAction *tmp_Action = m_dcopActionProxy->action(action);
+ if (tmp_Action)
+ {
+ tmp_Action->setEnabled(true);
+ return true;
+ }
+ else
+ return false;
+}
+bool KMainWindowInterface::actionIsEnabled( QCString action)
+{
+ delete m_dcopActionProxy;
+ m_dcopActionProxy = new KDCOPActionProxy( m_MainWindow->actionCollection(), this );
+ KAction *tmp_Action = m_dcopActionProxy->action(action);
+ if (tmp_Action)
+ {
+ return tmp_Action->isEnabled();
+ }
+ else
+ return false;
+}
+QCString KMainWindowInterface::actionToolTip( QCString action)
+{
+ delete m_dcopActionProxy;
+ m_dcopActionProxy = new KDCOPActionProxy( m_MainWindow->actionCollection(), this );
+ KAction *tmp_Action = m_dcopActionProxy->action(action);
+ if (tmp_Action)
+ {
+ return tmp_Action->toolTip().utf8();
+ }
+ else
+ return "Error no such object!";
+}
+
+DCOPRef KMainWindowInterface::action( const QCString &name )
+{
+ return DCOPRef( kapp->dcopClient()->appId(), m_dcopActionProxy->actionObjectId( name ) );
+}
+
+QMap<QCString,DCOPRef> KMainWindowInterface::actionMap()
+{
+ return m_dcopActionProxy->actionMap();
+}
+
+int KMainWindowInterface::getWinID()
+{
+ return (int) m_MainWindow->winId();
+}
+void KMainWindowInterface::grabWindowToClipBoard()
+{
+ QClipboard *clipboard = QApplication::clipboard();
+ clipboard->setPixmap(QPixmap::grabWidget(m_MainWindow));
+}
+void KMainWindowInterface::hide()
+{
+ m_MainWindow->hide();
+}
+void KMainWindowInterface::maximize()
+{
+ m_MainWindow->showMaximized();
+}
+void KMainWindowInterface::minimize()
+{
+ m_MainWindow->showMinimized();
+}
+void KMainWindowInterface::resize(int newX, int newY)
+{
+ m_MainWindow->resize(newX, newY);
+}
+void KMainWindowInterface::move(int newX, int newY)
+{
+ m_MainWindow->move(newX, newY);
+}
+void KMainWindowInterface::setGeometry(int newX, int newY, int newWidth, int newHeight)
+{
+ m_MainWindow->setGeometry(newX, newY, newWidth, newHeight);
+}
+void KMainWindowInterface::raise()
+{
+ m_MainWindow->raise();
+}
+void KMainWindowInterface::lower()
+{
+ m_MainWindow->lower();
+}
+void KMainWindowInterface::restore()
+{
+ m_MainWindow->showNormal();
+}
+void KMainWindowInterface::close()
+{
+ m_MainWindow->close();
+}
+void KMainWindowInterface::show()
+{
+ m_MainWindow->show();
+}
+QCStringList KMainWindowInterface::functionsDynamic()
+{
+ return m_dcopPropertyProxy->functions();
+}
+bool KMainWindowInterface::processDynamic(const QCString &fun, const QByteArray &data, QCString& replyType, QByteArray &replyData)
+{
+ return m_dcopPropertyProxy->processPropertyRequest( fun, data, replyType, replyData);
+
+}
+
diff --git a/kdeui/kmainwindowiface.h b/kdeui/kmainwindowiface.h
new file mode 100644
index 000000000..eaee8d1d9
--- /dev/null
+++ b/kdeui/kmainwindowiface.h
@@ -0,0 +1,161 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Ian Reinhart Geiser <geiseri@yahoo.com>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This 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 Library General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KWINDOW_INTERFACE_H
+#define KWINDOW_INTERFACE_H
+
+#include <dcopobject.h>
+#include <qstringlist.h>
+#include <qcstring.h>
+#include <dcopref.h>
+
+class KDCOPActionProxy;
+class KDCOPPropertyProxy;
+class KMainWindow;
+
+/**
+ * @short DCOP interface to KMainWindow.
+ *
+ * This is the main interface to the KMainWindow. This will provide a consistent
+ * DCOP interface to all KDE applications that use it.
+ *
+ * @author Ian Reinhart Geiser <geiseri@yahoo.com>
+ */
+class KDEUI_EXPORT KMainWindowInterface : virtual public DCOPObject
+{
+K_DCOP
+
+public:
+ /**
+ Construct a new interface object.
+ @param mainWindow - The parent KMainWindow object
+ that will provide us with the KAction objects.
+ */
+ KMainWindowInterface( KMainWindow * mainWindow );
+ /**
+ Destructor
+ Cleans up the dcop action proxy object.
+ **/
+ ~KMainWindowInterface();
+
+ QCStringList functionsDynamic();
+ bool processDynamic(const QCString &fun, const QByteArray &data, QCString& replyType, QByteArray &replyData);
+
+
+k_dcop:
+ /**
+ Return a list of actions available to the application's window.
+ @return A QCStringList containing valid names actions.
+ */
+ QCStringList actions();
+
+ /**
+ Activates the requested action.
+ @param action The name of the action to activate. The names of valid
+ actions can be found by calling actions().
+ @return The success of the operation.
+ */
+ bool activateAction( QCString action);
+
+ /**
+ Disables the requested action.
+ @param action The name of the action to disable. The names of valid
+ actions can be found by calling actions().
+ @return The success of the operation.
+ */
+ bool disableAction( QCString action);
+
+ /**
+ Enables the requested action.
+ @param action The name of the action to enable. The names of valid
+ actions can be found by calling actions().
+ @return The success of the operation.
+ */
+ bool enableAction( QCString action);
+
+ /**
+ Returns the status of the requested action.
+ @param action The name of the action. The names of valid
+ actions can be found by calling actions().
+ @returns The state of the action, true - enabled, false - disabled.
+ */
+ bool actionIsEnabled( QCString action);
+
+ /**
+ Returns the tool tip text of the requested action.
+ @param action The name of the action to activate. The names of valid
+ actions can be found by calling actions().
+ @return A QCString containing the text of the action's tool tip.
+ */
+ QCString actionToolTip( QCString action);
+
+ /**
+ Returns a dcop reference to the selected KAction
+ @param name The name of the action. The names of valid
+ actions can be found by calling actions().
+ @return A DCOPRef for the kaction.
+ **/
+ DCOPRef action( const QCString &name );
+
+ /**
+ Returns and action map
+ **/
+ QMap<QCString,DCOPRef> actionMap();
+ /**
+ Returns the ID of the current main window.
+ This is useful for automated screen captures or other evil
+ widget fun.
+ @return A integer value of the main window's ID.
+ **/
+ int getWinID();
+ /**
+ Copies a pixmap representation of the current main window to
+ the clipboard.
+ **/
+ void grabWindowToClipBoard();
+// bool isHidden();
+ void hide();
+// bool isMaximized();
+ void maximize();
+// bool isMinimized();
+ void minimize();
+// int width();
+// int height();
+ void resize(int newWidth, int newHeight);
+// int Xpos();
+// int Ypos();
+ void move(int newX, int newY);
+ void setGeometry(int newX, int newY, int newWidth, int newHeight);
+ void raise();
+ void lower();
+ void restore();
+ void show();
+ void close();
+
+// QCStringList getQTProperties();
+
+private:
+ KMainWindow *m_MainWindow;
+ KDCOPActionProxy *m_dcopActionProxy;
+ KDCOPPropertyProxy *m_dcopPropertyProxy;
+};
+
+#endif
+
+
diff --git a/kdeui/kmenubar.cpp b/kdeui/kmenubar.cpp
new file mode 100644
index 000000000..fcadd8648
--- /dev/null
+++ b/kdeui/kmenubar.cpp
@@ -0,0 +1,563 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997, 1998, 1999, 2000 Sven Radej (radej@kde.org)
+ Copyright (C) 1997, 1998, 1999, 2000 Matthias Ettrich (ettrich@kde.org)
+ Copyright (C) 1999, 2000 Daniel "Mosfet" Duley (mosfet@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDE_MENUITEM_DEF
+#define INCLUDE_MENUITEM_DEF
+#endif
+
+#include "config.h"
+#include <qevent.h>
+#include <qobjectlist.h>
+#include <qaccel.h>
+#include <qpainter.h>
+#include <qstyle.h>
+#include <qtimer.h>
+
+#include <kconfig.h>
+#include <kglobalsettings.h>
+#include <kmenubar.h>
+#include <kapplication.h>
+#include <kglobal.h>
+#include <kdebug.h>
+#include <kmanagerselection.h>
+
+#ifdef Q_WS_X11
+#include <kwin.h>
+#include <kwinmodule.h>
+#include <qxembed.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#endif
+
+/*
+
+ Toplevel menubar (not for the fallback size handling done by itself):
+ - should not alter position or set strut
+ - every toplevel must have at most one matching topmenu
+ - embedder won't allow shrinking below a certain size
+ - must have WM_TRANSIENT_FOR pointing the its mainwindow
+ - the exception is desktop's menubar, which can be transient for root window
+ because of using root window as the desktop window
+ - Fitts' Law
+
+*/
+
+class KMenuBar::KMenuBarPrivate
+{
+public:
+ KMenuBarPrivate()
+ : forcedTopLevel( false ),
+ topLevel( false ),
+ wasTopLevel( false ),
+#ifdef Q_WS_X11
+ selection( NULL ),
+#endif
+ min_size( 0, 0 )
+ {
+ }
+ ~KMenuBarPrivate()
+ {
+#ifdef Q_WS_X11
+ delete selection;
+#endif
+ }
+ bool forcedTopLevel;
+ bool topLevel;
+ bool wasTopLevel; // when TLW is fullscreen, remember state
+ int frameStyle; // only valid in toplevel mode
+ int lineWidth; // dtto
+ int margin; // dtto
+ bool fallback_mode; // dtto
+#ifdef Q_WS_X11
+ KSelectionWatcher* selection;
+#endif
+ QTimer selection_timer;
+ QSize min_size;
+ static Atom makeSelectionAtom();
+};
+
+#ifdef Q_WS_X11
+static Atom selection_atom = None;
+static Atom msg_type_atom = None;
+
+static
+void initAtoms()
+{
+ char nm[ 100 ];
+ sprintf( nm, "_KDE_TOPMENU_OWNER_S%d", DefaultScreen( qt_xdisplay()));
+ char nm2[] = "_KDE_TOPMENU_MINSIZE";
+ char* names[ 2 ] = { nm, nm2 };
+ Atom atoms[ 2 ];
+ XInternAtoms( qt_xdisplay(), names, 2, False, atoms );
+ selection_atom = atoms[ 0 ];
+ msg_type_atom = atoms[ 1 ];
+}
+#endif
+
+Atom KMenuBar::KMenuBarPrivate::makeSelectionAtom()
+{
+#ifdef Q_WS_X11
+ if( selection_atom == None )
+ initAtoms();
+ return selection_atom;
+#else
+ return 0;
+#endif
+}
+
+KMenuBar::KMenuBar(QWidget *parent, const char *name)
+ : QMenuBar(parent, name)
+{
+#ifdef Q_WS_X11
+ QXEmbed::initialize();
+#endif
+ d = new KMenuBarPrivate;
+ connect( &d->selection_timer, SIGNAL( timeout()),
+ this, SLOT( selectionTimeout()));
+
+ connect( qApp->desktop(), SIGNAL( resized( int )), SLOT( updateFallbackSize()));
+
+ if ( kapp )
+ // toolbarAppearanceChanged(int) is sent when changing macstyle
+ connect( kapp, SIGNAL(toolbarAppearanceChanged(int)),
+ this, SLOT(slotReadConfig()));
+
+ slotReadConfig();
+}
+
+KMenuBar::~KMenuBar()
+{
+ delete d;
+}
+
+void KMenuBar::setTopLevelMenu(bool top_level)
+{
+ d->forcedTopLevel = top_level;
+ setTopLevelMenuInternal( top_level );
+}
+
+void KMenuBar::setTopLevelMenuInternal(bool top_level)
+{
+ if (d->forcedTopLevel)
+ top_level = true;
+
+ d->wasTopLevel = top_level;
+ if( parentWidget()
+ && parentWidget()->topLevelWidget()->isFullScreen())
+ top_level = false;
+
+ if ( isTopLevelMenu() == top_level )
+ return;
+ d->topLevel = top_level;
+ if ( isTopLevelMenu() )
+ {
+#ifdef Q_WS_X11
+ d->selection = new KSelectionWatcher( KMenuBarPrivate::makeSelectionAtom(),
+ DefaultScreen( qt_xdisplay()));
+ connect( d->selection, SIGNAL( newOwner( Window )),
+ this, SLOT( updateFallbackSize()));
+ connect( d->selection, SIGNAL( lostOwner()),
+ this, SLOT( updateFallbackSize()));
+#endif
+ d->frameStyle = frameStyle();
+ d->lineWidth = lineWidth();
+ d->margin = margin();
+ d->fallback_mode = false;
+ bool wasShown = !isHidden();
+ reparent( parentWidget(), WType_TopLevel | WStyle_Tool | WStyle_Customize | WStyle_NoBorder, QPoint(0,0), false );
+#ifdef Q_WS_X11
+ KWin::setType( winId(), NET::TopMenu );
+ if( parentWidget())
+ XSetTransientForHint( qt_xdisplay(), winId(), parentWidget()->topLevelWidget()->winId());
+#endif
+ QMenuBar::setFrameStyle( NoFrame );
+ QMenuBar::setLineWidth( 0 );
+ QMenuBar::setMargin( 0 );
+ updateFallbackSize();
+ d->min_size = QSize( 0, 0 );
+ if( parentWidget() && !parentWidget()->isTopLevel())
+ setShown( parentWidget()->isVisible());
+ else if ( wasShown )
+ show();
+ } else
+ {
+#ifdef Q_WS_X11
+ delete d->selection;
+ d->selection = NULL;
+#endif
+ setBackgroundMode( PaletteButton );
+ setFrameStyle( d->frameStyle );
+ setLineWidth( d->lineWidth );
+ setMargin( d->margin );
+ setMinimumSize( 0, 0 );
+ setMaximumSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
+ updateMenuBarSize();
+ if ( parentWidget() )
+ reparent( parentWidget(), QPoint(0,0), !isHidden());
+ }
+}
+
+bool KMenuBar::isTopLevelMenu() const
+{
+ return d->topLevel;
+}
+
+// KDE4 remove
+void KMenuBar::show()
+{
+ QMenuBar::show();
+}
+
+void KMenuBar::slotReadConfig()
+{
+ KConfig *config = KGlobal::config();
+ KConfigGroupSaver saver( config, "KDE" );
+ setTopLevelMenuInternal( config->readBoolEntry( "macStyle", false ) );
+}
+
+bool KMenuBar::eventFilter(QObject *obj, QEvent *ev)
+{
+ if ( d->topLevel )
+ {
+ if ( parentWidget() && obj == parentWidget()->topLevelWidget() )
+ {
+ if( ev->type() == QEvent::Resize )
+ return false; // ignore resizing of parent, QMenuBar would try to adjust size
+ if ( ev->type() == QEvent::Accel || ev->type() == QEvent::AccelAvailable )
+ {
+ if ( QApplication::sendEvent( topLevelWidget(), ev ) )
+ return true;
+ }
+ if(ev->type() == QEvent::ShowFullScreen )
+ // will update the state properly
+ setTopLevelMenuInternal( d->topLevel );
+ }
+ if( parentWidget() && obj == parentWidget() && ev->type() == QEvent::Reparent )
+ {
+#ifdef Q_WS_X11
+ XSetTransientForHint( qt_xdisplay(), winId(), parentWidget()->topLevelWidget()->winId());
+#else
+ //TODO: WIN32?
+#endif
+ setShown( parentWidget()->isTopLevel() || parentWidget()->isVisible());
+ }
+ if( parentWidget() && !parentWidget()->isTopLevel() && obj == parentWidget())
+ { // if the parent is not toplevel, KMenuBar needs to match its visibility status
+ if( ev->type() == QEvent::Show )
+ {
+#ifdef Q_WS_X11
+ XSetTransientForHint( qt_xdisplay(), winId(), parentWidget()->topLevelWidget()->winId());
+#else
+ //TODO: WIN32?
+#endif
+ show();
+ }
+ if( ev->type() == QEvent::Hide )
+ hide();
+ }
+ }
+ else
+ {
+ if( parentWidget() && obj == parentWidget()->topLevelWidget())
+ {
+ if( ev->type() == QEvent::WindowStateChange
+ && !parentWidget()->topLevelWidget()->isFullScreen() )
+ setTopLevelMenuInternal( d->wasTopLevel );
+ }
+ }
+ return QMenuBar::eventFilter( obj, ev );
+}
+
+// KDE4 remove
+void KMenuBar::showEvent( QShowEvent *e )
+{
+ QMenuBar::showEvent(e);
+}
+
+void KMenuBar::updateFallbackSize()
+{
+ if( !d->topLevel )
+ return;
+#ifdef Q_WS_X11
+ if( d->selection->owner() != None )
+#endif
+ { // somebody is managing us, don't mess anything, undo changes
+ // done in fallback mode if needed
+ d->selection_timer.stop();
+ if( d->fallback_mode )
+ {
+ d->fallback_mode = false;
+ KWin::setStrut( winId(), 0, 0, 0, 0 );
+ setMinimumSize( 0, 0 );
+ setMaximumSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
+ updateMenuBarSize();
+ }
+ return;
+ }
+ if( d->selection_timer.isActive())
+ return;
+ d->selection_timer.start( 100, true );
+}
+
+void KMenuBar::selectionTimeout()
+{ // nobody is managing us, handle resizing
+ if ( d->topLevel )
+ {
+ d->fallback_mode = true; // KMenuBar is handling its position itself
+ KConfigGroup xineramaConfig(KGlobal::config(),"Xinerama");
+ int screen = xineramaConfig.readNumEntry("MenubarScreen",
+ QApplication::desktop()->screenNumber(QPoint(0,0)) );
+ QRect area = QApplication::desktop()->screenGeometry(screen);
+ int margin = 0;
+ move(area.left() - margin, area.top() - margin);
+ setFixedSize(area.width() + 2* margin , heightForWidth( area.width() + 2 * margin ) );
+#ifdef Q_WS_X11
+ int strut_height = height() - margin;
+ if( strut_height < 0 )
+ strut_height = 0;
+ KWin::setStrut( winId(), 0, 0, strut_height, 0 );
+#endif
+ }
+}
+
+int KMenuBar::block_resize = 0;
+
+void KMenuBar::resizeEvent( QResizeEvent *e )
+{
+ if( e->spontaneous() && d->topLevel && !d->fallback_mode )
+ {
+ ++block_resize; // do not respond with configure request to ConfigureNotify event
+ QMenuBar::resizeEvent(e); // to avoid possible infinite loop
+ --block_resize;
+ }
+ else
+ QMenuBar::resizeEvent(e);
+}
+
+void KMenuBar::setGeometry( const QRect& r )
+{
+ setGeometry( r.x(), r.y(), r.width(), r.height() );
+}
+
+void KMenuBar::setGeometry( int x, int y, int w, int h )
+{
+ if( block_resize > 0 )
+ {
+ move( x, y );
+ return;
+ }
+ checkSize( w, h );
+ if( geometry() != QRect( x, y, w, h ))
+ QMenuBar::setGeometry( x, y, w, h );
+}
+
+void KMenuBar::resize( int w, int h )
+{
+ if( block_resize > 0 )
+ return;
+ checkSize( w, h );
+ if( size() != QSize( w, h ))
+ QMenuBar::resize( w, h );
+// kdDebug() << "RS:" << w << ":" << h << ":" << width() << ":" << height() << ":" << minimumWidth() << ":" << minimumHeight() << endl;
+}
+
+void KMenuBar::checkSize( int& w, int& h )
+{
+ if( !d->topLevel || d->fallback_mode )
+ return;
+ QSize s = sizeHint();
+ w = s.width();
+ h = s.height();
+ // This is not done as setMinimumSize(), because that would set the minimum
+ // size in WM_NORMAL_HINTS, and KWin would not allow changing to smaller size
+ // anymore
+ w = KMAX( w, d->min_size.width());
+ h = KMAX( h, d->min_size.height());
+}
+
+// QMenuBar's sizeHint() gives wrong size (insufficient width), which causes wrapping in the kicker applet
+QSize KMenuBar::sizeHint() const
+{
+ if( !d->topLevel || block_resize > 0 )
+ return QMenuBar::sizeHint();
+ // Since QMenuBar::sizeHint() may indirectly call resize(),
+ // avoid infinite recursion.
+ ++block_resize;
+ // find the minimum useful height, and enlarge the width until the menu fits in that height (one row)
+ int h = heightForWidth( 1000000 );
+ int w = QMenuBar::sizeHint().width();
+ // optimization - don't call heightForWidth() too many times
+ while( heightForWidth( w + 12 ) > h )
+ w += 12;
+ while( heightForWidth( w + 4 ) > h )
+ w += 4;
+ while( heightForWidth( w ) > h )
+ ++w;
+ --block_resize;
+ return QSize( w, h );
+}
+
+#ifdef Q_WS_X11
+bool KMenuBar::x11Event( XEvent* ev )
+{
+ if( ev->type == ClientMessage && ev->xclient.message_type == msg_type_atom
+ && ev->xclient.window == winId())
+ {
+ // QMenuBar is trying really hard to keep the size it deems right.
+ // Forcing minimum size and blocking resizing to match parent size
+ // in checkResizingToParent() seem to be the only way to make
+ // KMenuBar keep the size it wants
+ d->min_size = QSize( ev->xclient.data.l[ 1 ], ev->xclient.data.l[ 2 ] );
+// kdDebug() << "MINSIZE:" << d->min_size << endl;
+ updateMenuBarSize();
+ return true;
+ }
+ return QMenuBar::x11Event( ev );
+}
+#endif
+
+void KMenuBar::updateMenuBarSize()
+ {
+ menuContentsChanged(); // trigger invalidating calculated size
+ resize( sizeHint()); // and resize to preferred size
+ }
+
+void KMenuBar::setFrameStyle( int style )
+{
+ if( d->topLevel )
+ d->frameStyle = style;
+ else
+ QMenuBar::setFrameStyle( style );
+}
+
+void KMenuBar::setLineWidth( int width )
+{
+ if( d->topLevel )
+ d->lineWidth = width;
+ else
+ QMenuBar::setLineWidth( width );
+}
+
+void KMenuBar::setMargin( int margin )
+{
+ if( d->topLevel )
+ d->margin = margin;
+ else
+ QMenuBar::setMargin( margin );
+}
+
+void KMenuBar::closeEvent( QCloseEvent* e )
+{
+ if( d->topLevel )
+ e->ignore(); // mainly for the fallback mode
+ else
+ QMenuBar::closeEvent( e );
+}
+
+void KMenuBar::drawContents( QPainter* p )
+{
+ // Closes the BR77113
+ // We need to overload this method to paint only the menu items
+ // This way when the KMenuBar is embedded in the menu applet it
+ // integrates correctly.
+ //
+ // Background mode and origin are set so late because of styles
+ // using the polish() method to modify these settings.
+ //
+ // Of course this hack can safely be removed when real transparency
+ // will be available
+
+ if( !d->topLevel )
+ {
+ QMenuBar::drawContents(p);
+ }
+ else
+ {
+ bool up_enabled = isUpdatesEnabled();
+ BackgroundMode bg_mode = backgroundMode();
+ BackgroundOrigin bg_origin = backgroundOrigin();
+
+ setUpdatesEnabled(false);
+ setBackgroundMode(X11ParentRelative);
+ setBackgroundOrigin(WindowOrigin);
+
+ p->eraseRect( rect() );
+ erase();
+
+ QColorGroup g = colorGroup();
+ bool e;
+
+ for ( int i=0; i<(int)count(); i++ )
+ {
+ QMenuItem *mi = findItem( idAt( i ) );
+
+ if ( !mi->text().isNull() || mi->pixmap() )
+ {
+ QRect r = itemRect(i);
+ if(r.isEmpty() || !mi->isVisible())
+ continue;
+
+ e = mi->isEnabledAndVisible();
+ if ( e )
+ g = isEnabled() ? ( isActiveWindow() ? palette().active() :
+ palette().inactive() ) : palette().disabled();
+ else
+ g = palette().disabled();
+
+ bool item_active = ( actItem == i );
+
+ p->setClipRect(r);
+
+ if( item_active )
+ {
+ QStyle::SFlags flags = QStyle::Style_Default;
+ if (isEnabled() && e)
+ flags |= QStyle::Style_Enabled;
+ if ( item_active )
+ flags |= QStyle::Style_Active;
+ if ( item_active && actItemDown )
+ flags |= QStyle::Style_Down;
+ flags |= QStyle::Style_HasFocus;
+
+ style().drawControl(QStyle::CE_MenuBarItem, p, this,
+ r, g, flags, QStyleOption(mi));
+ }
+ else
+ {
+ style().drawItem(p, r, AlignCenter | AlignVCenter | ShowPrefix,
+ g, e, mi->pixmap(), mi->text());
+ }
+ }
+ }
+
+ setBackgroundOrigin(bg_origin);
+ setBackgroundMode(bg_mode);
+ setUpdatesEnabled(up_enabled);
+ }
+}
+
+void KMenuBar::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "kmenubar.moc"
diff --git a/kdeui/kmenubar.h b/kdeui/kmenubar.h
new file mode 100644
index 000000000..91309a2a8
--- /dev/null
+++ b/kdeui/kmenubar.h
@@ -0,0 +1,114 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997, 1998, 1999, 2000 Sven Radej (radej@kde.org)
+ Copyright (C) 1997, 1998, 1999, 2000 Matthias Ettrich (ettrich@kde.org)
+ Copyright (C) 1999, 2000 Daniel "Mosfet" Duley (mosfet@kde.org)
+
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+//$Id$
+
+#ifndef _KMENUBAR_H
+#define _KMENUBAR_H
+
+#include <qmenubar.h>
+
+#include <kdelibs_export.h>
+
+/**
+ * %KDE Style-able menubar.
+ *
+ * This is required since QMenuBar is currently not handled by
+ * QStyle.
+ *
+ * @author Daniel "Mosfet" Duley.
+ * @version $Id$
+*/
+
+class KDEUI_EXPORT KMenuBar : public QMenuBar
+{
+ Q_OBJECT
+
+public:
+
+ KMenuBar (QWidget *parent=0, const char *name=0);
+ ~KMenuBar ();
+
+ /**
+ * This controls whether or not this menubar will be a top-level
+ * bar similar to the way Macintosh handles menubars. This
+ * overrides any global config settings.
+ *
+ * Keep in mind that it is probably a really bad idea to use this
+ * unless you really know what you're doing. A feature like a
+ * top-level menubar is one that should really be shared by all
+ * applications. If your app is the only one with a top-level
+ * bar, then things might look very... odd.
+ *
+ * This is included only for those people that @p do know that
+ * they need to use it.
+ *
+ * @param top_level If set to true, then this menubar will be a
+ * top-level menu
+ */
+ void setTopLevelMenu(bool top_level = true);
+
+ /**
+ * Is our menubar a top-level (Macintosh style) menubar?
+ *
+ * @return True if it is top-level.
+ */
+ bool isTopLevelMenu() const;
+
+ // TT are overloading virtuals :(
+ virtual void setGeometry( const QRect &r );
+ virtual void setGeometry( int x, int y, int w, int h );
+ virtual void resize( int w, int h );
+ void resize( const QSize& s ) { QMenuBar::resize( s ); }
+
+ virtual void show();
+ virtual void setFrameStyle( int );
+ virtual void setLineWidth( int );
+ virtual void setMargin( int );
+ virtual QSize sizeHint() const;
+protected slots:
+ void slotReadConfig();
+protected:
+ virtual void showEvent( QShowEvent* );
+ virtual void resizeEvent( QResizeEvent* );
+ virtual bool eventFilter(QObject *, QEvent *);
+#ifdef Q_WS_X11
+ virtual bool x11Event( XEvent* );
+#endif
+ virtual void closeEvent( QCloseEvent* );
+ virtual void drawContents( QPainter* );
+private slots:
+ void updateFallbackSize();
+ void selectionTimeout();
+private:
+ void setTopLevelMenuInternal(bool top_level);
+ void updateMenuBarSize();
+ void checkSize( int& w, int& h );
+ static int block_resize;
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KMenuBarPrivate;
+ KMenuBarPrivate *d;
+};
+
+#endif
diff --git a/kdeui/kmessagebox.cpp b/kdeui/kmessagebox.cpp
new file mode 100644
index 000000000..46336e9c6
--- /dev/null
+++ b/kdeui/kmessagebox.cpp
@@ -0,0 +1,1071 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Waldo Bastian (bastian@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; version 2
+ of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qcheckbox.h>
+#include <qguardedptr.h>
+#include <qhbox.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qmessagebox.h>
+#include <qstringlist.h>
+#include <qvbox.h>
+#include <qvgroupbox.h>
+#include <qstylesheet.h>
+#include <qsimplerichtext.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kdialogbase.h>
+#include <kguiitem.h>
+#include <klistbox.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <knotifyclient.h>
+#include <kstdguiitem.h>
+#include <kactivelabel.h>
+#include <kiconloader.h>
+#include <kglobalsettings.h>
+
+#ifdef Q_WS_X11
+#include <X11/Xlib.h>
+#endif
+
+ /**
+ * Easy MessageBox Dialog.
+ *
+ * Provides convenience functions for some i18n'ed standard dialogs,
+ * as well as audible notification via @ref KNotifyClient
+ *
+ * @author Waldo Bastian (bastian@kde.org)
+ */
+
+static bool KMessageBox_queue = false;
+
+static QPixmap themedMessageBoxIcon(QMessageBox::Icon icon)
+{
+ QString icon_name;
+
+ switch(icon)
+ {
+ case QMessageBox::NoIcon:
+ return QPixmap();
+ break;
+ case QMessageBox::Information:
+ icon_name = "messagebox_info";
+ break;
+ case QMessageBox::Warning:
+ icon_name = "messagebox_warning";
+ break;
+ case QMessageBox::Critical:
+ icon_name = "messagebox_critical";
+ break;
+ default:
+ break;
+ }
+
+ QPixmap ret = KGlobal::iconLoader()->loadIcon(icon_name, KIcon::NoGroup, KIcon::SizeMedium, KIcon::DefaultState, 0, true);
+
+ if (ret.isNull())
+ return QMessageBox::standardIcon(icon);
+ else
+ return ret;
+}
+
+static void sendNotification( QString message,
+ const QStringList& strlist,
+ QMessageBox::Icon icon,
+ WId parent_id )
+{
+ // create the message for KNotify
+ QString messageType;
+ switch ( icon )
+ {
+ case QMessageBox::Warning:
+ messageType = "messageWarning";
+ break;
+ case QMessageBox::Critical:
+ messageType = "messageCritical";
+ break;
+ case QMessageBox::Question:
+ messageType = "messageQuestion";
+ break;
+ default:
+ messageType = "messageInformation";
+ break;
+ }
+
+ if ( !strlist.isEmpty() )
+ {
+ for ( QStringList::ConstIterator it = strlist.begin(); it != strlist.end(); ++it )
+ message += "\n" + *it;
+ }
+
+ if ( !message.isEmpty() )
+ KNotifyClient::event( (int)parent_id, messageType, message );
+}
+
+static QString qrichtextify( const QString& text )
+{
+ if ( text.isEmpty() || text[0] == '<' )
+ return text;
+
+ QStringList lines = QStringList::split('\n', text);
+ for(QStringList::Iterator it = lines.begin(); it != lines.end(); ++it)
+ {
+ *it = QStyleSheet::convertFromPlainText( *it, QStyleSheetItem::WhiteSpaceNormal );
+ }
+
+ return lines.join(QString::null);
+}
+
+int KMessageBox::createKMessageBox(KDialogBase *dialog, QMessageBox::Icon icon,
+ const QString &text, const QStringList &strlist,
+ const QString &ask, bool *checkboxReturn,
+ int options, const QString &details)
+{
+ return createKMessageBox(dialog, themedMessageBoxIcon(icon), text, strlist,
+ ask, checkboxReturn, options, details, icon);
+}
+
+int KMessageBox::createKMessageBox(KDialogBase *dialog, QPixmap icon,
+ const QString &text, const QStringList &strlist,
+ const QString &ask, bool *checkboxReturn, int options,
+ const QString &details, QMessageBox::Icon notifyType)
+{
+ QVBox *topcontents = new QVBox (dialog);
+ topcontents->setSpacing(KDialog::spacingHint()*2);
+ topcontents->setMargin(KDialog::marginHint());
+
+ QWidget *contents = new QWidget(topcontents);
+ QHBoxLayout * lay = new QHBoxLayout(contents);
+ lay->setSpacing(KDialog::spacingHint());
+
+ QLabel *label1 = new QLabel( contents);
+
+ if (!icon.isNull())
+ label1->setPixmap(icon);
+
+ lay->addWidget( label1, 0, Qt::AlignCenter );
+ lay->addSpacing(KDialog::spacingHint());
+ // Enforce <p>text</p> otherwise the word-wrap doesn't work well
+ QString qt_text = qrichtextify( text );
+
+ int pref_width = 0;
+ int pref_height = 0;
+ // Calculate a proper size for the text.
+ {
+ QSimpleRichText rt(qt_text, dialog->font());
+ QRect d = KGlobalSettings::desktopGeometry(dialog);
+
+ pref_width = d.width() / 3;
+ rt.setWidth(pref_width);
+ int used_width = rt.widthUsed();
+ pref_height = rt.height();
+ if (3*pref_height > 2*d.height())
+ {
+ // Very high dialog.. make it wider
+ pref_width = d.width() / 2;
+ rt.setWidth(pref_width);
+ used_width = rt.widthUsed();
+ pref_height = rt.height();
+ }
+ if (used_width <= pref_width)
+ {
+ while(true)
+ {
+ int new_width = (used_width * 9) / 10;
+ rt.setWidth(new_width);
+ int new_height = rt.height();
+ if (new_height > pref_height)
+ break;
+ used_width = rt.widthUsed();
+ if (used_width > new_width)
+ break;
+ }
+ pref_width = used_width;
+ }
+ else
+ {
+ if (used_width > (pref_width *2))
+ pref_width = pref_width *2;
+ else
+ pref_width = used_width;
+ }
+ }
+ KActiveLabel *label2 = new KActiveLabel( qt_text, contents );
+ if (!(options & KMessageBox::AllowLink))
+ {
+ QObject::disconnect(label2, SIGNAL(linkClicked(const QString &)),
+ label2, SLOT(openLink(const QString &)));
+ }
+
+ // We add 10 pixels extra to compensate for some KActiveLabel margins.
+ // TODO: find out why this is 10.
+ label2->setFixedSize(QSize(pref_width+10, pref_height));
+ lay->addWidget( label2 );
+ lay->addStretch();
+
+ KListBox *listbox = 0;
+ if (!strlist.isEmpty())
+ {
+ listbox=new KListBox( topcontents );
+ listbox->insertStringList( strlist );
+ listbox->setSelectionMode( QListBox::NoSelection );
+ topcontents->setStretchFactor(listbox, 1);
+ }
+
+ QGuardedPtr<QCheckBox> checkbox = 0;
+ if (!ask.isEmpty())
+ {
+ checkbox = new QCheckBox(ask, topcontents);
+ if (checkboxReturn)
+ checkbox->setChecked(*checkboxReturn);
+ }
+
+ if (!details.isEmpty())
+ {
+ QVGroupBox *detailsGroup = new QVGroupBox( i18n("Details"), dialog);
+ if ( details.length() < 512 ) {
+ KActiveLabel *label3 = new KActiveLabel(qrichtextify(details),
+ detailsGroup);
+ label3->setMinimumSize(label3->sizeHint());
+ if (!(options & KMessageBox::AllowLink))
+ {
+ QObject::disconnect(label3, SIGNAL(linkClicked(const QString &)),
+ label3, SLOT(openLink(const QString &)));
+ }
+ } else {
+ QTextEdit* te = new QTextEdit(details, QString::null, detailsGroup);
+ te->setReadOnly( true );
+ te->setMinimumHeight( te->fontMetrics().lineSpacing() * 11 );
+ }
+ dialog->setDetailsWidget(detailsGroup);
+ }
+
+ dialog->setMainWidget(topcontents);
+ dialog->enableButtonSeparator(false);
+ if (!listbox)
+ dialog->disableResize();
+
+ const KDialogBase::ButtonCode buttons[] = {
+ KDialogBase::Help,
+ KDialogBase::Default,
+ KDialogBase::Ok,
+ KDialogBase::Apply,
+ KDialogBase::Try,
+ KDialogBase::Cancel,
+ KDialogBase::Close,
+ KDialogBase::User1,
+ KDialogBase::User2,
+ KDialogBase::User3,
+ KDialogBase::No,
+ KDialogBase::Yes,
+ KDialogBase::Details };
+ for( unsigned int i = 0;
+ i < sizeof( buttons )/sizeof( buttons[ 0 ] );
+ ++i )
+ if( QPushButton* btn = dialog->actionButton( buttons[ i ] ))
+ if( btn->isDefault())
+ btn->setFocus();
+
+ if ( (options & KMessageBox::Notify) )
+ sendNotification( text, strlist, notifyType, dialog->topLevelWidget()->winId());
+
+ if (KMessageBox_queue)
+ {
+ KDialogQueue::queueDialog(dialog);
+ return KMessageBox::Cancel; // We have to return something.
+ }
+
+ if ( (options & KMessageBox::NoExec) )
+ {
+ return KMessageBox::Cancel; // We have to return something.
+ }
+
+ // We use a QGuardedPtr because the dialog may get deleted
+ // during exec() if the parent of the dialog gets deleted.
+ // In that case the guarded ptr will reset to 0.
+ QGuardedPtr<KDialogBase> guardedDialog = dialog;
+
+ int result = guardedDialog->exec();
+ if (checkbox && checkboxReturn)
+ *checkboxReturn = checkbox->isChecked();
+ delete (KDialogBase *) guardedDialog;
+ return result;
+}
+
+int
+KMessageBox::questionYesNo(QWidget *parent, const QString &text,
+ const QString &caption,
+ const KGuiItem &buttonYes,
+ const KGuiItem &buttonNo,
+ const QString &dontAskAgainName,
+ int options)
+{
+ return questionYesNoList(parent, text, QStringList(), caption,
+ buttonYes, buttonNo, dontAskAgainName, options);
+}
+
+int
+KMessageBox::questionYesNoWId(WId parent_id, const QString &text,
+ const QString &caption,
+ const KGuiItem &buttonYes,
+ const KGuiItem &buttonNo,
+ const QString &dontAskAgainName,
+ int options)
+{
+ return questionYesNoListWId(parent_id, text, QStringList(), caption,
+ buttonYes, buttonNo, dontAskAgainName, options);
+}
+
+bool
+KMessageBox::shouldBeShownYesNo(const QString &dontShowAgainName,
+ ButtonCode &result)
+{
+ if ( dontShowAgainName.isEmpty() ) return true;
+ QString grpNotifMsgs = QString::fromLatin1("Notification Messages");
+ KConfig *config = againConfig ? againConfig : KGlobal::config();
+ KConfigGroupSaver saver( config, grpNotifMsgs );
+ QString dontAsk = config->readEntry(dontShowAgainName).lower();
+ if (dontAsk == "yes") {
+ result = Yes;
+ return false;
+ }
+ if (dontAsk == "no") {
+ result = No;
+ return false;
+ }
+ return true;
+}
+
+bool
+KMessageBox::shouldBeShownContinue(const QString &dontShowAgainName)
+{
+ if ( dontShowAgainName.isEmpty() ) return true;
+ QString grpNotifMsgs = QString::fromLatin1("Notification Messages");
+ KConfig *config = againConfig ? againConfig : KGlobal::config();
+ KConfigGroupSaver saver( config, grpNotifMsgs );
+ return config->readBoolEntry(dontShowAgainName, true);
+}
+
+void
+KMessageBox::saveDontShowAgainYesNo(const QString &dontShowAgainName,
+ ButtonCode result)
+{
+ if ( dontShowAgainName.isEmpty() ) return;
+ QString grpNotifMsgs = QString::fromLatin1("Notification Messages");
+ KConfig *config = againConfig ? againConfig : KGlobal::config();
+ KConfigGroupSaver saver( config, grpNotifMsgs );
+ config->writeEntry( dontShowAgainName, result==Yes ? "yes" : "no", true, (dontShowAgainName[0] == ':'));
+ config->sync();
+}
+
+void
+KMessageBox::saveDontShowAgainContinue(const QString &dontShowAgainName)
+{
+ if ( dontShowAgainName.isEmpty() ) return;
+ QString grpNotifMsgs = QString::fromLatin1("Notification Messages");
+ KConfig *config = againConfig ? againConfig : KGlobal::config();
+ KConfigGroupSaver saver( config, grpNotifMsgs );
+ config->writeEntry( dontShowAgainName, false, true, (dontShowAgainName[0] == ':'));
+ config->sync();
+}
+
+KConfig* KMessageBox::againConfig = NULL;
+void
+KMessageBox::setDontShowAskAgainConfig(KConfig* cfg)
+{
+ againConfig = cfg;
+}
+
+int
+KMessageBox::questionYesNoList(QWidget *parent, const QString &text,
+ const QStringList &strlist,
+ const QString &caption,
+ const KGuiItem &buttonYes,
+ const KGuiItem &buttonNo,
+ const QString &dontAskAgainName,
+ int options)
+{ // in order to avoid code duplication, convert to WId, it will be converted back
+ return questionYesNoListWId( parent ? parent->winId() : 0, text, strlist,
+ caption, buttonYes, buttonNo, dontAskAgainName, options );
+}
+
+int
+KMessageBox::questionYesNoListWId(WId parent_id, const QString &text,
+ const QStringList &strlist,
+ const QString &caption,
+ const KGuiItem &buttonYes,
+ const KGuiItem &buttonNo,
+ const QString &dontAskAgainName,
+ int options)
+{
+ ButtonCode res;
+ if ( !shouldBeShownYesNo(dontAskAgainName, res) )
+ return res;
+
+ QWidget* parent = QWidget::find( parent_id );
+ KDialogBase *dialog= new KDialogBase(
+ caption.isEmpty() ? i18n("Question") : caption,
+ KDialogBase::Yes | KDialogBase::No,
+ KDialogBase::Yes, KDialogBase::No,
+ parent, "questionYesNo", true, true,
+ buttonYes, buttonNo);
+ if( options & PlainCaption )
+ dialog->setPlainCaption( caption );
+#ifdef Q_WS_X11
+ if( parent == NULL && parent_id )
+ XSetTransientForHint( qt_xdisplay(), dialog->winId(), parent_id );
+#endif
+
+ bool checkboxResult = false;
+ int result = createKMessageBox(dialog, QMessageBox::Information, text, strlist,
+ dontAskAgainName.isEmpty() ? QString::null : i18n("Do not ask again"),
+ &checkboxResult, options);
+ res = (result==KDialogBase::Yes ? Yes : No);
+
+ if (checkboxResult)
+ saveDontShowAgainYesNo(dontAskAgainName, res);
+ return res;
+}
+
+int
+KMessageBox::questionYesNoCancel(QWidget *parent,
+ const QString &text,
+ const QString &caption,
+ const KGuiItem &buttonYes,
+ const KGuiItem &buttonNo,
+ const QString &dontAskAgainName,
+ int options)
+{
+ return questionYesNoCancelWId( parent ? parent->winId() : 0, text, caption, buttonYes, buttonNo,
+ dontAskAgainName, options );
+}
+
+int
+KMessageBox::questionYesNoCancelWId(WId parent_id,
+ const QString &text,
+ const QString &caption,
+ const KGuiItem &buttonYes,
+ const KGuiItem &buttonNo,
+ const QString &dontAskAgainName,
+ int options)
+{
+ ButtonCode res;
+ if ( !shouldBeShownYesNo(dontAskAgainName, res) )
+ return res;
+
+ QWidget* parent = QWidget::find( parent_id );
+ KDialogBase *dialog= new KDialogBase(
+ caption.isEmpty() ? i18n("Question") : caption,
+ KDialogBase::Yes | KDialogBase::No | KDialogBase::Cancel,
+ KDialogBase::Yes, KDialogBase::Cancel,
+ parent, "questionYesNoCancel", true, true,
+ buttonYes, buttonNo);
+ if( options & PlainCaption )
+ dialog->setPlainCaption( caption );
+#ifdef Q_WS_X11
+ if( parent == NULL && parent_id )
+ XSetTransientForHint( qt_xdisplay(), dialog->winId(), parent_id );
+#endif
+
+ bool checkboxResult = false;
+ int result = createKMessageBox(dialog, QMessageBox::Information,
+ text, QStringList(),
+ dontAskAgainName.isEmpty() ? QString::null : i18n("Do not ask again"),
+ &checkboxResult, options);
+ if ( result==KDialogBase::Cancel ) return Cancel;
+ res = (result==KDialogBase::Yes ? Yes : No);
+
+ if (checkboxResult)
+ saveDontShowAgainYesNo(dontAskAgainName, res);
+ return res;
+}
+
+int
+KMessageBox::warningYesNo(QWidget *parent, const QString &text,
+ const QString &caption,
+ const KGuiItem &buttonYes,
+ const KGuiItem &buttonNo,
+ const QString &dontAskAgainName,
+ int options)
+{
+ return warningYesNoList(parent, text, QStringList(), caption,
+ buttonYes, buttonNo, dontAskAgainName, options);
+}
+
+int
+KMessageBox::warningYesNoWId(WId parent_id, const QString &text,
+ const QString &caption,
+ const KGuiItem &buttonYes,
+ const KGuiItem &buttonNo,
+ const QString &dontAskAgainName,
+ int options)
+{
+ return warningYesNoListWId(parent_id, text, QStringList(), caption,
+ buttonYes, buttonNo, dontAskAgainName, options);
+}
+
+int
+KMessageBox::warningYesNoList(QWidget *parent, const QString &text,
+ const QStringList &strlist,
+ const QString &caption,
+ const KGuiItem &buttonYes,
+ const KGuiItem &buttonNo,
+ const QString &dontAskAgainName,
+ int options)
+{
+ return warningYesNoListWId( parent ? parent->winId() : 0, text, strlist, caption,
+ buttonYes, buttonNo, dontAskAgainName, options );
+}
+
+int
+KMessageBox::warningYesNoListWId(WId parent_id, const QString &text,
+ const QStringList &strlist,
+ const QString &caption,
+ const KGuiItem &buttonYes,
+ const KGuiItem &buttonNo,
+ const QString &dontAskAgainName,
+ int options)
+{
+ // warningYesNo and warningYesNoList are always "dangerous"
+ // ### Remove this line for KDE 4, when the 'options' default parameter
+ // takes effects.
+ options |= Dangerous;
+
+ ButtonCode res;
+ if ( !shouldBeShownYesNo(dontAskAgainName, res) )
+ return res;
+
+ QWidget* parent = QWidget::find( parent_id );
+ KDialogBase *dialog= new KDialogBase(
+ caption.isEmpty() ? i18n("Warning") : caption,
+ KDialogBase::Yes | KDialogBase::No,
+ KDialogBase::No, KDialogBase::No,
+ parent, "warningYesNoList", true, true,
+ buttonYes, buttonNo);
+ if( options & PlainCaption )
+ dialog->setPlainCaption( caption );
+#ifdef Q_WS_X11
+ if( parent == NULL && parent_id )
+ XSetTransientForHint( qt_xdisplay(), dialog->winId(), parent_id );
+#endif
+
+ bool checkboxResult = false;
+ int result = createKMessageBox(dialog, QMessageBox::Warning, text, strlist,
+ dontAskAgainName.isEmpty() ? QString::null : i18n("Do not ask again"),
+ &checkboxResult, options);
+ res = (result==KDialogBase::Yes ? Yes : No);
+
+ if (checkboxResult)
+ saveDontShowAgainYesNo(dontAskAgainName, res);
+ return res;
+}
+
+int
+KMessageBox::warningContinueCancel(QWidget *parent,
+ const QString &text,
+ const QString &caption,
+ const KGuiItem &buttonContinue,
+ const QString &dontAskAgainName,
+ int options)
+{
+ return warningContinueCancelList(parent, text, QStringList(), caption,
+ buttonContinue, dontAskAgainName, options);
+}
+
+int
+KMessageBox::warningContinueCancelWId(WId parent_id,
+ const QString &text,
+ const QString &caption,
+ const KGuiItem &buttonContinue,
+ const QString &dontAskAgainName,
+ int options)
+{
+ return warningContinueCancelListWId(parent_id, text, QStringList(), caption,
+ buttonContinue, dontAskAgainName, options);
+}
+
+int
+KMessageBox::warningContinueCancelList(QWidget *parent, const QString &text,
+ const QStringList &strlist,
+ const QString &caption,
+ const KGuiItem &buttonContinue,
+ const QString &dontAskAgainName,
+ int options)
+{
+ return warningContinueCancelListWId( parent ? parent->winId() : 0, text, strlist,
+ caption, buttonContinue, dontAskAgainName, options );
+}
+
+int
+KMessageBox::warningContinueCancelListWId(WId parent_id, const QString &text,
+ const QStringList &strlist,
+ const QString &caption,
+ const KGuiItem &buttonContinue,
+ const QString &dontAskAgainName,
+ int options)
+{
+ if ( !shouldBeShownContinue(dontAskAgainName) )
+ return Continue;
+
+ QWidget* parent = QWidget::find( parent_id );
+ KDialogBase *dialog= new KDialogBase(
+ caption.isEmpty() ? i18n("Warning") : caption,
+ KDialogBase::Yes | KDialogBase::No,
+ KDialogBase::Yes, KDialogBase::No,
+ parent, "warningYesNo", true, true,
+ buttonContinue, KStdGuiItem::cancel() );
+ if( options & PlainCaption )
+ dialog->setPlainCaption( caption );
+#ifdef Q_WS_X11
+ if( parent == NULL && parent_id )
+ XSetTransientForHint( qt_xdisplay(), dialog->winId(), parent_id );
+#endif
+
+ bool checkboxResult = false;
+ int result = createKMessageBox(dialog, QMessageBox::Warning, text, strlist,
+ dontAskAgainName.isEmpty() ? QString::null : i18n("Do not ask again"),
+ &checkboxResult, options);
+
+ if ( result==KDialogBase::No )
+ return Cancel;
+ if (checkboxResult)
+ saveDontShowAgainContinue(dontAskAgainName);
+ return Continue;
+}
+
+int
+KMessageBox::warningYesNoCancel(QWidget *parent, const QString &text,
+ const QString &caption,
+ const KGuiItem &buttonYes,
+ const KGuiItem &buttonNo,
+ const QString &dontAskAgainName,
+ int options)
+{
+ return warningYesNoCancelList(parent, text, QStringList(), caption,
+ buttonYes, buttonNo, dontAskAgainName, options);
+}
+
+int
+KMessageBox::warningYesNoCancelWId(WId parent_id, const QString &text,
+ const QString &caption,
+ const KGuiItem &buttonYes,
+ const KGuiItem &buttonNo,
+ const QString &dontAskAgainName,
+ int options)
+{
+ return warningYesNoCancelListWId(parent_id, text, QStringList(), caption,
+ buttonYes, buttonNo, dontAskAgainName, options);
+}
+
+int
+KMessageBox::warningYesNoCancelList(QWidget *parent, const QString &text,
+ const QStringList &strlist,
+ const QString &caption,
+ const KGuiItem &buttonYes,
+ const KGuiItem &buttonNo,
+ const QString &dontAskAgainName,
+ int options)
+{
+ return warningYesNoCancelListWId( parent ? parent->winId() : 0, text, strlist,
+ caption, buttonYes, buttonNo, dontAskAgainName, options );
+}
+
+int
+KMessageBox::warningYesNoCancelListWId(WId parent_id, const QString &text,
+ const QStringList &strlist,
+ const QString &caption,
+ const KGuiItem &buttonYes,
+ const KGuiItem &buttonNo,
+ const QString &dontAskAgainName,
+ int options)
+{
+ ButtonCode res;
+ if ( !shouldBeShownYesNo(dontAskAgainName, res) )
+ return res;
+
+ QWidget* parent = QWidget::find( parent_id );
+ KDialogBase *dialog= new KDialogBase(
+ caption.isEmpty() ? i18n("Warning") : caption,
+ KDialogBase::Yes | KDialogBase::No | KDialogBase::Cancel,
+ KDialogBase::Yes, KDialogBase::Cancel,
+ parent, "warningYesNoCancel", true, true,
+ buttonYes, buttonNo);
+ if( options & PlainCaption )
+ dialog->setPlainCaption( caption );
+#ifdef Q_WS_X11
+ if( parent == NULL && parent_id )
+ XSetTransientForHint( qt_xdisplay(), dialog->winId(), parent_id );
+#endif
+
+ bool checkboxResult = false;
+ int result = createKMessageBox(dialog, QMessageBox::Warning, text, strlist,
+ dontAskAgainName.isEmpty() ? QString::null : i18n("Do not ask again"),
+ &checkboxResult, options);
+ if ( result==KDialogBase::Cancel ) return Cancel;
+ res = (result==KDialogBase::Yes ? Yes : No);
+
+ if (checkboxResult)
+ saveDontShowAgainYesNo(dontAskAgainName, res);
+ return res;
+}
+
+void
+KMessageBox::error(QWidget *parent, const QString &text,
+ const QString &caption, int options)
+{
+ return errorListWId( parent ? parent->winId() : 0, text, QStringList(), caption, options );
+}
+
+void
+KMessageBox::errorWId(WId parent_id, const QString &text,
+ const QString &caption, int options)
+{
+ errorListWId( parent_id, text, QStringList(), caption, options );
+}
+
+void
+KMessageBox::errorList(QWidget *parent, const QString &text, const QStringList &strlist,
+ const QString &caption, int options)
+{
+ return errorListWId( parent ? parent->winId() : 0, text, strlist, caption, options );
+}
+
+void
+KMessageBox::errorListWId(WId parent_id, const QString &text, const QStringList &strlist,
+ const QString &caption, int options)
+{
+ QWidget* parent = QWidget::find( parent_id );
+ KDialogBase *dialog= new KDialogBase(
+ caption.isEmpty() ? i18n("Error") : caption,
+ KDialogBase::Yes,
+ KDialogBase::Yes, KDialogBase::Yes,
+ parent, "error", true, true,
+ KStdGuiItem::ok() );
+ if( options & PlainCaption )
+ dialog->setPlainCaption( caption );
+#ifdef Q_WS_X11
+ if( parent == NULL && parent_id )
+ XSetTransientForHint( qt_xdisplay(), dialog->winId(), parent_id );
+#endif
+
+ createKMessageBox(dialog, QMessageBox::Critical, text, strlist, QString::null, 0, options);
+}
+
+void
+KMessageBox::detailedError(QWidget *parent, const QString &text,
+ const QString &details,
+ const QString &caption, int options)
+{
+ return detailedErrorWId( parent ? parent->winId() : 0, text, details, caption, options );
+}
+
+void
+KMessageBox::detailedErrorWId(WId parent_id, const QString &text,
+ const QString &details,
+ const QString &caption, int options)
+{
+ QWidget* parent = QWidget::find( parent_id );
+ KDialogBase *dialog= new KDialogBase(
+ caption.isEmpty() ? i18n("Error") : caption,
+ KDialogBase::Yes | KDialogBase::Details,
+ KDialogBase::Yes, KDialogBase::Yes,
+ parent, "error", true, true,
+ KStdGuiItem::ok() );
+ if( options & PlainCaption )
+ dialog->setPlainCaption( caption );
+#ifdef Q_WS_X11
+ if( parent == NULL && parent_id )
+ XSetTransientForHint( qt_xdisplay(), dialog->winId(), parent_id );
+#endif
+
+ createKMessageBox(dialog, QMessageBox::Critical, text, QStringList(), QString::null, 0, options, details);
+}
+
+void
+KMessageBox::queuedDetailedError(QWidget *parent, const QString &text,
+ const QString &details,
+ const QString &caption)
+{
+ return queuedDetailedErrorWId( parent ? parent->winId() : 0, text, details, caption );
+}
+
+void
+KMessageBox::queuedDetailedErrorWId(WId parent_id, const QString &text,
+ const QString &details,
+ const QString &caption)
+{
+ KMessageBox_queue = true;
+ (void) detailedErrorWId(parent_id, text, details, caption);
+ KMessageBox_queue = false;
+}
+
+
+void
+KMessageBox::sorry(QWidget *parent, const QString &text,
+ const QString &caption, int options)
+{
+ return sorryWId( parent ? parent->winId() : 0, text, caption, options );
+}
+
+void
+KMessageBox::sorryWId(WId parent_id, const QString &text,
+ const QString &caption, int options)
+{
+ QWidget* parent = QWidget::find( parent_id );
+ KDialogBase *dialog= new KDialogBase(
+ caption.isEmpty() ? i18n("Sorry") : caption,
+ KDialogBase::Yes,
+ KDialogBase::Yes, KDialogBase::Yes,
+ parent, "sorry", true, true,
+ KStdGuiItem::ok() );
+ if( options & PlainCaption )
+ dialog->setPlainCaption( caption );
+#ifdef Q_WS_X11
+ if( parent == NULL && parent_id )
+ XSetTransientForHint( qt_xdisplay(), dialog->winId(), parent_id );
+#endif
+
+ createKMessageBox(dialog, QMessageBox::Warning, text, QStringList(), QString::null, 0, options);
+}
+
+void
+KMessageBox::detailedSorry(QWidget *parent, const QString &text,
+ const QString &details,
+ const QString &caption, int options)
+{
+ return detailedSorryWId( parent ? parent->winId() : 0, text, details, caption, options );
+}
+
+void
+KMessageBox::detailedSorryWId(WId parent_id, const QString &text,
+ const QString &details,
+ const QString &caption, int options)
+{
+ QWidget* parent = QWidget::find( parent_id );
+ KDialogBase *dialog= new KDialogBase(
+ caption.isEmpty() ? i18n("Sorry") : caption,
+ KDialogBase::Yes | KDialogBase::Details,
+ KDialogBase::Yes, KDialogBase::Yes,
+ parent, "sorry", true, true,
+ KStdGuiItem::ok() );
+ if( options & PlainCaption )
+ dialog->setPlainCaption( caption );
+#ifdef Q_WS_X11
+ if( parent == NULL && parent_id )
+ XSetTransientForHint( qt_xdisplay(), dialog->winId(), parent_id );
+#endif
+
+ createKMessageBox(dialog, QMessageBox::Warning, text, QStringList(), QString::null, 0, options, details);
+}
+
+void
+KMessageBox::information(QWidget *parent,const QString &text,
+ const QString &caption, const QString &dontShowAgainName, int options)
+{
+ informationList(parent, text, QStringList(), caption, dontShowAgainName, options);
+}
+
+void
+KMessageBox::informationWId(WId parent_id,const QString &text,
+ const QString &caption, const QString &dontShowAgainName, int options)
+{
+ informationListWId(parent_id, text, QStringList(), caption, dontShowAgainName, options);
+}
+
+void
+KMessageBox::informationList(QWidget *parent,const QString &text, const QStringList & strlist,
+ const QString &caption, const QString &dontShowAgainName, int options)
+{
+ return informationListWId( parent ? parent->winId() : 0, text, strlist, caption,
+ dontShowAgainName, options );
+}
+
+void
+KMessageBox::informationListWId(WId parent_id,const QString &text, const QStringList & strlist,
+ const QString &caption, const QString &dontShowAgainName, int options)
+{
+ if ( !shouldBeShownContinue(dontShowAgainName) )
+ return;
+
+ QWidget* parent = QWidget::find( parent_id );
+ KDialogBase *dialog= new KDialogBase(
+ caption.isEmpty() ? i18n("Information") : caption,
+ KDialogBase::Yes,
+ KDialogBase::Yes, KDialogBase::Yes,
+ parent, "information", true, true,
+ KStdGuiItem::ok() );
+ if( options & PlainCaption )
+ dialog->setPlainCaption( caption );
+#ifdef Q_WS_X11
+ if( parent == NULL && parent_id )
+ XSetTransientForHint( qt_xdisplay(), dialog->winId(), parent_id );
+#endif
+
+ bool checkboxResult = false;
+
+ createKMessageBox(dialog, QMessageBox::Information, text, strlist,
+ dontShowAgainName.isEmpty() ? QString::null : i18n("Do not show this message again"),
+ &checkboxResult, options);
+
+ if (checkboxResult)
+ saveDontShowAgainContinue(dontShowAgainName);
+}
+
+void
+KMessageBox::enableAllMessages()
+{
+ KConfig *config = againConfig ? againConfig : KGlobal::config();
+ QString grpNotifMsgs = QString::fromLatin1("Notification Messages");
+ if (!config->hasGroup(grpNotifMsgs))
+ return;
+
+ KConfigGroupSaver saver( config, grpNotifMsgs );
+
+ typedef QMap<QString, QString> configMap;
+
+ configMap map = config->entryMap(grpNotifMsgs);
+
+ configMap::Iterator it;
+ for (it = map.begin(); it != map.end(); ++it)
+ config->deleteEntry( it.key() );
+ config->sync();
+}
+
+void
+KMessageBox::enableMessage(const QString &dontShowAgainName)
+{
+ KConfig *config = againConfig ? againConfig : KGlobal::config();
+ QString grpNotifMsgs = QString::fromLatin1("Notification Messages");
+ if (!config->hasGroup(grpNotifMsgs))
+ return;
+
+ KConfigGroupSaver saver( config, grpNotifMsgs );
+
+ config->deleteEntry(dontShowAgainName);
+ config->sync();
+}
+
+void
+KMessageBox::about(QWidget *parent, const QString &text,
+ const QString &caption, int options)
+{
+ QString _caption = caption;
+ if (_caption.isEmpty())
+ _caption = i18n("About %1").arg(kapp->caption());
+
+ KDialogBase *dialog = new KDialogBase(
+ caption,
+ KDialogBase::Yes,
+ KDialogBase::Yes, KDialogBase::Yes,
+ parent, "about", true, true,
+ KStdGuiItem::ok() );
+
+ QPixmap ret = KApplication::kApplication()->icon();
+ if (ret.isNull())
+ ret = QMessageBox::standardIcon(QMessageBox::Information);
+ dialog->setIcon(ret);
+
+ createKMessageBox(dialog, ret, text, QStringList(), QString::null, 0, options);
+
+ return;
+}
+
+int KMessageBox::messageBox( QWidget *parent, DialogType type, const QString &text,
+ const QString &caption, const KGuiItem &buttonYes,
+ const KGuiItem &buttonNo, const QString &dontShowAskAgainName,
+ int options )
+{
+ return messageBoxWId( parent ? parent->winId() : 0, type, text, caption,
+ buttonYes, buttonNo, dontShowAskAgainName, options );
+}
+
+int KMessageBox::messageBox( QWidget *parent, DialogType type, const QString &text,
+ const QString &caption, const KGuiItem &buttonYes,
+ const KGuiItem &buttonNo, int options )
+{
+ return messageBoxWId( parent ? parent->winId() : 0, type, text, caption,
+ buttonYes, buttonNo, QString::null, options );
+}
+
+int KMessageBox::messageBoxWId( WId parent_id, DialogType type, const QString &text,
+ const QString &caption, const KGuiItem &buttonYes,
+ const KGuiItem &buttonNo, const QString &dontShow,
+ int options )
+{
+ switch (type) {
+ case QuestionYesNo:
+ return KMessageBox::questionYesNoWId( parent_id,
+ text, caption, buttonYes, buttonNo, dontShow, options );
+ case QuestionYesNoCancel:
+ return KMessageBox::questionYesNoCancelWId( parent_id,
+ text, caption, buttonYes, buttonNo, dontShow, options );
+ case WarningYesNo:
+ return KMessageBox::warningYesNoWId( parent_id,
+ text, caption, buttonYes, buttonNo, dontShow, options );
+ case WarningContinueCancel:
+ return KMessageBox::warningContinueCancelWId( parent_id,
+ text, caption, buttonYes.text(), dontShow, options );
+ case WarningYesNoCancel:
+ return KMessageBox::warningYesNoCancelWId( parent_id,
+ text, caption, buttonYes, buttonNo, dontShow, options );
+ case Information:
+ KMessageBox::informationWId( parent_id,
+ text, caption, dontShow, options );
+ return KMessageBox::Ok;
+
+ case Error:
+ KMessageBox::errorWId( parent_id, text, caption, options );
+ return KMessageBox::Ok;
+
+ case Sorry:
+ KMessageBox::sorryWId( parent_id, text, caption, options );
+ return KMessageBox::Ok;
+ }
+ return KMessageBox::Cancel;
+}
+
+void KMessageBox::queuedMessageBox( QWidget *parent, DialogType type, const QString &text, const QString &caption, int options )
+{
+ return queuedMessageBoxWId( parent ? parent->winId() : 0, type, text, caption, options );
+}
+
+void KMessageBox::queuedMessageBoxWId( WId parent_id, DialogType type, const QString &text, const QString &caption, int options )
+{
+ KMessageBox_queue = true;
+ (void) messageBoxWId(parent_id, type, text, caption, KStdGuiItem::yes(),
+ KStdGuiItem::no(), QString::null, options);
+ KMessageBox_queue = false;
+}
+
+void KMessageBox::queuedMessageBox( QWidget *parent, DialogType type, const QString &text, const QString &caption )
+{
+ return queuedMessageBoxWId( parent ? parent->winId() : 0, type, text, caption );
+}
+
+void KMessageBox::queuedMessageBoxWId( WId parent_id, DialogType type, const QString &text, const QString &caption )
+{
+ KMessageBox_queue = true;
+ (void) messageBoxWId(parent_id, type, text, caption);
+ KMessageBox_queue = false;
+}
diff --git a/kdeui/kmessagebox.h b/kdeui/kmessagebox.h
new file mode 100644
index 000000000..850fb7a5b
--- /dev/null
+++ b/kdeui/kmessagebox.h
@@ -0,0 +1,1166 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Waldo Bastian (bastian@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; version 2
+ of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef _KMESSAGEBOX_H_
+#define _KMESSAGEBOX_H_
+
+#include <qstring.h>
+#include <qmessagebox.h>
+
+#include <kguiitem.h>
+#include <kstdguiitem.h>
+
+class QWidget;
+class QStringList;
+class KConfig;
+class KDialogBase;
+
+ /**
+ * Easy message dialog box.
+ *
+ * Provides convenience functions for some i18n'ed standard dialogs.
+ *
+ * The text in message boxes is wrapped automatically. The text may either
+ * be plaintext or richtext. If the text is plaintext, a newline-character
+ * may be used to indicate the end of a paragraph.
+ *
+ * @author Waldo Bastian (bastian@kde.org)
+ */
+class KDEUI_EXPORT KMessageBox
+{
+public:
+ /**
+ * Button types.
+ **/
+ enum ButtonCode
+ {
+ Ok = 1,
+ Cancel = 2,
+ Yes = 3,
+ No = 4,
+ Continue = 5
+ };
+
+ enum DialogType
+ {
+ QuestionYesNo = 1,
+ WarningYesNo = 2,
+ WarningContinueCancel = 3,
+ WarningYesNoCancel = 4,
+ Information = 5,
+ // Reserved for: SSLMessageBox = 6
+ Sorry = 7,
+ Error = 8,
+ QuestionYesNoCancel = 9
+ };
+
+ enum OptionsType
+ {
+ Notify = 1, ///< Emit a KNotifyClient event
+ AllowLink = 2, ///< The message may contain links.
+ Dangerous = 4, ///< The action to be confirmed by the dialog is a potentially destructive one
+ PlainCaption = 8, /**< Do not use KApplication::makeStdCaption()
+ @since 3.4
+ */
+ NoExec = 16 /**< Do not call exec() in createKMessageBox()
+ @since 3.4
+ */
+ };
+
+ /**
+ * Display a simple "question" dialog.
+ *
+ * @param parent If @p parent is 0, then the message box becomes an
+ * application-global modal dialog box. If @p parent is a
+ * widget, the message box becomes modal relative to parent.
+ * @param text Message string.
+ * @param caption Message box title. The application name is added to
+ * the title. The default title is i18n("Question").
+ * @param buttonYes The text for the first button.
+ * The default is i18n("&Yes").
+ * @param buttonNo The text for the second button.
+ * The default is i18n("&No").
+ * @param dontAskAgainName If provided, a checkbox is added with which
+ * further confirmation can be turned off.
+ * The string is used to lookup and store the setting
+ * in the applications config file.
+ * The setting is stored in the "Notification Messages" group.
+ * If @p dontAskAgainName starts with a ':' then the setting
+ * is stored in the global config file.
+ * @param options see OptionsType
+ *
+ * @return 'Yes' is returned if the Yes-button is pressed. 'No' is returned
+ * if the No-button is pressed.
+ *
+ * To be used for questions like "Do you have a printer?"
+ *
+ * The default button is "Yes". Pressing "Esc" selects "No".
+ */
+
+ static int questionYesNo(QWidget *parent,
+ const QString &text,
+ const QString &caption = QString::null,
+ const KGuiItem &buttonYes = KStdGuiItem::yes(),
+ const KGuiItem &buttonNo = KStdGuiItem::no(),
+ const QString &dontAskAgainName = QString::null,
+ int options = Notify);
+ /**
+ * This function accepts the window id of the parent window, instead
+ * of QWidget*. It should be used only when necessary.
+ * @since 3.2
+ */
+ static int questionYesNoWId(WId parent_id,
+ const QString &text,
+ const QString &caption = QString::null,
+ const KGuiItem &buttonYes = KStdGuiItem::yes(),
+ const KGuiItem &buttonNo = KStdGuiItem::no(),
+ const QString &dontAskAgainName = QString::null,
+ int options = Notify);
+ /**
+ * Display a simple "question" dialog.
+ *
+ * @param parent If @p parent is 0, then the message box becomes an
+ * application-global modal dialog box. If @p parent is a
+ * widget, the message box becomes modal relative to parent.
+ * @param text Message string.
+ * @param caption Message box title. The application name is added to
+ * the title. The default title is i18n("Question").
+ * @param buttonYes The text for the first button.
+ * The default is i18n("&Yes").
+ * @param buttonNo The text for the second button.
+ * The default is i18n("&No").
+ * @param dontAskAgainName If provided, a checkbox is added with which
+ * further confirmation can be turned off.
+ * The string is used to lookup and store the setting
+ * in the applications config file.
+ * The setting is stored in the "Notification Messages" group.
+ * If @p dontAskAgainName starts with a ':' then the setting
+ * is stored in the global config file.
+ * @param options see OptionsType
+ *
+ * @return 'Yes' is returned if the Yes-button is pressed. 'No' is returned
+ * if the No-button is pressed.
+ *
+ * To be used for questions like "Do you want to discard the message or save it for later?",
+ *
+ * The default button is "Yes". Pressing "Esc" selects "Cancel".
+ *
+ * NOTE: The cancel button will always have the i18n'ed text '&Cancel'.
+ */
+
+ static int questionYesNoCancel(QWidget *parent,
+ const QString &text,
+ const QString &caption = QString::null,
+ const KGuiItem &buttonYes = KStdGuiItem::yes(),
+ const KGuiItem &buttonNo = KStdGuiItem::no(),
+ const QString &dontAskAgainName = QString::null,
+ int options = Notify);
+
+ /**
+ * This function accepts the window id of the parent window, instead
+ * of QWidget*. It should be used only when necessary.
+ * @since 3.2
+ */
+ static int questionYesNoCancelWId(WId parent_id,
+ const QString &text,
+ const QString &caption = QString::null,
+ const KGuiItem &buttonYes = KStdGuiItem::yes(),
+ const KGuiItem &buttonNo = KStdGuiItem::no(),
+ const QString &dontAskAgainName = QString::null,
+ int options = Notify);
+
+ /**
+ * Display a "question" dialog with a listbox to show information to the user
+ *
+ * @param parent If @p parent is 0, then the message box becomes an
+ * application-global modal dialog box. If @p parent is a
+ * widget, the message box becomes modal relative to parent.
+ * @param text Message string.
+ * @param strlist List of strings to be written in the listbox. If the list is
+ * empty, it doesn't show any listbox, working as questionYesNo.
+ * @param caption Message box title. The application name is added to
+ * the title. The default title is i18n("Question").
+ * @param buttonYes The text for the first button.
+ * The default is i18n("&Yes").
+ * @param buttonNo The text for the second button.
+ * The default is i18n("&No").
+ * @param dontAskAgainName If provided, a checkbox is added with which
+ * further confirmation can be turned off.
+ * The string is used to lookup and store the setting
+ * in the applications config file.
+ * The setting is stored in the "Notification Messages" group.
+ * If @p dontAskAgainName starts with a ':' then the setting
+ * is stored in the global config file.
+ * @param options see OptionsType
+ *
+ * @return 'Yes' is returned if the Yes-button is pressed. 'No' is returned
+ * if the No-button is pressed.
+ *
+ * To be used for questions like "Do you really want to delete these files?"
+ * And show the user exactly which files are going to be deleted in case
+ * he presses "Yes"
+ *
+ * The default button is "Yes". Pressing "Esc" selects "No".
+ */
+
+ static int questionYesNoList(QWidget *parent,
+ const QString &text,
+ const QStringList &strlist,
+ const QString &caption = QString::null,
+ const KGuiItem &buttonYes = KStdGuiItem::yes(),
+ const KGuiItem &buttonNo = KStdGuiItem::no(),
+ const QString &dontAskAgainName = QString::null,
+ int options = Notify);
+
+ /**
+ * This function accepts the window id of the parent window, instead
+ * of QWidget*. It should be used only when necessary.
+ * @since 3.2
+ */
+ static int questionYesNoListWId(WId parent_id,
+ const QString &text,
+ const QStringList &strlist,
+ const QString &caption = QString::null,
+ const KGuiItem &buttonYes = KStdGuiItem::yes(),
+ const KGuiItem &buttonNo = KStdGuiItem::no(),
+ const QString &dontAskAgainName = QString::null,
+ int options = Notify);
+
+ /**
+ * Display a "warning" dialog.
+ *
+ * @param parent If @p parent is 0, then the message box becomes an
+ * application-global modal dialog box. If @p parent is a
+ * widget, the message box becomes modal relative to parent.
+ * @param text Message string.
+ * @param caption Message box title. The application name is added to
+ * the title. The default title is i18n("Warning").
+ * @param buttonYes The text for the first button.
+ * The default is i18n("&Yes").
+ * @param buttonNo The text for the second button.
+ * The default is i18n("&No").
+ * @param dontAskAgainName If provided, a checkbox is added with which
+ * further confirmation can be turned off.
+ * The string is used to lookup and store the setting
+ * in the applications config file.
+ * The setting is stored in the "Notification Messages" group.
+ * If @p dontAskAgainName starts with a ':' then the setting
+ * is stored in the global config file.
+ * @param options see OptionsType
+ *
+ * @return @p Yes is returned if the Yes-button is pressed. @p No is returned
+ * if the No-button is pressed.
+ *
+ * To be used for questions "Shall I update your configuration?"
+ * The text should explain the implication of both options.
+ *
+ * The default button is "No". Pressing "Esc" selects "No".
+ */
+ static int warningYesNo(QWidget *parent,
+ const QString &text,
+ const QString &caption = QString::null,
+ const KGuiItem &buttonYes = KStdGuiItem::yes(),
+ const KGuiItem &buttonNo = KStdGuiItem::no(),
+ const QString &dontAskAgainName = QString::null,
+ int options = Notify | Dangerous);
+
+ /**
+ * This function accepts the window id of the parent window, instead
+ * of QWidget*. It should be used only when necessary.
+ * @since 3.2
+ */
+ static int warningYesNoWId(WId parent_id,
+ const QString &text,
+ const QString &caption = QString::null,
+ const KGuiItem &buttonYes = KStdGuiItem::yes(),
+ const KGuiItem &buttonNo = KStdGuiItem::no(),
+ const QString &dontAskAgainName = QString::null,
+ int options = Notify | Dangerous);
+
+ /**
+ * Display a "warning" dialog with a listbox to show information to the user
+ *
+ * @param parent If @p parent is 0, then the message box becomes an
+ * application-global modal dialog box. If @p parent is a
+ * widget, the message box becomes modal relative to parent.
+ * @param text Message string.
+ * @param strlist List of strings to be written in the listbox. If the list is
+ * empty, it doesn't show any listbox, working as questionYesNo.
+ * @param caption Message box title. The application name is added to
+ * the title. The default title is i18n("Question").
+ * @param buttonYes The text for the first button.
+ * The default is i18n("&Yes").
+ * @param buttonNo The text for the second button.
+ * The default is i18n("&No").
+ * @param dontAskAgainName If provided, a checkbox is added with which
+ * further confirmation can be turned off.
+ * The string is used to lookup and store the setting
+ * in the applications config file.
+ * The setting is stored in the "Notification Messages" group.
+ * If @p dontAskAgainName starts with a ':' then the setting
+ * is stored in the global config file.
+ * @param options see OptionsType
+ *
+ * @return 'Yes' is returned if the Yes-button is pressed. 'No' is returned
+ * if the No-button is pressed.
+ *
+ * To be used for questions like "Do you really want to delete these files?"
+ * And show the user exactly which files are going to be deleted in case
+ * he presses "Yes"
+ *
+ * The default button is "No". Pressing "Esc" selects "No".
+ */
+
+ static int warningYesNoList(QWidget *parent,
+ const QString &text,
+ const QStringList &strlist,
+ const QString &caption = QString::null,
+ const KGuiItem &buttonYes = KStdGuiItem::yes(),
+ const KGuiItem &buttonNo = KStdGuiItem::no(),
+ const QString &dontAskAgainName = QString::null,
+ int options = Notify | Dangerous);
+
+ /**
+ * This function accepts the window id of the parent window, instead
+ * of QWidget*. It should be used only when necessary.
+ * @since 3.2
+ */
+ static int warningYesNoListWId(WId parent_id,
+ const QString &text,
+ const QStringList &strlist,
+ const QString &caption = QString::null,
+ const KGuiItem &buttonYes = KStdGuiItem::yes(),
+ const KGuiItem &buttonNo = KStdGuiItem::no(),
+ const QString &dontAskAgainName = QString::null,
+ int options = Notify | Dangerous);
+
+ /**
+ * Display a "warning" dialog.
+ *
+ * @param parent If @p parent is 0, then the message box becomes an
+ * application-global modal dialog box. If @p parent is a
+ * widget, the message box becomes modal relative to parent.
+ * @param text Message string.
+ * @param caption Message box title. The application name is added to
+ * the title. The default title is i18n("Warning").
+ * @param buttonContinue The text for the first button.
+ * @param dontAskAgainName If provided, a checkbox is added with which
+ * further confirmation can be turned off.
+ * The string is used to lookup and store the setting
+ * in the applications config file.
+ * The setting is stored in the "Notification Messages" group.
+ * If @p dontAskAgainName starts with a ':' then the setting
+ * is stored in the global config file.
+ * @param options see OptionsType
+ *
+ * The second button always has the text "Cancel".
+ *
+ * @return @p Continue is returned if the Continue-button is pressed.
+ * @p Cancel is returned if the Cancel-button is pressed.
+ *
+ * To be used for questions like "You are about to Print. Are you sure?"
+ * the continueButton should then be labeled "Print".
+ *
+ * The default button is buttonContinue. Pressing "Esc" selects "Cancel".
+ */
+ static int warningContinueCancel(QWidget *parent,
+ const QString &text,
+ const QString &caption = QString::null,
+ const KGuiItem &buttonContinue = KStdGuiItem::cont(),
+ const QString &dontAskAgainName = QString::null,
+ int options = Notify);
+
+ /**
+ * This function accepts the window id of the parent window, instead
+ * of QWidget*. It should be used only when necessary.
+ * @since 3.2
+ */
+ static int warningContinueCancelWId(WId parent_id,
+ const QString &text,
+ const QString &caption = QString::null,
+ const KGuiItem &buttonContinue = KStdGuiItem::cont(),
+ const QString &dontAskAgainName = QString::null,
+ int options = Notify);
+
+ /**
+ * Display a "warning" dialog with a listbox to show information to the user.
+ *
+ * @param parent If @p parent is 0, then the message box becomes an
+ * application-global modal dialog box. If @p parent is a
+ * widget, the message box becomes modal relative to parent.
+ * @param text Message string.
+ * @param strlist List of strings to be written in the listbox. If the
+ * list is empty, it doesn't show any listbox, working
+ * as warningContinueCancel.
+ * @param caption Message box title. The application name is added to
+ * the title. The default title is i18n("Warning").
+ * @param buttonContinue The text for the first button.
+ * @param dontAskAgainName If provided, a checkbox is added with which
+ * further confirmation can be turned off.
+ * The string is used to lookup and store the setting
+ * in the applications config file.
+ * The setting is stored in the "Notification Messages" group.
+ * If @p dontAskAgainName starts with a ':' then the setting
+ * is stored in the global config file.
+ *
+ * @param options see OptionsType
+ *
+ * The second button always has the text "Cancel".
+ *
+ * @return @p Continue is returned if the Continue-button is pressed.
+ * @p Cancel is returned if the Cancel-button is pressed.
+ *
+ * To be used for questions like "You are about to Print. Are you sure?"
+ * the continueButton should then be labeled "Print".
+ *
+ * The default button is buttonContinue. Pressing "Esc" selects "Cancel".
+ */
+ static int warningContinueCancelList(QWidget *parent,
+ const QString &text,
+ const QStringList &strlist,
+ const QString &caption = QString::null,
+ const KGuiItem &buttonContinue = KStdGuiItem::cont(),
+ const QString &dontAskAgainName = QString::null,
+ int options = Notify);
+
+ /**
+ * This function accepts the window id of the parent window, instead
+ * of QWidget*. It should be used only when necessary.
+ * @since 3.2
+ */
+ static int warningContinueCancelListWId(WId parent_id,
+ const QString &text,
+ const QStringList &strlist,
+ const QString &caption = QString::null,
+ const KGuiItem &buttonContinue = KStdGuiItem::cont(),
+ const QString &dontAskAgainName = QString::null,
+ int options = Notify);
+
+ /**
+ * Display a Yes/No/Cancel "warning" dialog.
+ *
+ * @param parent If @p parent is 0, then the message box becomes an
+ * application-global modal dialog box. If @p parent is a
+ * widget, the message box becomes modal relative to parent.
+ * @param text Message string.
+ * @param caption Message box title. The application name is added to
+ * the title. The default title is i18n("Warning").
+ * @param buttonYes The text for the first button.
+ * The default is i18n("&Yes").
+ * @param buttonNo The text for the second button.
+ * The default is i18n("&No").
+ * @param dontAskAgainName If provided, a checkbox is added with which
+ * further questions can be turned off. If turned off
+ * all questions will be automatically answered with the
+ * last answer (either Yes or No).
+ * The string is used to lookup and store the setting
+ * in the applications config file.
+ * The setting is stored in the "Notification Messages" group.
+ * If @p dontAskAgainName starts with a ':' then the setting
+ * is stored in the global config file.
+ * @param options see OptionsType
+ *
+ * @return @p Yes is returned if the Yes-button is pressed. @p No is returned
+ * if the No-button is pressed. @p Cancel is retunred if the Cancel-
+ * button is pressed.
+ *
+ * To be used for questions "Do you want to save your changes?"
+ * The text should explain the implication of choosing 'No'.
+ *
+ * The default button is "Yes". Pressing "Esc" selects "Cancel"
+ *
+ * NOTE: The cancel button will always have the i18n'ed text '&Cancel'.
+ */
+
+ static int warningYesNoCancel(QWidget *parent,
+ const QString &text,
+ const QString &caption = QString::null,
+ const KGuiItem &buttonYes = KStdGuiItem::yes(),
+ const KGuiItem &buttonNo = KStdGuiItem::no(),
+ const QString &dontAskAgainName = QString::null,
+ int options = Notify);
+
+ /**
+ * This function accepts the window id of the parent window, instead
+ * of QWidget*. It should be used only when necessary.
+ * @since 3.2
+ */
+ static int warningYesNoCancelWId(WId parent_id,
+ const QString &text,
+ const QString &caption = QString::null,
+ const KGuiItem &buttonYes = KStdGuiItem::yes(),
+ const KGuiItem &buttonNo = KStdGuiItem::no(),
+ const QString &dontAskAgainName = QString::null,
+ int options = Notify);
+
+ /**
+ * Display a Yes/No/Cancel "warning" dialog with a listbox to show information
+ * to the user.
+ *
+ * @param parent If @p parent is 0, then the message box becomes an
+ * application-global modal dialog box. If @p parent is a
+ * widget, the message box becomes modal relative to parent.
+ * @param text Message string.
+ * @param strlist List of strings to be written in the listbox. If the
+ * list is empty, it doesn't show any listbox, working
+ * as warningYesNoCancel.
+ * @param caption Message box title. The application name is added to
+ * the title. The default title is i18n("Warning").
+ * @param buttonYes The text for the first button.
+ * The default is i18n("&Yes").
+ * @param buttonNo The text for the second button.
+ * The default is i18n("&No").
+ * @param dontAskAgainName If provided, a checkbox is added with which
+ * further questions can be turned off. If turned off
+ * all questions will be automatically answered with the
+ * last answer (either Yes or No).
+ * The string is used to lookup and store the setting
+ * in the applications config file.
+ * The setting is stored in the "Notification Messages" group.
+ * If @p dontAskAgainName starts with a ':' then the setting
+ * is stored in the global config file.
+ * @param options see OptionsType
+ *
+ * @return @p Yes is returned if the Yes-button is pressed. @p No is returned
+ * if the No-button is pressed. @p Cancel is retunred if the Cancel-
+ * button is pressed.
+ *
+ * To be used for questions "Do you want to save your changes?"
+ * The text should explain the implication of choosing 'No'.
+ *
+ * The default button is "Yes". Pressing "Esc" selects "Cancel"
+ *
+ * NOTE: The cancel button will always have the i18n'ed text '&Cancel'.
+ *
+ * @since 3.2
+ */
+ static int warningYesNoCancelList(QWidget *parent,
+ const QString &text,
+ const QStringList &strlist,
+ const QString &caption = QString::null,
+ const KGuiItem &buttonYes = KStdGuiItem::yes(),
+ const KGuiItem &buttonNo = KStdGuiItem::no(),
+ const QString &dontAskAgainName = QString::null,
+ int options = Notify);
+
+ /**
+ * This function accepts the window id of the parent window, instead
+ * of QWidget*. It should be used only when necessary.
+ * @since 3.2
+ */
+ static int warningYesNoCancelListWId(WId parent_id,
+ const QString &text,
+ const QStringList &strlist,
+ const QString &caption = QString::null,
+ const KGuiItem &buttonYes = KStdGuiItem::yes(),
+ const KGuiItem &buttonNo = KStdGuiItem::no(),
+ const QString &dontAskAgainName = QString::null,
+ int options = Notify);
+
+ /**
+ * Display an "Error" dialog.
+ *
+ * @param parent If @p parent is 0, then the message box becomes an
+ * application-global modal dialog box. If @p parent is a
+ * widget, the message box becomes modal relative to parent.
+ * @param text Message string.
+ * @param caption Message box title. The application name is added to
+ * the title. The default title is i18n("Error").
+ * @param options see OptionsType
+ *
+ * Your program messed up and now it's time to inform the user.
+ * To be used for important things like "Sorry, I deleted your hard disk."
+ *
+ * If your program detects the action specified by the user is somehow
+ * not allowed, this should never be reported with error(). Use sorry()
+ * instead to explain to the user that this action is not allowed.
+ *
+ * The default button is "&OK". Pressing "Esc" selects the OK-button.
+ *
+ * NOTE: The OK button will always have the i18n'ed text '&OK'.
+ */
+
+ static void error(QWidget *parent,
+ const QString &text,
+ const QString &caption = QString::null,
+ int options = Notify);
+
+ /**
+ * This function accepts the window id of the parent window, instead
+ * of QWidget*. It should be used only when necessary.
+ *
+ * @since 3.2
+ */
+ static void errorWId(WId parent_id,
+ const QString &text,
+ const QString &caption = QString::null,
+ int options = Notify);
+
+ /**
+ * Display an "Error" dialog with a listbox.
+ *
+ * @param parent If @p parent is 0, then the message box becomes an
+ * application-global modal dialog box. If @p parent is a
+ * widget, the message box becomes modal relative to parent.
+ * @param text Message string.
+ * @param strlist List of strings to be written in the listbox. If the
+ * list is empty, it doesn't show any listbox, working
+ * as error().
+ * @param caption Message box title. The application name is added to
+ * the title. The default title is i18n("Error").
+ * @param options see OptionsType
+ *
+ * Your program messed up and now it's time to inform the user.
+ * To be used for important things like "Sorry, I deleted your hard disk."
+ *
+ * If your program detects the action specified by the user is somehow
+ * not allowed, this should never be reported with error(). Use sorry()
+ * instead to explain to the user that this action is not allowed.
+ *
+ * The default button is "&OK". Pressing "Esc" selects the OK-button.
+ *
+ * NOTE: The OK button will always have the i18n'ed text '&OK'.
+ *
+ * @since 3.4
+ */
+
+ static void errorList(QWidget *parent,
+ const QString &text,
+ const QStringList &strlist,
+ const QString &caption = QString::null,
+ int options = Notify);
+
+ /**
+ * This function accepts the window id of the parent window, instead
+ * of QWidget*. It should be used only when necessary.
+ * @since 3.4
+ */
+
+ static void errorListWId(WId parent_id,
+ const QString &text,
+ const QStringList &strlist,
+ const QString &caption = QString::null,
+ int options = Notify);
+
+ /**
+ * Displays an "Error" dialog with a "Details >>" button.
+ *
+ * @param parent If @p parent is 0, then the message box becomes an
+ * application-global modal dialog box. If @p parent is a
+ * widget, the message box becomes modal relative to parent.
+ * @param text Message string.
+ * @param details Detailed message string.
+ * @param caption Message box title. The application name is added to
+ * the title. The default title is i18n("Error").
+ * @param options see OptionsType
+ *
+ * Your program messed up and now it's time to inform the user.
+ * To be used for important things like "Sorry, I deleted your hard disk."
+ *
+ * The @p details message can conatin additional information about
+ * the problem and can be shown on request to advanced/interested users.
+ *
+ * If your program detects the action specified by the user is somehow
+ * not allowed, this should never be reported with error(). Use sorry()
+ * instead to explain to the user that this action is not allowed.
+ *
+ * The default button is "&OK". Pressing "Esc" selects the OK-button.
+ *
+ * NOTE: The OK button will always have the i18n'ed text '&OK'.
+ */
+ static void detailedError(QWidget *parent,
+ const QString &text,
+ const QString &details,
+ const QString &caption = QString::null,
+ int options = Notify);
+
+ /**
+ * This function accepts the window id of the parent window, instead
+ * of QWidget*. It should be used only when necessary.
+ * @since 3.2
+ */
+ static void detailedErrorWId(WId parent_id,
+ const QString &text,
+ const QString &details,
+ const QString &caption = QString::null,
+ int options = Notify);
+
+ /**
+ * Like detailedError
+ *
+ * This function will return immediately, the messagebox will be shown
+ * once the application enters an event loop and no other messagebox
+ * is being shown.
+ *
+ * Note that if the parent gets deleted, the messagebox will not be
+ * shown.
+ */
+ static void queuedDetailedError( QWidget *parent,
+ const QString &text,
+ const QString &details,
+ const QString &caption = QString::null);
+
+ /**
+ * This function accepts the window id of the parent window, instead
+ * of QWidget*. It should be used only when necessary.
+ * @since 3.2
+ */
+ static void queuedDetailedErrorWId( WId parent_id,
+ const QString &text,
+ const QString &details,
+ const QString &caption = QString::null);
+
+ /**
+ * Display an "Sorry" dialog.
+ *
+ * @param parent If @p parent is 0, then the message box becomes an
+ * application-global modal dialog box. If @p parent is a
+ * widget, the message box becomes modal relative to parent.
+ * @param text Message string.
+ * @param caption Message box title. The application name is added to
+ * the title. The default title is i18n("Sorry").
+ * @param options see OptionsType
+ *
+ * Either your program messed up and asks for understanding
+ * or your user did something stupid.
+ *
+ * To be used for small problems like
+ * "Sorry, I can't find the file you specified."
+ *
+ * The default button is "&OK". Pressing "Esc" selects the OK-button.
+ *
+ * NOTE: The ok button will always have the i18n'ed text '&OK'.
+ */
+
+ static void sorry(QWidget *parent,
+ const QString &text,
+ const QString &caption = QString::null,
+ int options = Notify);
+
+ /**
+ * This function accepts the window id of the parent window, instead
+ * of QWidget*. It should be used only when necessary.
+ * @since 3.2
+ */
+ static void sorryWId(WId parent_id,
+ const QString &text,
+ const QString &caption = QString::null,
+ int options = Notify);
+
+ /**
+ * Displays a "Sorry" dialog with a "Details >>" button.
+ *
+ * @param parent If @p parent is 0, then the message box becomes an
+ * application-global modal dialog box. If @p parent is a
+ * widget, the message box becomes modal relative to parent.
+ * @param text Message string.
+ * @param details Detailed message string.
+ * @param caption Message box title. The application name is added to
+ * the title. The default title is i18n("Sorry").
+ * @param options see OptionsType
+ *
+ * Either your program messed up and asks for understanding
+ * or your user did something stupid.
+ *
+ * To be used for small problems like
+ * "Sorry, I can't find the file you specified."
+ *
+ * And then @p details can contain something like
+ * "foobar.txt was not found in any of
+ * the following directories:
+ * /usr/bin,/usr/local/bin,/usr/sbin"
+ *
+ * The default button is "&OK". Pressing "Esc" selects the OK-button.
+ *
+ * NOTE: The ok button will always have the i18n'ed text '&OK'.
+ */
+
+ static void detailedSorry(QWidget *parent,
+ const QString &text,
+ const QString &details,
+ const QString &caption = QString::null,
+ int options = Notify);
+
+ /**
+ * This function accepts the window id of the parent window, instead
+ * of QWidget*. It should be used only when necessary.
+ * @since 3.2
+ */
+ static void detailedSorryWId(WId parent_id,
+ const QString &text,
+ const QString &details,
+ const QString &caption = QString::null,
+ int options = Notify);
+
+ /**
+ * Display an "Information" dialog.
+ *
+ * @param parent If @p parent is 0, then the message box becomes an
+ * application-global modal dialog box. If @p parent is a
+ * widget, the message box becomes modal relative to parent.
+ * @param text Message string.
+ * @param caption Message box title. The application name is added to
+ * the title. The default title is i18n("Information").
+ * @param dontShowAgainName If provided, a checkbox is added with which
+ * further notifications can be turned off.
+ * The string is used to lookup and store the setting
+ * in the applications config file.
+ * The setting is stored in the "Notification Messages" group.
+ * @param options see OptionsType
+ *
+ *
+ * Your program wants to tell the user something.
+ * To be used for things like:
+ * "Your bookmarks have been rearranged."
+ *
+ * The default button is "&OK". Pressing "Esc" selects the OK-button.
+ *
+ * NOTE: The OK button will always have the i18n'ed text '&OK'.
+ */
+
+ static void information(QWidget *parent,
+ const QString &text,
+ const QString &caption = QString::null,
+ const QString &dontShowAgainName = QString::null,
+ int options = Notify);
+
+ /**
+ * This function accepts the window id of the parent window, instead
+ * of QWidget*. It should be used only when necessary.
+ * @since 3.2
+ */
+ static void informationWId(WId parent_id,
+ const QString &text,
+ const QString &caption = QString::null,
+ const QString &dontShowAgainName = QString::null,
+ int options = Notify);
+
+ /**
+ * Display an "Information" dialog with a listbox.
+ *
+ * @param parent If @p parent is 0, then the message box becomes an
+ * application-global modal dialog box. If @p parent is a
+ * widget, the message box becomes modal relative to parent.
+ * @param text Message string.
+ * @param strlist List of strings to be written in the listbox. If the
+ * list is empty, it doesn't show any listbox, working
+ * as information.
+ * @param caption Message box title. The application name is added to
+ * the title. The default title is i18n("Information").
+ * @param dontShowAgainName If provided, a checkbox is added with which
+ * further notifications can be turned off.
+ * The string is used to lookup and store the setting
+ * in the applications config file.
+ * The setting is stored in the "Notification Messages" group.
+ * @param options see OptionsType
+ *
+ *
+ * Your program wants to tell the user something.
+ * To be used for things like:
+ * "The following bookmarks have been rearranged:"
+ *
+ * The default button is "&OK". Pressing "Esc" selects the OK-button.
+ *
+ * NOTE: The OK button will always have the i18n'ed text '&OK'.
+ * @since 3.1
+ */
+
+ static void informationList(QWidget *parent,
+ const QString &text,
+ const QStringList & strlist,
+ const QString &caption = QString::null,
+ const QString &dontShowAgainName = QString::null,
+ int options = Notify);
+
+ /**
+ * This function accepts the window id of the parent window, instead
+ * of QWidget*. It should be used only when necessary.
+ * @since 3.2
+ */
+ static void informationListWId(WId parent_id,
+ const QString &text,
+ const QStringList & strlist,
+ const QString &caption = QString::null,
+ const QString &dontShowAgainName = QString::null,
+ int options = Notify);
+
+ /**
+ * Enable all messages which have been turned off with the
+ * @p dontShowAgainName feature.
+ */
+ static void enableAllMessages();
+
+ /**
+ * Re-enable a specific @p dontShowAgainName messages that had
+ * previously been turned off.
+ * @see saveDontShowAgainYesNo()
+ * @see saveDontShowAgainContinue()
+ * @since 3.2
+ */
+ static void enableMessage(const QString &dontShowAgainName);
+
+ /**
+ * Display an "About" dialog.
+ *
+ * @param parent If @p parent is 0, then the message box becomes an
+ * application-global modal dialog box. If @p parent is a
+ * widget, the message box becomes modal relative to parent.
+ * @param text Message string.
+ * @param caption Message box title. The application name is added to
+ * the title. The default title is i18n("About \<appname\>").
+ * @param options see OptionsType
+ *
+ *
+ * Your program wants to show some general information about the application
+ * like the authors's names and email addresses.
+ *
+ * The default button is "&OK".
+ *
+ * NOTE: The ok button will always have the i18n'ed text '&OK'.
+ */
+ static void about(QWidget *parent,
+ const QString& text,
+ const QString& caption = QString::null,
+ int options = Notify);
+
+ /**
+ * Alternate method to show a messagebox:
+ *
+ * @param parent If @p parent is 0, then the message box becomes an
+ * application-global modal dialog box. If @p parent is a
+ * widget, the message box becomes modal relative to parent.
+ * @param type type of message box: QuestionYesNo, WarningYesNo, WarningContinueCancel...
+ * @param text Message string.
+ * @param caption Message box title.
+ * @param buttonYes The text for the first button.
+ * The default is i18n("&Yes").
+ * @param buttonNo The text for the second button.
+ * The default is i18n("&No").
+ * @param dontShowAskAgainName If provided, a checkbox is added with which
+ * further questions/informations can be turned off. If turned off
+ * all questions will be automatically answered with the
+ * last answer (either Yes or No), if the message box needs an answer.
+ * The string is used to lookup and store the setting
+ * in the applications config file.
+ * @param options see OptionsType
+ * Note: for ContinueCancel, buttonYes is the continue button and buttonNo is unused.
+ * and for Information, none is used.
+ * @return a button code, as defined in KMessageBox.
+ */
+ static int messageBox( QWidget *parent, DialogType type, const QString &text,
+ const QString &caption,
+ const KGuiItem &buttonYes,
+ const KGuiItem &buttonNo,
+ const QString &dontShowAskAgainName,
+ int options = Notify);
+
+ /**
+ * Alternate method to show a messagebox:
+ *
+ * @param parent If @p parent is 0, then the message box becomes an
+ * application-global modal dialog box. If @p parent is a
+ * widget, the message box becomes modal relative to parent.
+ * @param type type of message box: QuestionYesNo, WarningYesNo, WarningContinueCancel...
+ * @param text Message string.
+ * @param caption Message box title.
+ * @param buttonYes The text for the first button.
+ * The default is i18n("&Yes").
+ * @param buttonNo The text for the second button.
+ * The default is i18n("&No").
+ * @param options see OptionsType
+ * Note: for ContinueCancel, buttonYes is the continue button and buttonNo is unused.
+ * and for Information, none is used.
+ * @return a button code, as defined in KMessageBox.
+ */
+ // KDE4 - merge with above?
+ static int messageBox( QWidget *parent, DialogType type, const QString &text,
+ const QString &caption = QString::null,
+ const KGuiItem &buttonYes = KStdGuiItem::yes(),
+ const KGuiItem &buttonNo = KStdGuiItem::no(),
+ int options = Notify);
+
+ /**
+ * This function accepts the window id of the parent window, instead
+ * of QWidget*. It should be used only when necessary.
+ * @since 3.2
+ */
+ static int messageBoxWId( WId parent_id, DialogType type, const QString &text,
+ const QString &caption = QString::null,
+ const KGuiItem &buttonYes = KStdGuiItem::yes(),
+ const KGuiItem &buttonNo = KStdGuiItem::no(),
+ const QString &dontShowAskAgainName = QString::null,
+ int options = Notify);
+
+ /**
+ * Like messageBox
+ *
+ * Only for message boxes of type Information, Sorry or Error.
+ *
+ * This function will return immediately, the messagebox will be shown
+ * once the application enters an event loop and no other messagebox
+ * is being shown.
+ *
+ * Note that if the parent gets deleted, the messagebox will not be
+ * shown.
+ */
+ static void queuedMessageBox( QWidget *parent,
+ DialogType type, const QString &text,
+ const QString &caption,
+ int options );
+
+ /**
+ * This function accepts the window id of the parent window, instead
+ * of QWidget*. It should be used only when necessary.
+ * @since 3.2
+ */
+ static void queuedMessageBoxWId( WId parent_id,
+ DialogType type, const QString &text,
+ const QString &caption,
+ int options );
+
+ /**
+ * @overload
+ *
+ * This is an overloaded member function, provided for convenience.
+ * It behaves essentially like the above function.
+ */
+ static void queuedMessageBox( QWidget *parent,
+ DialogType type, const QString &text,
+ const QString &caption = QString::null );
+
+ /**
+ * This function accepts the window id of the parent window, instead
+ * of QWidget*. It should be used only when necessary.
+ * @since 3.2
+ */
+ static void queuedMessageBoxWId( WId parent_id,
+ DialogType type, const QString &text,
+ const QString &caption = QString::null );
+
+ /**
+ * @return true if the corresponding yes/no message box should be shown.
+ * @param dontShowAgainName the name that identify the message box. If
+ * empty, true is always returned.
+ * @param result is set to the result (Yes or No) that was chosen the last
+ * time the message box was shown. Only meaningful, if the message box
+ * should not be shown.
+ * @since 3.2
+ */
+ static bool shouldBeShownYesNo(const QString &dontShowAgainName,
+ ButtonCode &result);
+ /**
+ * @return true if the corresponding continue/cancel message box should be
+ * shown.
+ * @param dontShowAgainName the name that identify the message box. If
+ * empty, true is always returned.
+ * @since 3.2
+ */
+ static bool shouldBeShownContinue(const QString &dontShowAgainName);
+
+ /**
+ * Save the fact that the yes/no message box should not be shown again.
+ * @param dontShowAgainName the name that identify the message box. If
+ * empty, this method does nothing.
+ * @param result the value (Yes or No) that should be used as the result
+ * for the message box.
+ * @since 3.2
+ */
+ static void saveDontShowAgainYesNo(const QString &dontShowAgainName,
+ ButtonCode result);
+
+ /**
+ * Save the fact that the continue/cancel message box should not be shown
+ * again.
+ * @param dontShowAgainName the name that identify the message box. If
+ * empty, this method does nothing.
+ * @since 3.2
+ */
+ static void saveDontShowAgainContinue(const QString &dontShowAgainName);
+
+ /**
+ * Use @p cfg for all settings related to the dontShowAgainName feature.
+ * If @p cfg is 0 (default) KGlobal::config() will be used.
+ * @since 3.2
+ */
+ static void setDontShowAskAgainConfig(KConfig* cfg);
+
+ /**
+ * Create content and layout of a standard dialog
+ *
+ * @param dialog The parent dialog base
+ * @param icon Which predefined icon the message box shall show.
+ * @param text Message string.
+ * @param strlist List of strings to be written in the listbox.
+ * If the list is empty, it doesn't show any listbox
+ * @param ask The text of the checkbox. If empty none will be shown.
+ * @param checkboxReturn The result of the checkbox. If it's initially
+ * true then the checkbox will be checked by default.
+ * @param options see OptionsType
+ * @param details Detailed message string.
+ * @since 3.3
+ * @return A KDialogBase button code, not a KMessageBox button code,
+ * based on the buttonmask given to the constructor of the
+ * @p dialog (ie. will return KDialogBase::Yes [256] instead of
+ * KMessageBox::Yes [3]). Will return KMessageBox::Cancel
+ * if the message box is queued for display instead of
+ * exec()ed immediately or if the option NoExec is set.
+ * @note The @p dialog that is passed in is deleted by this
+ * function. Do not delete it yourself.
+ */
+ static int createKMessageBox(KDialogBase *dialog, QMessageBox::Icon icon,
+ const QString &text, const QStringList &strlist,
+ const QString &ask, bool *checkboxReturn,
+ int options, const QString &details=QString::null);
+
+ /**
+ * Create content and layout of a standard dialog
+ *
+ * @param dialog The parent dialog base
+ * @param icon A QPixmap containing the icon to be displayed in the
+ * dialog next to the text.
+ * @param text Message string.
+ * @param strlist List of strings to be written in the listbox.
+ * If the list is empty, it doesn't show any listbox
+ * @param ask The text of the checkbox. If empty none will be shown.
+ * @param checkboxReturn The result of the checkbox. If it's initially
+ * true then the checkbox will be checked by default.
+ * @param options see OptionsType
+ * @param details Detailed message string.
+ * @param notifyType The type of notification to send when this message
+ * is presentend.
+ * @since 3.3
+ * @return A KDialogBase button code, not a KMessageBox button code,
+ * based on the buttonmask given to the constructor of the
+ * @p dialog (ie. will return KDialogBase::Yes [256] instead of
+ * KMessageBox::Yes [3]). Will return KMessageBox::Cancel
+ * if the message box is queued for display instead of
+ * exec()ed immediately or if the option NoExec is set.
+ * @note The @p dialog that is passed in is deleted by this
+ * function. Do not delete it yourself.
+ */
+ static int createKMessageBox(KDialogBase *dialog, QPixmap icon,
+ const QString &text, const QStringList &strlist,
+ const QString &ask, bool *checkboxReturn,
+ int options, const QString &details=QString::null,
+ QMessageBox::Icon notifyType=QMessageBox::Information);
+
+private:
+ static KConfig* againConfig;
+};
+
+#endif
diff --git a/kdeui/knuminput.cpp b/kdeui/knuminput.cpp
new file mode 100644
index 000000000..68587dcb4
--- /dev/null
+++ b/kdeui/knuminput.cpp
@@ -0,0 +1,1180 @@
+// -*- c-basic-offset: 4 -*-
+/*
+ * knuminput.cpp
+ *
+ * Initial implementation:
+ * Copyright (c) 1997 Patrick Dowler <dowler@morgul.fsh.uvic.ca>
+ * Rewritten and maintained by:
+ * Copyright (c) 2000 Dirk A. Mueller <mueller@kde.org>
+ * KDoubleSpinBox:
+ * Copyright (c) 2002 Marc Mutz <mutz@kde.org>
+ *
+ * Requires the Qt widget libraries, available at no cost at
+ * http://www.troll.no/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <config.h>
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#include <assert.h>
+#include <math.h>
+#include <algorithm>
+
+#include <qapplication.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qsize.h>
+#include <qslider.h>
+#include <qspinbox.h>
+#include <qstyle.h>
+
+#include <kglobal.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+#include "kdialog.h"
+#include "knumvalidator.h"
+#include "knuminput.h"
+
+static inline int calcDiffByTen( int x, int y ) {
+ // calculate ( x - y ) / 10 without overflowing ints:
+ return ( x / 10 ) - ( y / 10 ) + ( x % 10 - y % 10 ) / 10;
+}
+
+// ----------------------------------------------------------------------------
+
+KNumInput::KNumInput(QWidget* parent, const char* name)
+ : QWidget(parent, name)
+{
+ init();
+}
+
+KNumInput::KNumInput(KNumInput* below, QWidget* parent, const char* name)
+ : QWidget(parent, name)
+{
+ init();
+
+ if(below) {
+ m_next = below->m_next;
+ m_prev = below;
+ below->m_next = this;
+ if(m_next)
+ m_next->m_prev = this;
+ }
+}
+
+void KNumInput::init()
+{
+ m_prev = m_next = 0;
+ m_colw1 = m_colw2 = 0;
+
+ m_label = 0;
+ m_slider = 0;
+ m_alignment = 0;
+}
+
+KNumInput::~KNumInput()
+{
+ if(m_prev)
+ m_prev->m_next = m_next;
+
+ if(m_next)
+ m_next->m_prev = m_prev;
+}
+
+void KNumInput::setLabel(const QString & label, int a)
+{
+ if(label.isEmpty()) {
+ delete m_label;
+ m_label = 0;
+ m_alignment = 0;
+ }
+ else {
+ if (m_label) m_label->setText(label);
+ else m_label = new QLabel(label, this, "KNumInput::QLabel");
+ m_label->setAlignment((a & (~(AlignTop|AlignBottom|AlignVCenter)))
+ | AlignVCenter);
+ // if no vertical alignment set, use Top alignment
+ if(!(a & (AlignTop|AlignBottom|AlignVCenter)))
+ a |= AlignTop;
+ m_alignment = a;
+ }
+
+ layout(true);
+}
+
+QString KNumInput::label() const
+{
+ if (m_label) return m_label->text();
+ return QString::null;
+}
+
+void KNumInput::layout(bool deep)
+{
+ int w1 = m_colw1;
+ int w2 = m_colw2;
+
+ // label sizeHint
+ m_sizeLabel = (m_label ? m_label->sizeHint() : QSize(0,0));
+
+ if(m_label && (m_alignment & AlignVCenter))
+ m_colw1 = m_sizeLabel.width() + 4;
+ else
+ m_colw1 = 0;
+
+ // slider sizeHint
+ m_sizeSlider = (m_slider ? m_slider->sizeHint() : QSize(0, 0));
+
+ doLayout();
+
+ if(!deep) {
+ m_colw1 = w1;
+ m_colw2 = w2;
+ return;
+ }
+
+ KNumInput* p = this;
+ while(p) {
+ p->doLayout();
+ w1 = QMAX(w1, p->m_colw1);
+ w2 = QMAX(w2, p->m_colw2);
+ p = p->m_prev;
+ }
+
+ p = m_next;
+ while(p) {
+ p->doLayout();
+ w1 = QMAX(w1, p->m_colw1);
+ w2 = QMAX(w2, p->m_colw2);
+ p = p->m_next;
+ }
+
+ p = this;
+ while(p) {
+ p->m_colw1 = w1;
+ p->m_colw2 = w2;
+ p = p->m_prev;
+ }
+
+ p = m_next;
+ while(p) {
+ p->m_colw1 = w1;
+ p->m_colw2 = w2;
+ p = p->m_next;
+ }
+
+// kdDebug() << "w1 " << w1 << " w2 " << w2 << endl;
+}
+
+QSizePolicy KNumInput::sizePolicy() const
+{
+ return QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
+}
+
+QSize KNumInput::sizeHint() const
+{
+ return minimumSizeHint();
+}
+
+void KNumInput::setSteps(int minor, int major)
+{
+ if(m_slider)
+ m_slider->setSteps( minor, major );
+}
+
+
+// ----------------------------------------------------------------------------
+
+KIntSpinBox::KIntSpinBox(QWidget *parent, const char *name)
+ : QSpinBox(0, 99, 1, parent, name)
+{
+ editor()->setAlignment(AlignRight);
+ val_base = 10;
+ setValue(0);
+}
+
+KIntSpinBox::~KIntSpinBox()
+{
+}
+
+KIntSpinBox::KIntSpinBox(int lower, int upper, int step, int value, int base,
+ QWidget* parent, const char* name)
+ : QSpinBox(lower, upper, step, parent, name)
+{
+ editor()->setAlignment(AlignRight);
+ val_base = base;
+ setValue(value);
+}
+
+void KIntSpinBox::setBase(int base)
+{
+ val_base = base;
+}
+
+
+int KIntSpinBox::base() const
+{
+ return val_base;
+}
+
+QString KIntSpinBox::mapValueToText(int v)
+{
+ return QString::number(v, val_base);
+}
+
+int KIntSpinBox::mapTextToValue(bool* ok)
+{
+ return cleanText().toInt(ok, val_base);
+}
+
+void KIntSpinBox::setEditFocus(bool mark)
+{
+ editor()->setFocus();
+ if(mark)
+ editor()->selectAll();
+}
+
+
+// ----------------------------------------------------------------------------
+
+class KIntNumInput::KIntNumInputPrivate {
+public:
+ int referencePoint;
+ short blockRelative;
+ KIntNumInputPrivate( int r )
+ : referencePoint( r ),
+ blockRelative( 0 ) {}
+};
+
+
+KIntNumInput::KIntNumInput(KNumInput* below, int val, QWidget* parent,
+ int _base, const char* name)
+ : KNumInput(below, parent, name)
+{
+ init(val, _base);
+}
+
+KIntNumInput::KIntNumInput(QWidget *parent, const char *name)
+ : KNumInput(parent, name)
+{
+ init(0, 10);
+}
+
+KIntNumInput::KIntNumInput(int val, QWidget *parent, int _base, const char *name)
+ : KNumInput(parent, name)
+{
+ init(val, _base);
+
+}
+
+void KIntNumInput::init(int val, int _base)
+{
+ d = new KIntNumInputPrivate( val );
+ m_spin = new KIntSpinBox(INT_MIN, INT_MAX, 1, val, _base, this, "KIntNumInput::KIntSpinBox");
+ // the KIntValidator is broken beyond believe for
+ // spinboxes which have suffix or prefix texts, so
+ // better don't use it unless absolutely necessary
+ if (_base != 10)
+ m_spin->setValidator(new KIntValidator(this, _base, "KNumInput::KIntValidtr"));
+
+ connect(m_spin, SIGNAL(valueChanged(int)), SLOT(spinValueChanged(int)));
+ connect(this, SIGNAL(valueChanged(int)),
+ SLOT(slotEmitRelativeValueChanged(int)));
+
+ setFocusProxy(m_spin);
+ layout(true);
+}
+
+void KIntNumInput::setReferencePoint( int ref ) {
+ // clip to valid range:
+ ref = kMin( maxValue(), kMax( minValue(), ref ) );
+ d->referencePoint = ref;
+}
+
+int KIntNumInput::referencePoint() const {
+ return d->referencePoint;
+}
+
+void KIntNumInput::spinValueChanged(int val)
+{
+ if(m_slider)
+ m_slider->setValue(val);
+
+ emit valueChanged(val);
+}
+
+void KIntNumInput::slotEmitRelativeValueChanged( int value ) {
+ if ( d->blockRelative || !d->referencePoint ) return;
+ emit relativeValueChanged( double( value ) / double( d->referencePoint ) );
+}
+
+void KIntNumInput::setRange(int lower, int upper, int step, bool slider)
+{
+ upper = kMax(upper, lower);
+ lower = kMin(upper, lower);
+ m_spin->setMinValue(lower);
+ m_spin->setMaxValue(upper);
+ m_spin->setLineStep(step);
+
+ step = m_spin->lineStep(); // maybe QRangeControl didn't like out lineStep?
+
+ if(slider) {
+ if (m_slider)
+ m_slider->setRange(lower, upper);
+ else {
+ m_slider = new QSlider(lower, upper, step, m_spin->value(),
+ QSlider::Horizontal, this);
+ m_slider->setTickmarks(QSlider::Below);
+ connect(m_slider, SIGNAL(valueChanged(int)),
+ m_spin, SLOT(setValue(int)));
+ }
+
+ // calculate (upper-lower)/10 without overflowing int's:
+ int major = calcDiffByTen( upper, lower );
+ if ( major==0 ) major = step; // #### workaround Qt bug in 2.1-beta4
+
+ m_slider->setSteps(step, major);
+ m_slider->setTickInterval(major);
+ }
+ else {
+ delete m_slider;
+ m_slider = 0;
+ }
+
+ // check that reference point is still inside valid range:
+ setReferencePoint( referencePoint() );
+
+ layout(true);
+}
+
+void KIntNumInput::setMinValue(int min)
+{
+ setRange(min, m_spin->maxValue(), m_spin->lineStep(), m_slider);
+}
+
+int KIntNumInput::minValue() const
+{
+ return m_spin->minValue();
+}
+
+void KIntNumInput::setMaxValue(int max)
+{
+ setRange(m_spin->minValue(), max, m_spin->lineStep(), m_slider);
+}
+
+int KIntNumInput::maxValue() const
+{
+ return m_spin->maxValue();
+}
+
+void KIntNumInput::setSuffix(const QString &suffix)
+{
+ m_spin->setSuffix(suffix);
+
+ layout(true);
+}
+
+QString KIntNumInput::suffix() const
+{
+ return m_spin->suffix();
+}
+
+void KIntNumInput::setPrefix(const QString &prefix)
+{
+ m_spin->setPrefix(prefix);
+
+ layout(true);
+}
+
+QString KIntNumInput::prefix() const
+{
+ return m_spin->prefix();
+}
+
+void KIntNumInput::setEditFocus(bool mark)
+{
+ m_spin->setEditFocus(mark);
+}
+
+QSize KIntNumInput::minimumSizeHint() const
+{
+ constPolish();
+
+ int w;
+ int h;
+
+ h = 2 + QMAX(m_sizeSpin.height(), m_sizeSlider.height());
+
+ // if in extra row, then count it here
+ if(m_label && (m_alignment & (AlignBottom|AlignTop)))
+ h += 4 + m_sizeLabel.height();
+ else
+ // label is in the same row as the other widgets
+ h = QMAX(h, m_sizeLabel.height() + 2);
+
+ w = m_slider ? m_slider->sizeHint().width() + 8 : 0;
+ w += m_colw1 + m_colw2;
+
+ if(m_alignment & (AlignTop|AlignBottom))
+ w = QMAX(w, m_sizeLabel.width() + 4);
+
+ return QSize(w, h);
+}
+
+void KIntNumInput::doLayout()
+{
+ m_sizeSpin = m_spin->sizeHint();
+ m_colw2 = m_sizeSpin.width();
+
+ if (m_label)
+ m_label->setBuddy(m_spin);
+}
+
+void KIntNumInput::resizeEvent(QResizeEvent* e)
+{
+ int w = m_colw1;
+ int h = 0;
+
+ if(m_label && (m_alignment & AlignTop)) {
+ m_label->setGeometry(0, 0, e->size().width(), m_sizeLabel.height());
+ h += m_sizeLabel.height() + KDialog::spacingHint();
+ }
+
+ if(m_label && (m_alignment & AlignVCenter))
+ m_label->setGeometry(0, 0, w, m_sizeSpin.height());
+
+ if (qApp->reverseLayout())
+ {
+ m_spin->setGeometry(w, h, m_slider ? m_colw2 : QMAX(m_colw2, e->size().width() - w), m_sizeSpin.height());
+ w += m_colw2 + 8;
+
+ if(m_slider)
+ m_slider->setGeometry(w, h, e->size().width() - w, m_sizeSpin.height());
+ }
+ else if(m_slider) {
+ m_slider->setGeometry(w, h, e->size().width() - (w + m_colw2 + KDialog::spacingHint()), m_sizeSpin.height());
+ m_spin->setGeometry(w + m_slider->size().width() + KDialog::spacingHint(), h, m_colw2, m_sizeSpin.height());
+ }
+ else {
+ m_spin->setGeometry(w, h, QMAX(m_colw2, e->size().width() - w), m_sizeSpin.height());
+ }
+
+ h += m_sizeSpin.height() + 2;
+
+ if(m_label && (m_alignment & AlignBottom))
+ m_label->setGeometry(0, h, m_sizeLabel.width(), m_sizeLabel.height());
+}
+
+KIntNumInput::~KIntNumInput()
+{
+ delete d;
+}
+
+void KIntNumInput::setValue(int val)
+{
+ m_spin->setValue(val);
+ // slider value is changed by spinValueChanged
+}
+
+void KIntNumInput::setRelativeValue( double r ) {
+ if ( !d->referencePoint ) return;
+ ++d->blockRelative;
+ setValue( int( d->referencePoint * r + 0.5 ) );
+ --d->blockRelative;
+}
+
+double KIntNumInput::relativeValue() const {
+ if ( !d->referencePoint ) return 0;
+ return double( value() ) / double ( d->referencePoint );
+}
+
+int KIntNumInput::value() const
+{
+ return m_spin->value();
+}
+
+void KIntNumInput::setSpecialValueText(const QString& text)
+{
+ m_spin->setSpecialValueText(text);
+ layout(true);
+}
+
+QString KIntNumInput::specialValueText() const
+{
+ return m_spin->specialValueText();
+}
+
+void KIntNumInput::setLabel(const QString & label, int a)
+{
+ KNumInput::setLabel(label, a);
+
+ if(m_label)
+ m_label->setBuddy(m_spin);
+}
+
+// ----------------------------------------------------------------------------
+
+class KDoubleNumInput::KDoubleNumInputPrivate {
+public:
+ KDoubleNumInputPrivate( double r )
+ : spin( 0 ),
+ referencePoint( r ),
+ blockRelative ( 0 ) {}
+ KDoubleSpinBox * spin;
+ double referencePoint;
+ short blockRelative;
+};
+
+KDoubleNumInput::KDoubleNumInput(QWidget *parent, const char *name)
+ : KNumInput(parent, name)
+{
+ init(0.0, 0.0, 9999.0, 0.01, 2);
+}
+
+KDoubleNumInput::KDoubleNumInput(double lower, double upper, double value,
+ double step, int precision, QWidget* parent,
+ const char *name)
+ : KNumInput(parent, name)
+{
+ init(value, lower, upper, step, precision);
+}
+
+KDoubleNumInput::KDoubleNumInput(KNumInput *below,
+ double lower, double upper, double value,
+ double step, int precision, QWidget* parent,
+ const char *name)
+ : KNumInput(below, parent, name)
+{
+ init(value, lower, upper, step, precision);
+}
+
+KDoubleNumInput::KDoubleNumInput(double value, QWidget *parent, const char *name)
+ : KNumInput(parent, name)
+{
+ init(value, kMin(0.0, value), kMax(0.0, value), 0.01, 2 );
+}
+
+KDoubleNumInput::KDoubleNumInput(KNumInput* below, double value, QWidget* parent,
+ const char* name)
+ : KNumInput(below, parent, name)
+{
+ init( value, kMin(0.0, value), kMax(0.0, value), 0.01, 2 );
+}
+
+KDoubleNumInput::~KDoubleNumInput()
+{
+ delete d;
+}
+
+// ### remove when BIC changes are allowed again:
+
+bool KDoubleNumInput::eventFilter( QObject * o, QEvent * e ) {
+ return KNumInput::eventFilter( o, e );
+}
+
+void KDoubleNumInput::resetEditBox() {
+
+}
+
+// ### end stuff to remove when BIC changes are allowed again
+
+
+
+void KDoubleNumInput::init(double value, double lower, double upper,
+ double step, int precision )
+{
+ // ### init no longer used members:
+ edit = 0;
+ m_range = true;
+ m_value = 0.0;
+ m_precision = 2;
+ // ### end
+
+ d = new KDoubleNumInputPrivate( value );
+
+ d->spin = new KDoubleSpinBox( lower, upper, step, value, precision,
+ this, "KDoubleNumInput::d->spin" );
+ setFocusProxy(d->spin);
+ connect( d->spin, SIGNAL(valueChanged(double)),
+ this, SIGNAL(valueChanged(double)) );
+ connect( this, SIGNAL(valueChanged(double)),
+ this, SLOT(slotEmitRelativeValueChanged(double)) );
+
+ updateLegacyMembers();
+
+ layout(true);
+}
+
+void KDoubleNumInput::updateLegacyMembers() {
+ // ### update legacy members that are either not private or for
+ // which an inlined getter exists:
+ m_lower = minValue();
+ m_upper = maxValue();
+ m_step = d->spin->lineStep();
+ m_specialvalue = specialValueText();
+}
+
+
+double KDoubleNumInput::mapSliderToSpin( int val ) const
+{
+ // map [slidemin,slidemax] to [spinmin,spinmax]
+ double spinmin = d->spin->minValue();
+ double spinmax = d->spin->maxValue();
+ double slidemin = m_slider->minValue(); // cast int to double to avoid
+ double slidemax = m_slider->maxValue(); // overflow in rel denominator
+ double rel = ( double(val) - slidemin ) / ( slidemax - slidemin );
+ return spinmin + rel * ( spinmax - spinmin );
+}
+
+void KDoubleNumInput::sliderMoved(int val)
+{
+ d->spin->setValue( mapSliderToSpin( val ) );
+}
+
+void KDoubleNumInput::slotEmitRelativeValueChanged( double value )
+{
+ if ( !d->referencePoint ) return;
+ emit relativeValueChanged( value / d->referencePoint );
+}
+
+QSize KDoubleNumInput::minimumSizeHint() const
+{
+ constPolish();
+
+ int w;
+ int h;
+
+ h = 2 + QMAX(m_sizeEdit.height(), m_sizeSlider.height());
+
+ // if in extra row, then count it here
+ if(m_label && (m_alignment & (AlignBottom|AlignTop)))
+ h += 4 + m_sizeLabel.height();
+ else
+ // label is in the same row as the other widgets
+ h = QMAX(h, m_sizeLabel.height() + 2);
+
+ w = m_slider ? m_slider->sizeHint().width() + 8 : 0;
+ w += m_colw1 + m_colw2;
+
+ if(m_alignment & (AlignTop|AlignBottom))
+ w = QMAX(w, m_sizeLabel.width() + 4);
+
+ return QSize(w, h);
+}
+
+void KDoubleNumInput::resizeEvent(QResizeEvent* e)
+{
+ int w = m_colw1;
+ int h = 0;
+
+ if(m_label && (m_alignment & AlignTop)) {
+ m_label->setGeometry(0, 0, e->size().width(), m_sizeLabel.height());
+ h += m_sizeLabel.height() + 4;
+ }
+
+ if(m_label && (m_alignment & AlignVCenter))
+ m_label->setGeometry(0, 0, w, m_sizeEdit.height());
+
+ if (qApp->reverseLayout())
+ {
+ d->spin->setGeometry(w, h, m_slider ? m_colw2
+ : e->size().width() - w, m_sizeEdit.height());
+ w += m_colw2 + KDialog::spacingHint();
+
+ if(m_slider)
+ m_slider->setGeometry(w, h, e->size().width() - w, m_sizeEdit.height());
+ }
+ else if(m_slider) {
+ m_slider->setGeometry(w, h, e->size().width() -
+ (m_colw1 + m_colw2 + KDialog::spacingHint()),
+ m_sizeEdit.height());
+ d->spin->setGeometry(w + m_slider->width() + KDialog::spacingHint(), h,
+ m_colw2, m_sizeEdit.height());
+ }
+ else {
+ d->spin->setGeometry(w, h, e->size().width() - w, m_sizeEdit.height());
+ }
+
+ h += m_sizeEdit.height() + 2;
+
+ if(m_label && (m_alignment & AlignBottom))
+ m_label->setGeometry(0, h, m_sizeLabel.width(), m_sizeLabel.height());
+}
+
+void KDoubleNumInput::doLayout()
+{
+ m_sizeEdit = d->spin->sizeHint();
+ m_colw2 = m_sizeEdit.width();
+}
+
+void KDoubleNumInput::setValue(double val)
+{
+ d->spin->setValue( val );
+}
+
+void KDoubleNumInput::setRelativeValue( double r )
+{
+ if ( !d->referencePoint ) return;
+ ++d->blockRelative;
+ setValue( r * d->referencePoint );
+ --d->blockRelative;
+}
+
+void KDoubleNumInput::setReferencePoint( double ref )
+{
+ // clip to valid range:
+ ref = kMin( maxValue(), kMax( minValue(), ref ) );
+ d->referencePoint = ref;
+}
+
+void KDoubleNumInput::setRange(double lower, double upper, double step,
+ bool slider)
+{
+ if( m_slider ) {
+ // don't update the slider to avoid an endless recursion
+ QSpinBox * spin = d->spin;
+ disconnect(spin, SIGNAL(valueChanged(int)),
+ m_slider, SLOT(setValue(int)) );
+ }
+ d->spin->setRange( lower, upper, step, d->spin->precision() );
+
+ if(slider) {
+ // upcast to base type to get the min/maxValue in int form:
+ QSpinBox * spin = d->spin;
+ int slmax = spin->maxValue();
+ int slmin = spin->minValue();
+ int slvalue = spin->value();
+ int slstep = spin->lineStep();
+ if (m_slider) {
+ m_slider->setRange(slmin, slmax);
+ m_slider->setLineStep(slstep);
+ m_slider->setValue(slvalue);
+ } else {
+ m_slider = new QSlider(slmin, slmax, slstep, slvalue,
+ QSlider::Horizontal, this);
+ m_slider->setTickmarks(QSlider::Below);
+ // feedback line: when one moves, the other moves, too:
+ connect(m_slider, SIGNAL(valueChanged(int)),
+ SLOT(sliderMoved(int)) );
+ }
+ connect(spin, SIGNAL(valueChanged(int)),
+ m_slider, SLOT(setValue(int)) );
+ // calculate ( slmax - slmin ) / 10 without overflowing ints:
+ int major = calcDiffByTen( slmax, slmin );
+ if ( !major ) major = slstep; // ### needed?
+ m_slider->setTickInterval(major);
+ } else {
+ delete m_slider;
+ m_slider = 0;
+ }
+
+ setReferencePoint( referencePoint() );
+
+ layout(true);
+ updateLegacyMembers();
+}
+
+void KDoubleNumInput::setMinValue(double min)
+{
+ setRange(min, maxValue(), d->spin->lineStep(), m_slider);
+}
+
+double KDoubleNumInput::minValue() const
+{
+ return d->spin->minValue();
+}
+
+void KDoubleNumInput::setMaxValue(double max)
+{
+ setRange(minValue(), max, d->spin->lineStep(), m_slider);
+}
+
+double KDoubleNumInput::maxValue() const
+{
+ return d->spin->maxValue();
+}
+
+double KDoubleNumInput::value() const
+{
+ return d->spin->value();
+}
+
+double KDoubleNumInput::relativeValue() const
+{
+ if ( !d->referencePoint ) return 0;
+ return value() / d->referencePoint;
+}
+
+double KDoubleNumInput::referencePoint() const
+{
+ return d->referencePoint;
+}
+
+QString KDoubleNumInput::suffix() const
+{
+ return d->spin->suffix();
+}
+
+QString KDoubleNumInput::prefix() const
+{
+ return d->spin->prefix();
+}
+
+void KDoubleNumInput::setSuffix(const QString &suffix)
+{
+ d->spin->setSuffix( suffix );
+
+ layout(true);
+}
+
+void KDoubleNumInput::setPrefix(const QString &prefix)
+{
+ d->spin->setPrefix( prefix );
+
+ layout(true);
+}
+
+void KDoubleNumInput::setPrecision(int precision)
+{
+ d->spin->setPrecision( precision );
+
+ layout(true);
+}
+
+int KDoubleNumInput::precision() const
+{
+ return d->spin->precision();
+}
+
+void KDoubleNumInput::setSpecialValueText(const QString& text)
+{
+ d->spin->setSpecialValueText( text );
+
+ layout(true);
+ updateLegacyMembers();
+}
+
+void KDoubleNumInput::setLabel(const QString & label, int a)
+{
+ KNumInput::setLabel(label, a);
+
+ if(m_label)
+ m_label->setBuddy(d->spin);
+
+}
+
+// ----------------------------------------------------------------------------
+
+
+class KDoubleSpinBoxValidator : public KDoubleValidator
+{
+public:
+ KDoubleSpinBoxValidator( double bottom, double top, int decimals, KDoubleSpinBox* sb, const char *name )
+ : KDoubleValidator( bottom, top, decimals, sb, name ), spinBox( sb ) { }
+
+ virtual State validate( QString& str, int& pos ) const;
+
+private:
+ KDoubleSpinBox *spinBox;
+};
+
+QValidator::State KDoubleSpinBoxValidator::validate( QString& str, int& pos ) const
+{
+ QString pref = spinBox->prefix();
+ QString suff = spinBox->suffix();
+ QString suffStriped = suff.stripWhiteSpace();
+ uint overhead = pref.length() + suff.length();
+ State state = Invalid;
+
+ if ( overhead == 0 ) {
+ state = KDoubleValidator::validate( str, pos );
+ } else {
+ bool stripedVersion = false;
+ if ( str.length() >= overhead && str.startsWith(pref)
+ && (str.endsWith(suff)
+ || (stripedVersion = str.endsWith(suffStriped))) ) {
+ if ( stripedVersion )
+ overhead = pref.length() + suffStriped.length();
+ QString core = str.mid( pref.length(), str.length() - overhead );
+ int corePos = pos - pref.length();
+ state = KDoubleValidator::validate( core, corePos );
+ pos = corePos + pref.length();
+ str.replace( pref.length(), str.length() - overhead, core );
+ } else {
+ state = KDoubleValidator::validate( str, pos );
+ if ( state == Invalid ) {
+ // stripWhiteSpace(), cf. QSpinBox::interpretText()
+ QString special = spinBox->specialValueText().stripWhiteSpace();
+ QString candidate = str.stripWhiteSpace();
+
+ if ( special.startsWith(candidate) ) {
+ if ( candidate.length() == special.length() ) {
+ state = Acceptable;
+ } else {
+ state = Intermediate;
+ }
+ }
+ }
+ }
+ }
+ return state;
+}
+
+// We use a kind of fixed-point arithmetic to represent the range of
+// doubles [mLower,mUpper] in steps of 10^(-mPrecision). Thus, the
+// following relations hold:
+//
+// 1. factor = 10^mPrecision
+// 2. basicStep = 1/factor = 10^(-mPrecision);
+// 3. lowerInt = lower * factor;
+// 4. upperInt = upper * factor;
+// 5. lower = lowerInt * basicStep;
+// 6. upper = upperInt * basicStep;
+class KDoubleSpinBox::Private {
+public:
+ Private( int precision=1 )
+ : mPrecision( precision ),
+ mValidator( 0 )
+ {
+ }
+
+ int factor() const {
+ int f = 1;
+ for ( int i = 0 ; i < mPrecision ; ++i ) f *= 10;
+ return f;
+ }
+
+ double basicStep() const {
+ return 1.0/double(factor());
+ }
+
+ int mapToInt( double value, bool * ok ) const {
+ assert( ok );
+ const double f = factor();
+ if ( value > double(INT_MAX) / f ) {
+ kdWarning() << "KDoubleSpinBox: can't represent value " << value
+ << "in terms of fixed-point numbers with precision "
+ << mPrecision << endl;
+ *ok = false;
+ return INT_MAX;
+ } else if ( value < double(INT_MIN) / f ) {
+ kdWarning() << "KDoubleSpinBox: can't represent value " << value
+ << "in terms of fixed-point numbers with precision "
+ << mPrecision << endl;
+ *ok = false;
+ return INT_MIN;
+ } else {
+ *ok = true;
+ return int( value * f + ( value < 0 ? -0.5 : 0.5 ) );
+ }
+ }
+
+ double mapToDouble( int value ) const {
+ return double(value) * basicStep();
+ }
+
+ int mPrecision;
+ KDoubleSpinBoxValidator * mValidator;
+};
+
+KDoubleSpinBox::KDoubleSpinBox( QWidget * parent, const char * name )
+ : QSpinBox( parent, name )
+{
+ editor()->setAlignment( Qt::AlignRight );
+ d = new Private();
+ updateValidator();
+ connect( this, SIGNAL(valueChanged(int)), SLOT(slotValueChanged(int)) );
+}
+
+KDoubleSpinBox::KDoubleSpinBox( double lower, double upper, double step,
+ double value, int precision,
+ QWidget * parent, const char * name )
+ : QSpinBox( parent, name )
+{
+ editor()->setAlignment( Qt::AlignRight );
+ d = new Private();
+ setRange( lower, upper, step, precision );
+ setValue( value );
+ connect( this, SIGNAL(valueChanged(int)), SLOT(slotValueChanged(int)) );
+}
+
+KDoubleSpinBox::~KDoubleSpinBox() {
+ delete d; d = 0;
+}
+
+bool KDoubleSpinBox::acceptLocalizedNumbers() const {
+ if ( !d->mValidator ) return true; // we'll set one that does;
+ // can't do it now, since we're const
+ return d->mValidator->acceptLocalizedNumbers();
+}
+
+void KDoubleSpinBox::setAcceptLocalizedNumbers( bool accept ) {
+ if ( !d->mValidator ) updateValidator();
+ d->mValidator->setAcceptLocalizedNumbers( accept );
+}
+
+void KDoubleSpinBox::setRange( double lower, double upper, double step,
+ int precision ) {
+ lower = kMin(upper, lower);
+ upper = kMax(upper, lower);
+ setPrecision( precision, true ); // disable bounds checking, since
+ setMinValue( lower ); // it's done in set{Min,Max}Value
+ setMaxValue( upper ); // anyway and we want lower, upper
+ setLineStep( step ); // and step to have the right precision
+}
+
+int KDoubleSpinBox::precision() const {
+ return d->mPrecision;
+}
+
+void KDoubleSpinBox::setPrecision( int precision ) {
+ setPrecision( precision, false );
+}
+
+void KDoubleSpinBox::setPrecision( int precision, bool force ) {
+ if ( precision < 1 ) return;
+ if ( !force ) {
+ int maxPrec = maxPrecision();
+ if ( precision > maxPrec )
+ precision = maxPrec;
+ }
+ d->mPrecision = precision;
+ updateValidator();
+}
+
+int KDoubleSpinBox::maxPrecision() const {
+ // INT_MAX must be > maxAbsValue * 10^precision
+ // ==> 10^precision < INT_MAX / maxAbsValue
+ // ==> precision < log10 ( INT_MAX / maxAbsValue )
+ // ==> maxPrecision = floor( log10 ( INT_MAX / maxAbsValue ) );
+ double maxAbsValue = kMax( fabs(minValue()), fabs(maxValue()) );
+ if ( maxAbsValue == 0 ) return 6; // return arbitrary value to avoid dbz...
+
+ return int( floor( log10( double(INT_MAX) / maxAbsValue ) ) );
+}
+
+double KDoubleSpinBox::value() const {
+ return d->mapToDouble( base::value() );
+}
+
+void KDoubleSpinBox::setValue( double value ) {
+ if ( value == this->value() ) return;
+ if ( value < minValue() )
+ base::setValue( base::minValue() );
+ else if ( value > maxValue() )
+ base::setValue( base::maxValue() );
+ else {
+ bool ok = false;
+ base::setValue( d->mapToInt( value, &ok ) );
+ assert( ok );
+ }
+}
+
+double KDoubleSpinBox::minValue() const {
+ return d->mapToDouble( base::minValue() );
+}
+
+void KDoubleSpinBox::setMinValue( double value ) {
+ bool ok = false;
+ int min = d->mapToInt( value, &ok );
+ if ( !ok ) return;
+ base::setMinValue( min );
+ updateValidator();
+}
+
+
+double KDoubleSpinBox::maxValue() const {
+ return d->mapToDouble( base::maxValue() );
+}
+
+void KDoubleSpinBox::setMaxValue( double value ) {
+ bool ok = false;
+ int max = d->mapToInt( value, &ok );
+ if ( !ok ) return;
+ base::setMaxValue( max );
+ updateValidator();
+}
+
+double KDoubleSpinBox::lineStep() const {
+ return d->mapToDouble( base::lineStep() );
+}
+
+void KDoubleSpinBox::setLineStep( double step ) {
+ bool ok = false;
+ if ( step > maxValue() - minValue() )
+ base::setLineStep( 1 );
+ else
+ base::setLineStep( kMax( d->mapToInt( step, &ok ), 1 ) );
+}
+
+QString KDoubleSpinBox::mapValueToText( int value ) {
+ if ( acceptLocalizedNumbers() )
+ return KGlobal::locale()
+ ->formatNumber( d->mapToDouble( value ), d->mPrecision );
+ else
+ return QString().setNum( d->mapToDouble( value ), 'f', d->mPrecision );
+}
+
+int KDoubleSpinBox::mapTextToValue( bool * ok ) {
+ double value;
+ if ( acceptLocalizedNumbers() )
+ value = KGlobal::locale()->readNumber( cleanText(), ok );
+ else
+ value = cleanText().toDouble( ok );
+ if ( !*ok ) return 0;
+ if ( value > maxValue() )
+ value = maxValue();
+ else if ( value < minValue() )
+ value = minValue();
+ return d->mapToInt( value, ok );
+}
+
+void KDoubleSpinBox::setValidator( const QValidator * ) {
+ // silently discard the new validator. We don't want another one ;-)
+}
+
+void KDoubleSpinBox::slotValueChanged( int value ) {
+ emit valueChanged( d->mapToDouble( value ) );
+}
+
+void KDoubleSpinBox::updateValidator() {
+ if ( !d->mValidator ) {
+ d->mValidator = new KDoubleSpinBoxValidator( minValue(), maxValue(), precision(),
+ this, "d->mValidator" );
+ base::setValidator( d->mValidator );
+ } else
+ d->mValidator->setRange( minValue(), maxValue(), precision() );
+}
+
+void KNumInput::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void KIntNumInput::virtual_hook( int id, void* data )
+{ KNumInput::virtual_hook( id, data ); }
+
+void KDoubleNumInput::virtual_hook( int id, void* data )
+{ KNumInput::virtual_hook( id, data ); }
+
+void KIntSpinBox::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void KDoubleSpinBox::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "knuminput.moc"
diff --git a/kdeui/knuminput.h b/kdeui/knuminput.h
new file mode 100644
index 000000000..212e0e3cf
--- /dev/null
+++ b/kdeui/knuminput.h
@@ -0,0 +1,957 @@
+/*
+ * knuminput.h
+ *
+ * Copyright (c) 1997 Patrick Dowler <dowler@morgul.fsh.uvic.ca>
+ * Copyright (c) 2000 Dirk A. Mueller <mueller@kde.org>
+ * Copyright (c) 2002 Marc Mutz <mutz@kde.org>
+ *
+ * Requires the Qt widget libraries, available at no cost at
+ * http://www.troll.no/
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef K_NUMINPUT_H
+#define K_NUMINPUT_H
+
+#include <qwidget.h>
+#include <qspinbox.h>
+#include <kdelibs_export.h>
+
+class QLabel;
+class QSlider;
+class QLineEdit;
+class QLayout;
+class QValidator;
+
+class KIntSpinBox;
+
+/* ------------------------------------------------------------------------ */
+
+/**
+ * You need to inherit from this class if you want to implement K*NumInput
+ * for a different variable type
+ *
+ */
+class KDEUI_EXPORT KNumInput : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY( QString label READ label WRITE setLabel )
+public:
+ /**
+ * Default constructor
+ * @param parent If parent is 0, the new widget becomes a top-level window. If parent is another widget, this widget becomes a child window inside parent. The new widget is deleted when its parent is deleted.
+ * @param name The name is sent to the QObject constructor.
+ */
+ KNumInput(QWidget* parent=0, const char* name=0);
+
+ /**
+ * @param below A pointer to another KNumInput.
+ * @param parent parent widget
+ * @param name name of the widget
+ */
+ KNumInput(KNumInput* below, QWidget* parent=0, const char* name=0);
+ ~KNumInput();
+
+ /**
+ * Sets the text and alignment of the main description label.
+ *
+ * @param label The text of the label.
+ * Use QString::null to remove an existing one.
+ *
+ * @param a one of @p AlignLeft, @p AlignHCenter, YAlignRight and
+ * @p AlignTop, @p AlignVCenter, @p AlignBottom.
+ * default is @p AlignLeft | @p AlignTop.
+ *
+ * The vertical alignment flags have special meaning with this
+ * widget:
+ *
+ * @li @p AlignTop The label is placed above the edit/slider
+ * @li @p AlignVCenter The label is placed left beside the edit
+ * @li @p AlignBottom The label is placed below the edit/slider
+ *
+ */
+ virtual void setLabel(const QString & label, int a = AlignLeft | AlignTop);
+
+ /**
+ * @return the text of the label.
+ */
+ QString label() const;
+
+ /**
+ * @return if the num input has a slider.
+ * @since 3.1
+ */
+ bool showSlider() const { return m_slider; }
+
+ /**
+ * Sets the spacing of tickmarks for the slider.
+ *
+ * @param minor Minor tickmark separation.
+ * @param major Major tickmark separation.
+ */
+ void setSteps(int minor, int major);
+
+ /**
+ * Specifies that this widget may stretch horizontally, but is
+ * fixed vertically (like QSpinBox itself).
+ */
+ QSizePolicy sizePolicy() const;
+
+ /**
+ * Returns a size which fits the contents of the control.
+ *
+ * @return the preferred size necessary to show the control
+ */
+ virtual QSize sizeHint() const;
+
+protected:
+ /**
+ * Call this function whenever you change something in the geometry
+ * of your KNumInput child.
+ *
+ */
+ void layout(bool deep);
+
+ /**
+ * You need to overwrite this method and implement your layout
+ * calculations there.
+ *
+ * See KIntNumInput::doLayout and KDoubleNumInput::doLayout implementation
+ * for details.
+ *
+ */
+ virtual void doLayout() = 0;
+
+ KNumInput* m_prev, *m_next;
+ int m_colw1, m_colw2;
+
+ QLabel* m_label;
+ QSlider* m_slider;
+ QSize m_sizeSlider, m_sizeLabel;
+
+ int m_alignment;
+
+private:
+ void init();
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KNumInputPrivate;
+ KNumInputPrivate *d;
+};
+
+/* ------------------------------------------------------------------------ */
+
+/**
+ * @short An input widget for integer numbers, consisting of a spinbox and a slider.
+ *
+ * KIntNumInput combines a QSpinBox and optionally a QSlider
+ * with a label to make an easy to use control for setting some integer
+ * parameter. This is especially nice for configuration dialogs,
+ * which can have many such combinated controls.
+ *
+ * The slider is created only when the user specifies a range
+ * for the control using the setRange function with the slider
+ * parameter set to "true".
+ *
+ * A special feature of KIntNumInput, designed specifically for
+ * the situation when there are several KIntNumInputs in a column,
+ * is that you can specify what portion of the control is taken by the
+ * QSpinBox (the remaining portion is used by the slider). This makes
+ * it very simple to have all the sliders in a column be the same size.
+ *
+ * It uses KIntValidator validator class. KIntNumInput enforces the
+ * value to be in the given range, and can display it in any base
+ * between 2 and 36.
+ *
+ * \image html kintnuminput.png "KDE Int Number Input Spinbox"
+ *
+ * @version $Id$
+ */
+
+class KDEUI_EXPORT KIntNumInput : public KNumInput
+{
+ Q_OBJECT
+ Q_PROPERTY( int value READ value WRITE setValue )
+ Q_PROPERTY( int minValue READ minValue WRITE setMinValue )
+ Q_PROPERTY( int maxValue READ maxValue WRITE setMaxValue )
+ Q_PROPERTY( int referencePoint READ referencePoint WRITE setReferencePoint )
+ Q_PROPERTY( double relativeValue READ relativeValue WRITE setRelativeValue )
+ Q_PROPERTY( QString suffix READ suffix WRITE setSuffix )
+ Q_PROPERTY( QString prefix READ prefix WRITE setPrefix )
+ Q_PROPERTY( QString specialValueText READ specialValueText WRITE setSpecialValueText )
+
+public:
+ /**
+ * Constructs an input control for integer values
+ * with base 10 and initial value 0.
+ */
+ KIntNumInput(QWidget *parent=0, const char *name=0);
+ /**
+ * Constructor
+ * It constructs a QSpinBox that allows the input of integer numbers
+ * in the range of -INT_MAX to +INT_MAX. To set a descriptive label,
+ * use setLabel(). To enforce the value being in a range and optionally to
+ * attach a slider to it, use setRange().
+ *
+ * @param value initial value for the control
+ * @param base numeric base used for display
+ * @param parent parent QWidget
+ * @param name internal name for this widget
+ */
+ KIntNumInput(int value, QWidget* parent=0, int base = 10, const char *name=0);
+
+ /**
+ * Constructor
+ *
+ * the difference to the one above is the "below" parameter. It tells
+ * this instance that it is visually put below some other KNumInput widget.
+ * Note that these two KNumInput's need not to have the same parent widget
+ * or be in the same layout group.
+ * The effect is that it'll adjust it's layout in correspondence
+ * with the layout of the other KNumInput's (you can build an arbitrary long
+ * chain).
+ *
+ * @param below append KIntNumInput to the KNumInput chain
+ * @param value initial value for the control
+ * @param base numeric base used for display
+ * @param parent parent QWidget
+ * @param name internal name for this widget
+ */
+ KIntNumInput(KNumInput* below, int value, QWidget* parent=0, int base = 10, const char *name=0);
+
+ /**
+ * Destructor
+ *
+ *
+ */
+ virtual ~KIntNumInput();
+
+ /**
+ * @return the current value.
+ */
+ int value() const;
+
+ /**
+ * @return the curent value in units of the referencePoint.
+ * @since 3.1
+ */
+ double relativeValue() const;
+
+ /**
+ * @return the current reference point
+ * @since 3.1
+ */
+ int referencePoint() const;
+
+ /**
+ * @return the suffix displayed behind the value.
+ * @see setSuffix()
+ */
+ QString suffix() const;
+ /**
+ * @return the prefix displayed in front of the value.
+ * @see setPrefix()
+ */
+ QString prefix() const;
+ /**
+ * @return the string displayed for a special value.
+ * @see setSpecialValueText()
+ */
+ QString specialValueText() const;
+
+ /**
+ * @param min minimum value
+ * @param max maximum value
+ * @param step step size for the QSlider
+ * @param slider whether the slider is created or not
+ */
+ void setRange(int min, int max, int step=1, bool slider=true);
+ /**
+ * Sets the minimum value.
+ */
+ void setMinValue(int min);
+ /**
+ * @return the minimum value.
+ */
+ int minValue() const;
+ /**
+ * Sets the maximum value.
+ */
+ void setMaxValue(int max);
+ /**
+ * @return the maximum value.
+ */
+ int maxValue() const;
+
+ /**
+ * Sets the special value text. If set, the SpinBox will display
+ * this text instead of the numeric value whenever the current
+ * value is equal to minVal(). Typically this is used for indicating
+ * that the choice has a special (default) meaning.
+ */
+ void setSpecialValueText(const QString& text);
+
+ virtual void setLabel(const QString & label, int a = AlignLeft | AlignTop);
+
+ /**
+ * This method returns the minimum size necessary to display the
+ * control. The minimum size is enough to show all the labels
+ * in the current font (font change may invalidate the return value).
+ *
+ * @return the minimum size necessary to show the control
+ */
+ virtual QSize minimumSizeHint() const;
+
+public slots:
+ /**
+ * Sets the value of the control.
+ */
+ void setValue(int);
+
+ /**
+ * Sets the value in units of the referencePoint
+ * @since 3.1
+ */
+ void setRelativeValue(double);
+
+ /**
+ * Sets the reference point for relativeValue.
+ * @since 3.1
+ */
+ void setReferencePoint(int);
+
+ /**
+ * Sets the suffix to @p suffix.
+ * Use QString::null to disable this feature.
+ * Formatting has to be provided (e.g. a space separator between the
+ * prepended @p value and the suffix's text has to be provided
+ * as the first character in the suffix).
+ *
+ * @see QSpinBox::setSuffix(), #setPrefix()
+ */
+ void setSuffix(const QString &suffix);
+
+ /**
+ * Sets the prefix to @p prefix.
+ * Use QString::null to disable this feature.
+ * Formatting has to be provided (see above).
+ *
+ * @see QSpinBox::setPrefix(), #setSuffix()
+ */
+ void setPrefix(const QString &prefix);
+
+ /**
+ * sets focus to the edit widget and marks all text in if mark == true
+ *
+ */
+ void setEditFocus( bool mark = true );
+
+signals:
+ /**
+ * Emitted every time the value changes (by calling setValue() or
+ * by user interaction).
+ */
+ void valueChanged(int);
+
+ /**
+ * Emitted whenever valueChanged is. Contains the change
+ * relative to the referencePoint.
+ * @since 3.1
+ */
+ void relativeValueChanged(double);
+
+private slots:
+ void spinValueChanged(int);
+ void slotEmitRelativeValueChanged(int);
+
+protected:
+ virtual void doLayout();
+ void resizeEvent ( QResizeEvent * );
+
+ KIntSpinBox* m_spin;
+ QSize m_sizeSpin;
+
+private:
+ void init(int value, int _base);
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KIntNumInputPrivate;
+ KIntNumInputPrivate *d;
+};
+
+
+/* ------------------------------------------------------------------------ */
+
+class KDoubleLine;
+
+/**
+ * @short An input control for real numbers, consisting of a spinbox and a slider.
+ *
+ * KDoubleNumInput combines a QSpinBox and optionally a QSlider
+ * with a label to make an easy to use control for setting some float
+ * parameter. This is especially nice for configuration dialogs,
+ * which can have many such combinated controls.
+ *
+ * The slider is created only when the user specifies a range
+ * for the control using the setRange function with the slider
+ * parameter set to "true".
+ *
+ * A special feature of KDoubleNumInput, designed specifically for
+ * the situation when there are several instances in a column,
+ * is that you can specify what portion of the control is taken by the
+ * QSpinBox (the remaining portion is used by the slider). This makes
+ * it very simple to have all the sliders in a column be the same size.
+ *
+ * It uses the KDoubleValidator validator class. KDoubleNumInput
+ * enforces the value to be in the given range, but see the class
+ * documentation of KDoubleSpinBox for the tricky
+ * interrelationship of precision and values. All of what is said
+ * there applies here, too.
+ *
+ * @see KIntNumInput, KDoubleSpinBox
+ */
+
+class KDEUI_EXPORT KDoubleNumInput : public KNumInput
+{
+ Q_OBJECT
+ Q_PROPERTY( double value READ value WRITE setValue )
+ Q_PROPERTY( double minValue READ minValue WRITE setMinValue )
+ Q_PROPERTY( double maxValue READ maxValue WRITE setMaxValue )
+ Q_PROPERTY( QString suffix READ suffix WRITE setSuffix )
+ Q_PROPERTY( QString prefix READ prefix WRITE setPrefix )
+ Q_PROPERTY( QString specialValueText READ specialValueText WRITE setSpecialValueText )
+ Q_PROPERTY( int precision READ precision WRITE setPrecision )
+ Q_PROPERTY( double referencePoint READ referencePoint WRITE setReferencePoint )
+ Q_PROPERTY( double relativeValue READ relativeValue WRITE setRelativeValue )
+
+public:
+ /**
+ * Constructs an input control for double values
+ * with initial value 0.00.
+ */
+ KDoubleNumInput(QWidget *parent=0, const char *name=0);
+
+ /**
+ * @deprecated (value is rounded to a multiple of 1/100)
+ * Constructor
+ *
+ * @param value initial value for the control
+ * @param parent parent QWidget
+ * @param name internal name for this widget
+ */
+ KDoubleNumInput(double value, QWidget *parent=0, const char *name=0) KDE_DEPRECATED;
+
+ /**
+ * Constructor
+ *
+ * @param lower lower boundary value
+ * @param upper upper boundary value
+ * @param value initial value for the control
+ * @param step step size to use for up/down arrow clicks
+ * @param precision number of digits after the decimal point
+ * @param parent parent QWidget
+ * @param name internal name for this widget
+ * @since 3.1
+ */
+ KDoubleNumInput(double lower, double upper, double value, double step=0.01,
+ int precision=2, QWidget *parent=0, const char *name=0);
+
+ /**
+ * destructor
+ */
+ virtual ~KDoubleNumInput();
+
+ /**
+ * @deprecated (rounds @p value to a multiple of 1/100)
+ * Constructor
+ *
+ * puts it visually below other KNumInput
+ *
+ * @param below
+ * @param value initial value for the control
+ * @param parent parent QWidget
+ * @param name internal name for this widget
+ **/
+ KDoubleNumInput(KNumInput* below, double value, QWidget* parent=0, const char* name=0) KDE_DEPRECATED;
+
+ /**
+ * Constructor
+ *
+ * the difference here is the "below" parameter. It tells this
+ * instance that it is visually put below some other KNumInput
+ * widget. Note that these two KNumInput's need not to have the
+ * same parent widget or be in the same layout group. The effect
+ * is that it'll adjust it's layout in correspondence with the
+ * layout of the other KNumInput's (you can build an arbitrary long
+ * chain).
+ *
+ * @param below append KDoubleNumInput to the KDoubleNumInput chain
+ * @param lower lower boundary value
+ * @param upper upper boundary value
+ * @param value initial value for the control
+ * @param step step size to use for up/down arrow clicks
+ * @param precision number of digits after the decimal point
+ * @param parent parent QWidget
+ * @param name internal name for this widget
+ * @since 3.1
+ */
+ KDoubleNumInput(KNumInput* below,
+ double lower, double upper, double value, double step=0.02,
+ int precision=2, QWidget *parent=0, const char *name=0);
+
+ /**
+ * @return the current value.
+ */
+ double value() const;
+
+ /**
+ * @return the suffix.
+ * @see setSuffix()
+ */
+ QString suffix() const;
+
+ /**
+ * @return the prefix.
+ * @see setPrefix()
+ */
+ QString prefix() const;
+
+ /**
+ * @return the precision.
+ * @see setPrecision()
+ */
+ int precision() const;
+
+ /**
+ * @return the string displayed for a special value.
+ * @see setSpecialValueText()
+ */
+ QString specialValueText() const { return m_specialvalue; }
+
+ /**
+ * @param min minimum value
+ * @param max maximum value
+ * @param step step size for the QSlider
+ * @param slider whether the slider is created or not
+ */
+ void setRange(double min, double max, double step=1, bool slider=true);
+ /**
+ * Sets the minimum value.
+ */
+ void setMinValue(double min);
+ /**
+ * @return the minimum value.
+ */
+ double minValue() const;
+ /**
+ * Sets the maximum value.
+ */
+ void setMaxValue(double max);
+ /**
+ * @return the maximum value.
+ */
+ double maxValue() const;
+
+ /**
+ * Specifies the number of digits to use.
+ */
+ void setPrecision(int precision);
+
+ /**
+ * @return the reference point for relativeValue calculation
+ * @since 3.1
+ */
+ double referencePoint() const;
+
+ /**
+ * @return the current value in units of referencePoint.
+ * @since 3.1
+ */
+ double relativeValue() const;
+
+ /**
+ * Sets the special value text. If set, the spin box will display
+ * this text instead of the numeric value whenever the current
+ * value is equal to minVal(). Typically this is used for indicating
+ * that the choice has a special (default) meaning.
+ */
+ void setSpecialValueText(const QString& text);
+
+ virtual void setLabel(const QString & label, int a = AlignLeft | AlignTop);
+ virtual QSize minimumSizeHint() const;
+ virtual bool eventFilter(QObject*, QEvent*);
+
+public slots:
+ /**
+ * Sets the value of the control.
+ */
+ void setValue(double);
+
+ /**
+ * Sets the value in units of referencePoint.
+ * @since 3.1
+ */
+ void setRelativeValue(double);
+
+ /**
+ * Sets the reference Point to @p ref. It @p ref == 0, emitting of
+ * relativeValueChanged is blocked and relativeValue
+ * just returns 0.
+ * @since 3.1
+ */
+ void setReferencePoint(double ref);
+
+ /**
+ * Sets the suffix to be displayed to @p suffix. Use QString::null to disable
+ * this feature. Note that the suffix is attached to the value without any
+ * spacing. So if you prefer to display a space separator, set suffix
+ * to something like " cm".
+ * @see setSuffix()
+ */
+ void setSuffix(const QString &suffix);
+
+ /**
+ * Sets the prefix to be displayed to @p prefix. Use QString::null to disable
+ * this feature. Note that the prefix is attached to the value without any
+ * spacing.
+ * @see setPrefix()
+ */
+ void setPrefix(const QString &prefix);
+
+signals:
+ /**
+ * Emitted every time the value changes (by calling setValue() or
+ * by user interaction).
+ */
+ void valueChanged(double);
+ /**
+ * This is an overloaded member function, provided for
+ * convenience. It essentially behaves like the above function.
+ *
+ * Contains the value in units of referencePoint.
+ * @since 3.1
+ */
+ void relativeValueChanged(double);
+
+private slots:
+ void sliderMoved(int);
+ void slotEmitRelativeValueChanged(double);
+
+protected:
+ virtual void doLayout();
+ void resizeEvent ( QResizeEvent * );
+
+ virtual void resetEditBox();
+
+ // ### no longer used, remove when BIC allowed
+ KDoubleLine* edit;
+
+ bool m_range;
+ double m_lower, m_upper, m_step;
+ // ### end no longer used
+
+ QSize m_sizeEdit;
+
+ friend class KDoubleLine;
+private:
+ void init(double value, double lower, double upper,
+ double step, int precision);
+ double mapSliderToSpin(int) const;
+ void updateLegacyMembers();
+ // ### no longer used, remove when BIC allowed:
+ QString m_specialvalue, m_prefix, m_suffix;
+ double m_value;
+ short m_precision;
+ // ### end remove when BIC allowed
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KDoubleNumInputPrivate;
+ KDoubleNumInputPrivate *d;
+};
+
+
+/* ------------------------------------------------------------------------ */
+
+/**
+ * @short A QSpinBox with support for arbitrary base numbers.
+ *
+ * A QSpinBox with support for arbitrary base numbers
+ * (e.g. hexadecimal).
+ *
+ * The class provides an easy interface to use other
+ * numeric systems than the decimal.
+ */
+class KDEUI_EXPORT KIntSpinBox : public QSpinBox
+{
+ Q_OBJECT
+ Q_PROPERTY( int base READ base WRITE setBase )
+
+public:
+
+ /**
+ * Constructor.
+ *
+ * Constructs a widget with an integer inputline with a little scrollbar
+ * and a slider, with minimal value 0, maximal value 99, step 1, base 10
+ * and initial value 0.
+ */
+ KIntSpinBox( QWidget *parent=0, const char *name=0);
+
+ /**
+ * Constructor.
+ *
+ * Constructs a widget with an integer inputline with a little scrollbar
+ * and a slider.
+ *
+ * @param lower The lowest valid value.
+ * @param upper The greatest valid value.
+ * @param step The step size of the scrollbar.
+ * @param value The actual value.
+ * @param base The base of the used number system.
+ * @param parent The parent of the widget.
+ * @param name The Name of the widget.
+ */
+ KIntSpinBox(int lower, int upper, int step, int value, int base = 10,
+ QWidget* parent = 0, const char* name = 0);
+
+ /**
+ * Destructor.
+ */
+ virtual ~KIntSpinBox();
+
+ /**
+ * Sets the base in which the numbers in the spin box are represented.
+ */
+ void setBase(int base);
+ /**
+ * @return the base in which numbers in the spin box are represented.
+ */
+ int base() const;
+ /**
+ * sets focus and optionally marks all text
+ *
+ */
+ void setEditFocus(bool mark);
+
+protected:
+
+ /**
+ * Overloaded the method in QSpinBox
+ * to make use of the base given in the constructor.
+ */
+ virtual QString mapValueToText(int);
+
+ /**
+ * Overloaded the method in QSpinBox
+ * to make use of the base given in the constructor.
+ */
+ virtual int mapTextToValue(bool*);
+
+private:
+ int val_base;
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KIntSpinBoxPrivate;
+ KIntSpinBoxPrivate *d;
+};
+
+
+/* --------------------------------------------------------------------------- */
+
+/**
+ @short A spin box for fractional numbers.
+
+ This class provides a spin box for fractional numbers.
+
+ \image html kdoublespinbox.png "KDE Fractional Number Spinbox"
+
+ See below for code examples on how to use this class.
+
+ \b Parameters \n
+
+ To make successful use of KDoubleSpinBox, you need to understand the
+ relationship between precision and available range.
+
+ @li precision: The number of digits after the decimal point.
+ @li maxValue/minValue: upper and lower bounds of the valid range
+ @li lineStep: the size of the step that is made when the user hits
+ the up or down buttons
+
+ Since we work with fixed-point numbers internally, the maximum
+ precision is a function of the valid range and vice versa. More
+ precisely, the following relationships hold:
+ \code
+ max( abs(minValue()), abs(maxValue() ) <= INT_MAX/10^precision
+ maxPrecision = floor( log10( INT_MAX/max(abs(minValue()),abs(maxValue())) ) )
+ \endcode
+
+ Since the value, bounds and lineStep are rounded to the current
+ precision, you may find that the order of setting these
+ parameters matters. As an example, the following are @em not equivalent (try
+ it!):
+
+ \code
+ // sets precision,
+ // then min/max value (rounded to precision and clipped to obtainable range if needed)
+ // then value and lineStep
+ KDoubleSpinBox * spin = new KDoubleSpinBox( 0, 9.999, 0.001, 4.321, 3, this );
+
+ // sets minValue to 0; maxValue to 10.00(!); value to 4.32(!) and only then
+ // increases the precision - too late, since e.g. value has already been rounded...
+ KDoubleSpinBox * spin = new KDoubleSpinBox( this );
+ spin->setMinValue( 0 );
+ spin->setMaxValue( 9.999 );
+ spin->setValue( 4.321 );
+ spin->setPrecision( 3 );
+ \endcode
+
+ @author Marc Mutz <mutz@kde.org>
+ @version $Id$
+ @since 3.1
+**/
+
+class KDEUI_EXPORT KDoubleSpinBox : public QSpinBox {
+ Q_OBJECT
+ Q_PROPERTY( bool acceptLocalizedNumbers READ acceptLocalizedNumbers WRITE setAcceptLocalizedNumbers )
+ Q_OVERRIDE( double maxValue READ maxValue WRITE setMaxValue )
+ Q_OVERRIDE( double minValue READ minValue WRITE setMinValue )
+ Q_OVERRIDE( double lineStep READ lineStep WRITE setLineStep )
+ Q_OVERRIDE( double value READ value WRITE setValue )
+ Q_PROPERTY( int precision READ precision WRITE setPrecision )
+
+public:
+ /** Constructs a KDoubleSpinBox with parent @p parent and
+ default values for range and value (whatever QRangeControl
+ uses) and precision (2). */
+ KDoubleSpinBox( QWidget * parent=0, const char * name=0 );
+
+ /** Constructs a KDoubleSpinBox with parent @p parent, range
+ [ @p lower, @p upper ], lineStep @p step, precision @p
+ precision and initial value @p value. */
+ KDoubleSpinBox( double lower, double upper, double step, double value,
+ int precision=2, QWidget * parent=0, const char * name=0 );
+
+ virtual ~KDoubleSpinBox();
+
+ /** @return whether the spinbox uses localized numbers */
+ bool acceptLocalizedNumbers() const;
+
+ /** Sets whether to use and accept localized numbers as returned by
+ KLocale::formatNumber() */
+ virtual void setAcceptLocalizedNumbers( bool accept );
+
+ /** Sets a new range for the spin box values. Note that @p lower, @p
+ upper and @p step are rounded to @p precision decimal points
+ first. */
+ void setRange( double lower, double upper, double step=0.01, int precision=2 );
+
+ /** @return the current number of digits displayed to the right of the
+ decimal point. */
+ int precision() const;
+
+ /** Equivalent to setPrecision( @p precision, @p false ); Needed
+ since Qt's moc doesn't ignore trailing parameters with default
+ args when searching for a property setter method. */
+ void setPrecision( int precision );
+
+ /** Sets the precision (number of digits to the right of the decimal point). Note
+ that there is a tradeoff between the precision used and the available range of
+ values. See the class documentation above for more information on this.
+
+ @param precision the new precision to use
+
+ @param force if true, disables checking of bounds violations that can
+ arise if you increase the precision so much that the
+ minimum and maximum values can't be represented
+ anymore. Disabling is useful if you were going to disable range
+ control in any case.
+ **/
+ virtual void setPrecision( int precision, bool force );
+
+ /** @return the current value */
+ double value() const;
+
+ /** @return the current lower bound */
+ double minValue() const;
+
+ /** Sets the lower bound of the range to @p value, subject to the
+ contraints that @p value is first rounded to the current
+ precision and then clipped to the maximum range interval that can
+ be handled at that precision.
+ @see maxValue, minValue, setMaxValue, setRange
+ */
+ void setMinValue( double value );
+
+ /** @return the current upper bound */
+ double maxValue() const;
+
+ /** Sets the upper bound of the range to @p value, subject to the
+ contraints that @p value is first rounded to the current
+ precision and then clipped to the maximum range interval
+ that can be handled at that precision.
+ @see minValue, maxValue, setMinValue, setRange
+ */
+ void setMaxValue( double value );
+
+ /** @return the current step size */
+ double lineStep() const;
+
+ /** Sets the step size for clicking the up/down buttons to @p step,
+ subject to the constraints that @p step is first rounded to the
+ current precision and then clipped to the meaningful interval
+ [ 1, @p maxValue() - @p minValue() ]. */
+ void setLineStep( double step );
+
+ /** Overridden to ignore any setValidator() calls. */
+ void setValidator( const QValidator * );
+
+signals:
+ /** Emitted whenever QSpinBox::valueChanged( int ) is emitted. */
+ void valueChanged( double value );
+
+public slots:
+ /** Sets the current value to @p value, subject to the constraints
+ that @p value is first rounded to the current precision and then
+ clipped to the interval [ @p minValue() , @p maxValue() ]. */
+ virtual void setValue( double value );
+
+protected:
+ virtual QString mapValueToText(int);
+ virtual int mapTextToValue(bool*);
+
+protected slots:
+ void slotValueChanged( int value );
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ typedef QSpinBox base;
+ void updateValidator();
+ int maxPrecision() const;
+
+ class Private;
+ Private * d;
+};
+
+#endif // K_NUMINPUT_H
diff --git a/kdeui/knumvalidator.cpp b/kdeui/knumvalidator.cpp
new file mode 100644
index 000000000..890fb76a0
--- /dev/null
+++ b/kdeui/knumvalidator.cpp
@@ -0,0 +1,371 @@
+/**********************************************************************
+**
+**
+** KIntValidator, KFloatValidator:
+** Copyright (C) 1999 Glen Parker <glenebob@nwlink.com>
+** KDoubleValidator:
+** Copyright (c) 2002 Marc Mutz <mutz@kde.org>
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Library General Public
+** License as published by the Free Software Foundation; either
+** version 2 of the License, or (at your option) any later version.
+**
+** This library is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** Library General Public License for more details.
+**
+** You should have received a copy of the GNU Library General Public
+** License along with this library; if not, write to the Free
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+**
+*****************************************************************************/
+
+#include <qwidget.h>
+#include <qstring.h>
+
+#include "knumvalidator.h"
+#include <klocale.h>
+#include <kglobal.h>
+#include <kdebug.h>
+
+///////////////////////////////////////////////////////////////
+// Implementation of KIntValidator
+//
+
+KIntValidator::KIntValidator ( QWidget * parent, int base, const char * name )
+ : QValidator(parent, name)
+{
+ _base = base;
+ if (_base < 2) _base = 2;
+ if (_base > 36) _base = 36;
+
+ _min = _max = 0;
+}
+
+KIntValidator::KIntValidator ( int bottom, int top, QWidget * parent, int base, const char * name )
+ : QValidator(parent, name)
+{
+ _base = base;
+ if (_base > 36) _base = 36;
+
+ _min = bottom;
+ _max = top;
+}
+
+KIntValidator::~KIntValidator ()
+{}
+
+QValidator::State KIntValidator::validate ( QString &str, int & ) const
+{
+ bool ok;
+ int val = 0;
+ QString newStr;
+
+ newStr = str.stripWhiteSpace();
+ if (_base > 10)
+ newStr = newStr.upper();
+
+ if (newStr == QString::fromLatin1("-")) // a special case
+ if ((_min || _max) && _min >= 0)
+ ok = false;
+ else
+ return QValidator::Acceptable;
+ else if (newStr.length())
+ val = newStr.toInt(&ok, _base);
+ else {
+ val = 0;
+ ok = true;
+ }
+
+ if (! ok)
+ return QValidator::Invalid;
+
+ if ((! _min && ! _max) || (val >= _min && val <= _max))
+ return QValidator::Acceptable;
+
+ if (_max && _min >= 0 && val < 0)
+ return QValidator::Invalid;
+
+ return QValidator::Valid;
+}
+
+void KIntValidator::fixup ( QString &str ) const
+{
+ int dummy;
+ int val;
+ QValidator::State state;
+
+ state = validate(str, dummy);
+
+ if (state == QValidator::Invalid || state == QValidator::Acceptable)
+ return;
+
+ if (! _min && ! _max)
+ return;
+
+ val = str.toInt(0, _base);
+
+ if (val < _min) val = _min;
+ if (val > _max) val = _max;
+
+ str.setNum(val, _base);
+}
+
+void KIntValidator::setRange ( int bottom, int top )
+{
+ _min = bottom;
+ _max = top;
+
+ if (_max < _min)
+ _max = _min;
+}
+
+void KIntValidator::setBase ( int base )
+{
+ _base = base;
+ if (_base < 2) _base = 2;
+}
+
+int KIntValidator::bottom () const
+{
+ return _min;
+}
+
+int KIntValidator::top () const
+{
+ return _max;
+}
+
+int KIntValidator::base () const
+{
+ return _base;
+}
+
+
+///////////////////////////////////////////////////////////////
+// Implementation of KFloatValidator
+//
+
+class KFloatValidatorPrivate
+{
+public:
+ KFloatValidatorPrivate()
+ {
+ }
+ ~KFloatValidatorPrivate()
+ {
+ }
+ bool acceptLocalizedNumbers;
+};
+
+
+KFloatValidator::KFloatValidator ( QWidget * parent, const char * name )
+ : QValidator(parent, name)
+{
+ d = new KFloatValidatorPrivate;
+ d->acceptLocalizedNumbers=false;
+ _min = _max = 0;
+}
+
+KFloatValidator::KFloatValidator ( double bottom, double top, QWidget * parent, const char * name )
+ : QValidator(parent, name)
+{
+ d = new KFloatValidatorPrivate;
+ d->acceptLocalizedNumbers=false;
+ _min = bottom;
+ _max = top;
+}
+
+KFloatValidator::KFloatValidator ( double bottom, double top, bool localeAware, QWidget * parent, const char * name )
+ : QValidator(parent, name)
+{
+ d = new KFloatValidatorPrivate;
+ d->acceptLocalizedNumbers = localeAware;
+ _min = bottom;
+ _max = top;
+}
+
+KFloatValidator::~KFloatValidator ()
+{
+ delete d;
+}
+
+void KFloatValidator::setAcceptLocalizedNumbers(bool _b)
+{
+ d->acceptLocalizedNumbers=_b;
+}
+
+bool KFloatValidator::acceptLocalizedNumbers() const
+{
+ return d->acceptLocalizedNumbers;
+}
+
+QValidator::State KFloatValidator::validate ( QString &str, int & ) const
+{
+ bool ok;
+ double val = 0;
+ QString newStr;
+ newStr = str.stripWhiteSpace();
+
+ if (newStr == QString::fromLatin1("-")) // a special case
+ if ((_min || _max) && _min >= 0)
+ ok = false;
+ else
+ return QValidator::Acceptable;
+ else if (newStr == QString::fromLatin1(".") || (d->acceptLocalizedNumbers && newStr==KGlobal::locale()->decimalSymbol())) // another special case
+ return QValidator::Acceptable;
+ else if (newStr.length())
+ {
+ val = newStr.toDouble(&ok);
+ if(!ok && d->acceptLocalizedNumbers)
+ val= KGlobal::locale()->readNumber(newStr,&ok);
+ }
+ else {
+ val = 0;
+ ok = true;
+ }
+
+ if (! ok)
+ return QValidator::Invalid;
+
+ if (( !_min && !_max) || (val >= _min && val <= _max))
+ return QValidator::Acceptable;
+
+ if (_max && _min >= 0 && val < 0)
+ return QValidator::Invalid;
+
+ if ( (_min || _max) && (val < _min || val > _max))
+ return QValidator::Invalid;
+
+ return QValidator::Valid;
+}
+
+void KFloatValidator::fixup ( QString &str ) const
+{
+ int dummy;
+ double val;
+ QValidator::State state;
+
+ state = validate(str, dummy);
+
+ if (state == QValidator::Invalid || state == QValidator::Acceptable)
+ return;
+
+ if (! _min && ! _max)
+ return;
+
+ val = str.toDouble();
+
+ if (val < _min) val = _min;
+ if (val > _max) val = _max;
+
+ str.setNum(val);
+}
+
+void KFloatValidator::setRange ( double bottom, double top )
+{
+ _min = bottom;
+ _max = top;
+
+ if (_max < _min)
+ _max = _min;
+}
+
+double KFloatValidator::bottom () const
+{
+ return _min;
+}
+
+double KFloatValidator::top () const
+{
+ return _max;
+}
+
+
+
+
+///////////////////////////////////////////////////////////////
+// Implementation of KDoubleValidator
+//
+
+class KDoubleValidator::Private {
+public:
+ Private( bool accept=true ) : acceptLocalizedNumbers( accept ) {}
+
+ bool acceptLocalizedNumbers;
+};
+
+KDoubleValidator::KDoubleValidator( QObject * parent, const char * name )
+ : QDoubleValidator( parent, name ), d( 0 )
+{
+ d = new Private();
+}
+
+KDoubleValidator::KDoubleValidator( double bottom, double top, int decimals,
+ QObject * parent, const char * name )
+ : QDoubleValidator( bottom, top, decimals, parent, name ), d( 0 )
+{
+ d = new Private();
+}
+
+KDoubleValidator::~KDoubleValidator()
+{
+ delete d;
+}
+
+bool KDoubleValidator::acceptLocalizedNumbers() const {
+ return d->acceptLocalizedNumbers;
+}
+
+void KDoubleValidator::setAcceptLocalizedNumbers( bool accept ) {
+ d->acceptLocalizedNumbers = accept;
+}
+
+QValidator::State KDoubleValidator::validate( QString & input, int & p ) const {
+ QString s = input;
+ if ( acceptLocalizedNumbers() ) {
+ KLocale * l = KGlobal::locale();
+ // ok, we have to re-format the number to have:
+ // 1. decimalSymbol == '.'
+ // 2. negativeSign == '-'
+ // 3. positiveSign == <empty>
+ // 4. thousandsSeparator() == <empty> (we don't check that there
+ // are exactly three decimals between each separator):
+ QString d = l->decimalSymbol(),
+ n = l->negativeSign(),
+ p = l->positiveSign(),
+ t = l->thousandsSeparator();
+ // first, delete p's and t's:
+ if ( !p.isEmpty() )
+ for ( int idx = s.find( p ) ; idx >= 0 ; idx = s.find( p, idx ) )
+ s.remove( idx, p.length() );
+
+
+ if ( !t.isEmpty() )
+ for ( int idx = s.find( t ) ; idx >= 0 ; idx = s.find( t, idx ) )
+ s.remove( idx, t.length() );
+
+ // then, replace the d's and n's
+ if ( ( !n.isEmpty() && n.find('.') != -1 ) ||
+ ( !d.isEmpty() && d.find('-') != -1 ) ) {
+ // make sure we don't replace something twice:
+ kdWarning() << "KDoubleValidator: decimal symbol contains '-' or "
+ "negative sign contains '.' -> improve algorithm" << endl;
+ return Invalid;
+ }
+
+ if ( !d.isEmpty() && d != "." )
+ for ( int idx = s.find( d ) ; idx >= 0 ; idx = s.find( d, idx + 1 ) )
+ s.replace( idx, d.length(), '.');
+
+ if ( !n.isEmpty() && n != "-" )
+ for ( int idx = s.find( n ) ; idx >= 0 ; idx = s.find( n, idx + 1 ) )
+ s.replace( idx, n.length(), '-' );
+ }
+
+ return base::validate( s, p );
+}
+
+#include "knumvalidator.moc"
diff --git a/kdeui/knumvalidator.h b/kdeui/knumvalidator.h
new file mode 100644
index 000000000..114a82d57
--- /dev/null
+++ b/kdeui/knumvalidator.h
@@ -0,0 +1,212 @@
+/**********************************************************************
+**
+** $Id$
+**
+** Copyright (C) 1999 Glen Parker <glenebob@nwlink.com>
+** Copyright (C) 2002 Marc Mutz <mutz@kde.org>
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Library General Public
+** License as published by the Free Software Foundation; either
+** version 2 of the License, or (at your option) any later version.
+**
+** This library is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** Library General Public License for more details.
+**
+** You should have received a copy of the GNU Library General Public
+** License along with this library; if not, write to the Free
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+**
+*****************************************************************************/
+
+#ifndef __KNUMVALIDATOR_H
+#define __KNUMVALIDATOR_H
+
+#include <qvalidator.h>
+
+#include <kdelibs_export.h>
+
+class QWidget;
+class QString;
+
+/**
+ * QValidator for integers.
+
+ This can be used by QLineEdit or subclass to provide validated
+ text entry. Can be provided with a base value (default is 10), to allow
+ the proper entry of hexadecimal, octal, or any other base numeric data.
+
+ @author Glen Parker <glenebob@nwlink.com>
+ @version 0.0.1
+*/
+class KDEUI_EXPORT KIntValidator : public QValidator {
+
+ public:
+ /**
+ Constuctor. Also sets the base value.
+ */
+ KIntValidator ( QWidget * parent, int base = 10, const char * name = 0 );
+ /**
+ * Constructor. Also sets the minimum, maximum, and numeric base values.
+ */
+ KIntValidator ( int bottom, int top, QWidget * parent, int base = 10, const char * name = 0 );
+ /**
+ * Destructs the validator.
+ */
+ virtual ~KIntValidator ();
+ /**
+ * Validates the text, and return the result. Does not modify the parameters.
+ */
+ virtual State validate ( QString &, int & ) const;
+ /**
+ * Fixes the text if possible, providing a valid string. The parameter may be modified.
+ */
+ virtual void fixup ( QString & ) const;
+ /**
+ * Sets the minimum and maximum values allowed.
+ */
+ virtual void setRange ( int bottom, int top );
+ /**
+ * Sets the numeric base value.
+ */
+ virtual void setBase ( int base );
+ /**
+ * Returns the current minimum value allowed.
+ */
+ virtual int bottom () const;
+ /**
+ * Returns the current maximum value allowed.
+ */
+ virtual int top () const;
+ /**
+ * Returns the current numeric base.
+ */
+ virtual int base () const;
+
+ private:
+ int _base;
+ int _min;
+ int _max;
+
+};
+
+class KFloatValidatorPrivate;
+
+/**
+ \brief QValidator for floating point entry (Obsolete)
+
+ @obsolete Use KDoubleValidator
+
+ Extends the QValidator class to properly validate double numeric data.
+ This can be used by QLineEdit or subclass to provide validated
+ text entry.
+
+ @author Glen Parker <glenebob@nwlink.com>
+ @version 0.0.1
+*/
+class KDEUI_EXPORT KFloatValidator : public QValidator {
+
+ public:
+ /**
+ * Constructor.
+ */
+ KFloatValidator ( QWidget * parent, const char * name = 0 );
+ /**
+ * Constructor. Also sets the minimum and maximum values.
+ */
+ KFloatValidator ( double bottom, double top, QWidget * parent, const char * name = 0 );
+ /**
+ * Constructor. Sets the validator to be locale aware if @p localeAware is true.
+ */
+ KFloatValidator ( double bottom, double top, bool localeAware, QWidget * parent, const char * name = 0 );
+ /**
+ * Destructs the validator.
+ */
+ virtual ~KFloatValidator ();
+ /**
+ * Validates the text, and return the result. Does not modify the parameters.
+ */
+ virtual State validate ( QString &, int & ) const;
+ /**
+ * Fixes the text if possible, providing a valid string. The parameter may be modified.
+ */
+ virtual void fixup ( QString & ) const;
+ /**
+ * Sets the minimum and maximum value allowed.
+ */
+ virtual void setRange ( double bottom, double top );
+ /**
+ * Returns the current minimum value allowed.
+ */
+ virtual double bottom () const;
+ /**
+ * Returns the current maximum value allowed.
+ */
+ virtual double top () const;
+ /**
+ * Sets the validator to be locale aware if @p is true. In this case, the
+ * character KLocale::decimalSymbol() from the global locale is recognized
+ * as decimal separator.
+ */
+ void setAcceptLocalizedNumbers(bool b);
+ /**
+ * Returns true if the validator is locale aware.
+ * @see setAcceptLocalizedNumbers().
+ */
+ bool acceptLocalizedNumbers() const;
+
+ private:
+ double _min;
+ double _max;
+
+ KFloatValidatorPrivate *d;
+};
+
+/**
+ @short A locale-aware QDoubleValidator
+
+ KDoubleValidator extends QDoubleValidator to be
+ locale-aware. That means that - subject to not being disabled -
+ KLocale::decimalSymbol(), KLocale::thousandsSeparator()
+ and KLocale::positiveSign() and KLocale::negativeSign()
+ are respected.
+
+ @author Marc Mutz <mutz@kde.org>
+ @see KIntValidator
+ @since 3.1
+**/
+
+class KDEUI_EXPORT KDoubleValidator : public QDoubleValidator {
+ Q_OBJECT
+ Q_PROPERTY( bool acceptLocalizedNumbers READ acceptLocalizedNumbers WRITE setAcceptLocalizedNumbers )
+public:
+ /** Constuct a locale-aware KDoubleValidator with default range
+ (whatever QDoubleValidator uses for that) and parent @p
+ parent */
+ KDoubleValidator( QObject * parent, const char * name=0 );
+ /** Constuct a locale-aware KDoubleValidator for range [@p bottom,@p
+ top] and a precision of @p decimals decimals after the decimal
+ point. */
+ KDoubleValidator( double bottom, double top, int decimals,
+ QObject * parent, const char * name=0 );
+ /** Destructs the validator.
+ */
+ virtual ~KDoubleValidator();
+
+ /** Overloaded for internal reasons. The API is not affected. */
+ virtual QValidator::State validate( QString & input, int & pos ) const;
+
+ /** @return whether localized numbers are accepted (default: true) */
+ bool acceptLocalizedNumbers() const;
+ /** Sets whether to accept localized numbers (default: true) */
+ void setAcceptLocalizedNumbers( bool accept );
+
+private:
+ typedef QDoubleValidator base;
+ class Private;
+ Private * d;
+};
+
+#endif
diff --git a/kdeui/kpanelapplet.cpp b/kdeui/kpanelapplet.cpp
new file mode 100644
index 000000000..1536e974d
--- /dev/null
+++ b/kdeui/kpanelapplet.cpp
@@ -0,0 +1,198 @@
+/*****************************************************************
+
+Copyright (c) 2000 Matthias Elter
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qptrlist.h>
+
+#include "kpanelapplet.h"
+#include "kpanelapplet.moc"
+#include <kapplication.h>
+#include <kconfig.h>
+
+class KPanelApplet::KPanelAppletPrivate
+{
+public:
+ KPanelAppletPrivate()
+ : customMenu(0),
+ hasFocus(false)
+ {}
+
+ const QPopupMenu* customMenu;
+ KSharedConfig::Ptr sharedConfig;
+ QPtrList<QObject> watchedForFocus;
+ bool hasFocus;
+};
+
+KPanelApplet::KPanelApplet(const QString& configFile, Type type,
+ int actions, QWidget *parent, const char *name, WFlags f)
+ : QFrame(parent, name, f)
+ , _type(type)
+ , _position( pBottom )
+ , _alignment( LeftTop )
+ , _config(0)
+ , _actions(actions)
+ , d(new KPanelApplet::KPanelAppletPrivate())
+{
+ setFrameStyle(NoFrame);
+ QPalette pal(palette());
+ if(pal.active().mid() != pal.inactive().mid()){
+ pal.setInactive(pal.active());
+ setPalette(pal);
+ }
+ setBackgroundOrigin( AncestorOrigin );
+
+ d->sharedConfig = KSharedConfig::openConfig(configFile, kapp && kapp->config()->isImmutable());
+ _config = d->sharedConfig;
+}
+
+KPanelApplet::~KPanelApplet()
+{
+ d->watchedForFocus.clear();
+ needsFocus(false);
+ delete d;
+}
+
+void KPanelApplet::setPosition( Position p )
+{
+ if( _position == p ) return;
+ _position = p;
+ positionChange( p );
+}
+
+void KPanelApplet::setAlignment( Alignment a )
+{
+ if( _alignment == a ) return;
+ _alignment = a;
+ alignmentChange( a );
+}
+
+// FIXME: Remove implementation for KDE 4
+void KPanelApplet::positionChange( Position )
+{
+ orientationChange( orientation() );
+ QResizeEvent e( size(), size() );
+ resizeEvent( &e );
+ popupDirectionChange( popupDirection() );
+}
+
+Qt::Orientation KPanelApplet::orientation() const
+{
+ if( _position == pTop || _position == pBottom ) {
+ return Horizontal;
+ } else {
+ return Vertical;
+ }
+}
+
+// FIXME: Remove for KDE 4
+KPanelApplet::Direction KPanelApplet::popupDirection()
+{
+ switch( _position ) {
+ case pTop: return Down;
+ case pRight: return Left;
+ case pLeft: return Right;
+ default:
+ case pBottom: return Up;
+ }
+}
+
+void KPanelApplet::action( Action a )
+{
+ if ( (a & About) )
+ about();
+ if ( (a & Help) )
+ help();
+ if ( (a & Preferences) )
+ preferences();
+ if ( (a & ReportBug) )
+ reportBug();
+}
+
+const QPopupMenu* KPanelApplet::customMenu() const
+{
+ return d->customMenu;
+}
+
+void KPanelApplet::setCustomMenu(const QPopupMenu* menu)
+{
+ d->customMenu = menu;
+}
+
+void KPanelApplet::watchForFocus(QWidget* widget, bool watch)
+{
+ if (!widget)
+ {
+ return;
+ }
+
+ if (watch)
+ {
+ if (d->watchedForFocus.find(widget) == -1)
+ {
+ d->watchedForFocus.append(widget);
+ widget->installEventFilter(this);
+ }
+ }
+ else if (d->watchedForFocus.find(widget) != -1)
+ {
+ d->watchedForFocus.remove(widget);
+ widget->removeEventFilter(this);
+ }
+}
+
+void KPanelApplet::needsFocus(bool focus)
+{
+ if (focus == d->hasFocus)
+ {
+ return;
+ }
+
+ d->hasFocus = focus;
+ emit requestFocus(focus);
+}
+
+bool KPanelApplet::eventFilter(QObject *o, QEvent * e)
+{
+ if (d->watchedForFocus.find(o) != -1)
+ {
+ if (e->type() == QEvent::MouseButtonRelease ||
+ e->type() == QEvent::FocusIn)
+ {
+ needsFocus(true);
+ }
+ else if (e->type() == QEvent::FocusOut)
+ {
+ needsFocus(false);
+ }
+ }
+
+ return QFrame::eventFilter(o, e);
+}
+
+KSharedConfig::Ptr KPanelApplet::sharedConfig() const
+{
+ return d->sharedConfig;
+}
+
+void KPanelApplet::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
diff --git a/kdeui/kpanelapplet.h b/kdeui/kpanelapplet.h
new file mode 100644
index 000000000..fa0d3adbb
--- /dev/null
+++ b/kdeui/kpanelapplet.h
@@ -0,0 +1,395 @@
+/*****************************************************************
+
+Copyright (c) 2000 Matthias Elter
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __kpanelapplet_h__
+#define __kpanelapplet_h__
+
+class KConfig;
+class QPopupMenu;
+
+#include <qframe.h>
+#include <kconfig.h>
+
+/**
+ * @short %KDE Panel Applet class
+ *
+ * Panel applets
+ * @li Are small applications living in the %KDE panel.
+ * @li Are implemented as DSOs (Dynamic Shared Objects).
+ *
+ * Note: For security and stability reasons the panel won't load
+ * untrusted third party applets directly into its namespace but via an
+ * external wrapper process.
+ *
+ * The panel locates available applets by searching for applet desktop
+ * files in (ALL_DIRS)/share/apps/kicker/applets. Every panel applet should
+ * install a desktop file there to be recognized by the panel.
+ *
+ * Besides standard keys like "Name", "Comment" and "Icon" there are
+ * two panel applet specific keys:
+ *
+ * \b X-KDE-Library \n
+ *
+ * Used by the panel to locate the applet DSO (Dynamic Shared Object)
+ * Example: X-KDE-Library=libexampleapplet
+ *
+ * \b X-KDE-UniqueApplet \n
+ *
+ * Similar to KApplication and KUniqueApplication there are
+ * two types of panel applets. Use unique applets when it makes no
+ * sence to run more than one instance of a applet in the panel. A
+ * good example for unique applets is the taskbar applet. Use normal
+ * applets when you need instance specific configuration. An example
+ * is the koolclock applet where you might want to run two instances
+ * in your panel, one configured as analog clock, the other one as
+ * digital clock. X-KDE-UniqueApplet is a boolean key which defaults
+ * to "false". Example: X-KDE-UniqueApplet=true
+ *
+ * Back to panel applet DSOs, the following conventions are used for %KDE:
+ * Name: lib<appletname>applet.la
+ * LDFLAGS: -module -no-undefined
+ *
+ * To implement a panel applet it is not enough to write a class
+ * inheriting from KPanelApplet but you also have to provide a
+ * factory function in your DSO. A sample factory function could look
+ * like this:
+ *
+ * \code
+ *
+ * extern "C"
+ * {
+ * KPanelApplet* init(QWidget *parent, const QString& configFile)
+ * {
+ * KGlobal::locale()->insertCatalogue("exampleapplet");
+ * return new ExampleApplet(configFile, KPanelApplet::Normal,
+ * KPanelApplet::About | KPanelApplet::Help | KPanelApplet::Preferences,
+ * parent, "exampleapplet");
+ * }
+ * }
+ *
+ * \endcode
+ *
+ * Note: Don't change the factory function signature or the panel will
+ * fail to load your applet.
+ *
+ * @author Matthias Elter <elter@kde.org>
+ **/
+class KDEUI_EXPORT KPanelApplet : public QFrame
+{
+ Q_OBJECT
+
+public:
+
+ /**
+ * This enum describes the type of the applet.
+ */
+ enum Type { Normal = 0, Stretch };
+ /**
+ * This enum holds flags which can be ORed together to describe
+ * which items the context menu over the applet handle contains.
+ */
+ // KDE4: Merge these with KPanelExtension's enums
+ enum Action { About = 1, Help = 2, Preferences = 4, ReportBug = 8 };
+ enum Position { pLeft = 0, pRight, pTop, pBottom };
+ enum Alignment { LeftTop = 0, Center, RightBottom };
+ enum Direction { Up = 0, Down, Left, Right };
+
+ /**
+ * Constructs a KPanelApplet just like any other widget.
+ *
+ * @param configFile The configFile handed over in the factory function.
+ * @param t The applet type().
+ * @param actions Standard RMB menu actions supported by the applet (see action() ).
+ * @param parent The pointer to the parent widget handed over in the factory function.
+ * @param name A Qt object name for your applet.
+ * @param f Window control flags
+ **/
+ KPanelApplet(const QString& configFile, Type t = Normal,
+ int actions = 0, QWidget *parent = 0, const char *name = 0,
+ WFlags f = 0);
+
+ /**
+ * Destructor.
+ **/
+ ~KPanelApplet();
+
+ /**
+ * Returns a suggested width for a given height.
+ *
+ * Every applet should reimplement this function.
+ *
+ * Depending on the panel orientation the height (horizontal panel) or the
+ * width (vertical panel) of the applets is fixed.
+ * The exact values of the fixed size component depend on the panel size.
+ *
+ * On a horizontal panel the applet height is fixed, the panel will
+ * call widthForHeight(int height) with @p height
+ * equal to 'the fixed applet height'
+ * when laying out the applets.
+ *
+ * The applet can now choose the other size component (width)
+ * based on the given height.
+ *
+ * The width you return is granted.
+ **/
+ virtual int widthForHeight(int height) const { return height; }
+
+ /**
+ * @return A suggested height for a given width.
+ *
+ * Every applet should reimplement this function.
+ *
+ * Depending on the panel orientation the height (horizontal panel) or the
+ * width (vertical panel) of the applets is fixed.
+ * The exact values of the fixed size component depend on the panel size.
+ *
+ * On a vertical panel the applet width is fixed, the panel will
+ * call heightForWidth(int width) with @p width
+ * equal to 'the fixed applet width'
+ * when laying out the applets.
+ *
+ * The applet can now choose the other size component (height)
+ * based on the given width.
+ *
+ * The height you return is granted.
+ **/
+ virtual int heightForWidth(int width) const { return width; }
+
+ /**
+ * Always use this KConfig object to save/load your applet's configuration.
+ *
+ * For unique applets this config object will write to a config file called
+ * \<appletname\>rc in the user's local %KDE directory.
+ *
+ * For normal applets this config object will write to a instance specific config file
+ * called \<appletname\>\<instanceid\>rc in the user's local %KDE directory.
+ **/
+ KConfig* config() const { return _config; }
+ KSharedConfig::Ptr sharedConfig() const;
+
+ /**
+ * @return Type indicating the applet's type.
+ * Type
+ **/
+ Type type() const { return _type; }
+
+ /**
+ * @return int indicating the supported RMB menu actions.
+ * Action
+ **/
+ int actions() const { return _actions; }
+
+ /**
+ * Generic action dispatcher. Called when the user selects an item
+ * from the applet's RMB menu.
+ *
+ * Reimplement this function to handle actions.
+ *
+ * For About, Help, Preferences and ReportBug, use the convenience handlers
+ * ref about(), help(), preferences(), reportBug()
+ *
+ **/
+ virtual void action( Action a );
+
+ /**
+ * @return the applet's custom menu, usually the same as the context menu, or 0 if none
+ * see setCustomMenu(QPopupMenu*)
+ */
+ const QPopupMenu* customMenu() const;
+
+ /**
+ * @internal
+ **/
+ void setPosition( Position p );
+ /**
+ * @internal
+ **/
+ void setAlignment( Alignment a );
+
+signals:
+ /**
+ * Emit this signal to make the panel relayout all applets, when
+ * you want to change your width (horizontal panel) or
+ * height (vertical panel).
+ *
+ * The panel is going to relayout all applets based on their
+ * widthForHeight(int height) (horizontal panel) or
+ * heightForWidth(int width) (vertical panel).
+ *
+ * Please note that the panel may change the applet's location
+ * if the new widthForHeight(int height) (horizontal panel) or
+ * heightForWidth(int width) (vertical panel) does not fit into the
+ * current panel layout.
+ **/
+ void updateLayout();
+
+ /**
+ * Request keyboard focus from the panel.
+ * @deprecated
+ **/
+ void requestFocus();
+
+ /**
+ * Request keyboard focus from the panel. Applets should never call this directly
+ * but rather call needsFocus(bool)
+ * @see needsFocus
+ * @param focus activate the window and ensure the panel remains visible when true
+ * Each and ever time a requestFocus(true) is emitted, it MUST be paired eventually
+ * with a requestFocus(false) otherwise the panel may end up never hiding
+ * @since 3.4
+ **/
+ void requestFocus(bool focus);
+
+protected:
+
+ /**
+ * Is called when the user selects "About" from the applet's RMB menu.
+ * Reimplement this function to launch a about dialog.
+ *
+ * Note that this is called only when your applet supports the About action.
+ * See Action and KPanelApplet().
+ **/
+ virtual void about() {}
+
+ /**
+ * Is called when the user selects "Help" from the applet's RMB menu.
+ * Reimplement this function to launch a manual or help page.
+ *
+ * Note that this is called only when your applet supports the Help action.
+ * See Action and KPanelApplet().
+ **/
+ virtual void help() {}
+
+ /**
+ * Is called when the user selects "Preferences" from the applet's RMB menu.
+ * Reimplement this function to launch a preferences dialog or kcontrol module.
+ *
+ * Note that this is called only when your applet supports the preferences action.
+ * See Action and KPanelApplet().
+ **/
+ virtual void preferences() {}
+
+ /**
+ * Is called when the user selects "Report bug" from the applet's RMB menu.
+ * Reimplement this function to launch a bug reporting dialog.
+ *
+ * Note that this is called only when your applet supports the ReportBug
+ * action.
+ * See Action and KPanelApplet()
+ **/
+ virtual void reportBug() {}
+
+ /**
+ * @return the applet's orientation. (horizontal or vertical)
+ **/
+ Orientation orientation() const;
+ /**
+ * @return the applet's position. (top, left, bottom, or right)
+ **/
+ Position position() const { return _position; }
+ /**
+ * @return the applet's alignment. (top/left, center, or bottom/right)
+ **/
+ Alignment alignment() const { return _alignment; }
+
+ /**
+ * The panel on which this applet resides has changed its position.
+ * Reimplement this change handler in order to adjust the look of your
+ * applet.
+ **/
+ virtual void positionChange( Position p );
+
+ /**
+ * The panel on which this applet resides has changed its alignment.
+ * Reimplement this change handler in order to adjust the look of your
+ * applet.
+ **/
+ virtual void alignmentChange( Alignment /*a*/ ) {}
+
+ /**
+ * Use this method to set the custom menu for this applet so that it can be shown
+ * in the applet handle menu and other appropriate places that the applet many not itself
+ * be aware of. The applet itself is still responsible for deleting and managing the
+ * the menu.
+ *
+ * If the menu is deleted during the life of the applet, be sure to call this method again
+ * with the new menu (or 0) to avoid crashes
+ */
+ void setCustomMenu(const QPopupMenu*);
+
+ /**
+ * Register widgets that can receive keyboard focus with this this method
+ * This call results in an eventFilter being places on the widget.
+ * @param widget the widget to watch for keyboard focus
+ * @param watch whether to start watching the widget, or to stop doing so
+ * @since 3.4
+ */
+ void watchForFocus(QWidget* widget, bool watch = true);
+
+ /**
+ * Call this whenever focus is needed or not needed. You do not have to call this method
+ * for widgets that have been registered with watchForFocus
+ * @param focus whether to or not to request focus
+ * @since 3.4
+ */
+ void needsFocus(bool focus);
+
+ /**
+ * The orientation changed to @p orientation. Reimplement this
+ * change handler in order to adjust the look of your applet.
+ *
+ * @deprecated Reimplement positionChange instead.
+ **/
+ // FIXME: Remove for KDE 4
+ virtual KDE_DEPRECATED void orientationChange( Orientation /* orientation*/) {}
+
+ /**
+ * A convenience method that translates the position of the applet into which
+ * direction to show a popup.
+ **/
+ Direction popupDirection();
+
+ /**
+ * The popup direction changed to @p direction. Reimplement this
+ * change handler in order to adjust the look of your applet.
+ *
+ * @deprecated Reimplement positionChange instead.
+ **/
+ // FIXME: Remove for KDE 4
+ virtual KDE_DEPRECATED void popupDirectionChange( Direction /*direction*/ ) {}
+
+ bool eventFilter(QObject *, QEvent *);
+
+private:
+ Type _type;
+ Position _position;
+ Alignment _alignment;
+ KConfig* _config;
+ int _actions;
+protected:
+ virtual void virtual_hook( int id, void* data );
+ class KPanelAppletPrivate;
+ KPanelAppletPrivate *d;
+};
+
+#endif
diff --git a/kdeui/kpanelappmenu.cpp b/kdeui/kpanelappmenu.cpp
new file mode 100644
index 000000000..dd9f01120
--- /dev/null
+++ b/kdeui/kpanelappmenu.cpp
@@ -0,0 +1,182 @@
+/*
+
+(C) Daniel M. Duley <mosfet@kde.org>
+(C) Matthias Ettrich <ettrich@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include "kpanelappmenu.h"
+#include <qstringlist.h>
+#include <dcopclient.h>
+#include <kapplication.h>
+#include <kdebug.h>
+
+static int panelmenu_get_seq_id()
+{
+ static int panelmenu_seq_no = -2;
+ return panelmenu_seq_no--;
+}
+
+
+KPanelAppMenu::KPanelAppMenu(const QString &title, QObject *parent,
+ const char *name)
+ : QObject(parent, name), DCOPObject()
+{
+ init(QString::null, title);
+}
+
+KPanelAppMenu::KPanelAppMenu(const QPixmap &icon, const QString &title,
+ QObject *parent, const char *name)
+: QObject(parent, name), DCOPObject()
+{
+
+ init(icon, title);
+}
+
+
+KPanelAppMenu::KPanelAppMenu(QObject *parent, const char *name)
+ : QObject(parent, name), DCOPObject(name)
+{
+ realObjId = name;
+}
+
+
+void KPanelAppMenu::init(const QPixmap &icon, const QString &title)
+{
+ DCOPClient *client = kapp->dcopClient();
+ if(!client->isAttached())
+ client->attach();
+ QByteArray sendData, replyData;
+ QCString replyType;
+ {
+ QDataStream stream(sendData, IO_WriteOnly);
+ stream << icon << title;
+ if ( client->call("kicker", "kickerMenuManager", "createMenu(QPixmap,QString)", sendData, replyType, replyData ) ) {
+ if (replyType != "QCString")
+ kdDebug() << "error! replyType for createMenu should be QCstring in KPanelAppMenu::init" << endl;
+ else {
+ QDataStream reply( replyData, IO_ReadOnly );
+ reply >> realObjId;
+ }
+ }
+ }
+ {
+ QDataStream stream(sendData, IO_WriteOnly);
+ stream << QCString("activated(int)") << client->appId() << objId();
+ client->send("kicker", realObjId, "connectDCOPSignal(QCString,QCString,QCString)", sendData);
+ }
+}
+
+KPanelAppMenu::~KPanelAppMenu()
+{
+ DCOPClient *client = kapp->dcopClient();
+ QByteArray sendData;
+ QDataStream stream(sendData, IO_WriteOnly);
+ stream << realObjId;
+ client->send("kicker", "kickerMenuManager", "removeMenu", sendData );
+}
+
+int KPanelAppMenu::insertItem(const QPixmap &icon, const QString &text, int id )
+{
+ if ( id < 0 )
+ id = panelmenu_get_seq_id();
+ DCOPClient *client = kapp->dcopClient();
+ QByteArray sendData;
+ QDataStream stream(sendData, IO_WriteOnly);
+ stream << icon << text << id;
+ client->send("kicker", realObjId, "insertItem(QPixmap,QString,int)", sendData );
+ return id;
+}
+
+
+KPanelAppMenu *KPanelAppMenu::insertMenu(const QPixmap &icon, const QString &text, int id )
+{
+ if ( id < 0 )
+ id = panelmenu_get_seq_id();
+ DCOPClient *client = kapp->dcopClient();
+ QByteArray sendData, replyData;
+ QCString replyType;
+ QDataStream stream(sendData, IO_WriteOnly);
+ stream << icon << text << id;
+ client->call("kicker", realObjId, "insertMenu(QPixmap,QString,int)", sendData, replyType, replyData );
+ if ( replyType != "QCString")
+ return 0;
+ QDataStream ret(replyData, IO_ReadOnly);
+ QCString subid;
+ ret >> subid;
+
+ QByteArray sendData2;
+ QDataStream stream2(sendData2, IO_WriteOnly);
+ stream2 << QCString("activated(int)") << client->appId() << subid;
+ client->send("kicker", subid, "connectDCOPSignal(QCString,QCString,QCString)", sendData2);
+
+ return new KPanelAppMenu(this, subid);
+}
+
+
+int KPanelAppMenu::insertItem(const QString &text, int id )
+{
+ if ( id < 0 )
+ id = panelmenu_get_seq_id();
+ DCOPClient *client = kapp->dcopClient();
+ QByteArray sendData;
+ QDataStream stream(sendData, IO_WriteOnly);
+ stream << text << id;
+ client->send("kicker", realObjId, "insertItem(QString,int)", sendData );
+ return id;
+}
+
+
+void KPanelAppMenu::clear()
+{
+ DCOPClient *client = kapp->dcopClient();
+ QByteArray sendData;
+ client->send("kicker", realObjId, "clear()", sendData);
+}
+
+
+bool KPanelAppMenu::process(const QCString &fun, const QByteArray &data,
+ QCString &replyType, QByteArray &)
+{
+ if ( fun == "activated(int)" ) {
+ QDataStream dataStream( data, IO_ReadOnly );
+ int id;
+ dataStream >> id;
+ emit activated( id );
+ replyType = "void";
+ return true;
+ }
+ return false;
+}
+
+
+#include "kpanelappmenu.moc"
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/kdeui/kpanelappmenu.h b/kdeui/kpanelappmenu.h
new file mode 100644
index 000000000..2cb9adc1f
--- /dev/null
+++ b/kdeui/kpanelappmenu.h
@@ -0,0 +1,99 @@
+/*
+
+(C) Daniel M. Duley <mosfet@kde.org>
+(C) Matthias Ettrich <ettrich@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+#ifndef __PANELAPPMENU_H
+#define __PANELAPPMENU_H "$Id$"
+
+#include <dcopobject.h>
+
+
+/**
+ * DCop client menu class for the Kicker panel that will insert a submenu into
+ * the %KDE menu.
+ *
+ * @author Daniel M. Duley <mosfet@kde.org>
+ */
+class KDEUI_EXPORT KPanelAppMenu : public QObject, public DCOPObject
+{
+ Q_OBJECT
+public:
+ /**
+ * Constructs a new menu with the given title.
+ */
+ KPanelAppMenu(const QString &title, QObject *parent = 0, const char *name = 0 );
+ /**
+ * Same as above, but with an icon for the submenu item.
+ */
+ KPanelAppMenu(const QPixmap &icon, const QString &title, QObject *parent,
+ const char *name);
+ /**
+ * Constructs a new (sub)menu with a given id.
+ */
+ KPanelAppMenu(QObject *parent, const char *name);
+
+ /**
+ * Make sure you actually destroy this thing or the menu will never go
+ * away until this application quits or Kicker restarts ;-)
+ */
+ ~KPanelAppMenu();
+
+ /**
+ * Inserts an item into the menu.
+ */
+ int insertItem(const QString &text, int id = -1);
+ /**
+ * Inserts an item with a icon. The icon name must be a full path.
+ */
+ int insertItem(const QPixmap &icon, const QString &text, int id = -1 );
+ /**
+ * Inserts a sub menu with a icon. The icon name must be a full path.
+ */
+ KPanelAppMenu *insertMenu(const QPixmap &icon, const QString &text, int id=-1);
+
+ /**
+ * Clears the menu.
+ */
+ void clear();
+
+ /**
+ * @internal
+ */
+ bool process(const QCString &fun, const QByteArray &data,
+ QCString &replyType, QByteArray &replyData);
+
+signals:
+ /**
+ * Emitted when the user selects an item from the Kicker menu.
+ */
+ void activated(int id);
+
+protected:
+ void init(const QPixmap &icon, const QString &title);
+
+private:
+ QCString realObjId;
+};
+
+
+#endif
diff --git a/kdeui/kpanelextension.cpp b/kdeui/kpanelextension.cpp
new file mode 100644
index 000000000..190540f70
--- /dev/null
+++ b/kdeui/kpanelextension.cpp
@@ -0,0 +1,163 @@
+/*****************************************************************
+
+Copyright (c) 2000 Matthias Elter
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qpopupmenu.h>
+
+#include <kconfig.h>
+
+#include "kpanelextension.h"
+#include "kpanelextension.moc"
+
+class KPanelExtensionPrivate
+{
+public:
+ KPanelExtensionPrivate()
+ : _size(KPanelExtension::SizeNormal),
+ _customMenu(0),
+ _customSize(58),
+ _reserveStrut(true)
+ {}
+
+ KPanelExtension::Size _size;
+ QPopupMenu* _customMenu;
+ int _customSize;
+ bool _reserveStrut;
+};
+
+KPanelExtension::KPanelExtension(const QString& configFile, Type type,
+ int actions, QWidget *parent, const char *name)
+ : QFrame(parent, name)
+ , _type(type)
+ , _position( Top )
+ , _alignment( LeftTop )
+ , _config(0)
+ , _actions(actions)
+{
+ d = new KPanelExtensionPrivate;
+ setFrameStyle(NoFrame);
+ _config = new KConfig(configFile);
+}
+
+KPanelExtension::~KPanelExtension()
+{
+ delete _config;
+ delete d;
+}
+
+void KPanelExtension::setPosition( Position p )
+{
+ if( _position == p ) return;
+ _position = p;
+ positionChange( p );
+}
+
+void KPanelExtension::setAlignment( Alignment a )
+{
+ if( _alignment == a ) return;
+ _alignment = a;
+ alignmentChange( a );
+}
+
+void KPanelExtension::setSize( Size size, int customSize )
+{
+ if ( d->_size == size && d->_customSize == customSize ) return;
+ d->_size = size;
+ d->_customSize = customSize;
+ emit updateLayout();
+}
+
+void KPanelExtension::action( Action a )
+{
+ if ( (a & About) )
+ about();
+ if ( (a & Help) )
+ help();
+ if ( (a & Preferences) )
+ preferences();
+ if ( (a & ReportBug) )
+ reportBug();
+}
+
+Qt::Orientation KPanelExtension::orientation()
+{
+ if (_position == Left || _position == Right)
+ return Vertical;
+ else
+ return Horizontal;
+}
+
+KPanelExtension::Size KPanelExtension::sizeSetting() const
+{
+ return d->_size;
+}
+
+int KPanelExtension::customSize() const
+{
+ return d->_customSize;
+}
+
+int KPanelExtension::sizeInPixels() const
+{
+ if (d->_size == SizeTiny)
+ {
+ return 24;
+ }
+ else if (d->_size == SizeSmall)
+ {
+ return 30;
+ }
+ else if (d->_size == SizeNormal)
+ {
+ return 46;
+ }
+ else if (d->_size == SizeLarge)
+ {
+ return 58;
+ }
+
+ return d->_customSize;
+}
+
+QPopupMenu* KPanelExtension::customMenu() const
+{
+ return d->_customMenu;
+}
+
+void KPanelExtension::setCustomMenu(QPopupMenu* menu)
+{
+ d->_customMenu = menu;
+}
+
+bool KPanelExtension::reserveStrut() const
+{
+ return position() == Floating || d->_reserveStrut;
+}
+
+void KPanelExtension::setReserveStrut(bool reserve)
+{
+ d->_reserveStrut = reserve;
+}
+
+void KPanelExtension::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
diff --git a/kdeui/kpanelextension.h b/kdeui/kpanelextension.h
new file mode 100644
index 000000000..2ff1a5133
--- /dev/null
+++ b/kdeui/kpanelextension.h
@@ -0,0 +1,346 @@
+/*****************************************************************
+
+Copyright (c) 2000 Matthias Elter
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __kpanelextension_h__
+#define __kpanelextension_h__
+
+class QPopupMenu;
+class KConfig;
+class KPanelExtensionPrivate;
+
+#include <qframe.h>
+
+#include <kdelibs_export.h>
+
+/**
+ * @short %KDE Panel Extension class
+ *
+ * Panel extensions
+ * @li Are small applications living in the Window Manager dock managed by the panel.
+ * @li Are implemented as DSOs (Dynamic Shared Objects).
+ *
+ * Note: For security and stability reasons the panel won't load
+ * untrusted third party extensions directly into its namespace but via an
+ * external wrapper process.
+ *
+ * The panel locates available extensions by searching for extension desktop
+ * files in (ALL_KDEDIRS)/share/apps/kicker/extensions. Every panel extension should
+ * install a desktop file there to be recognized by the panel.
+ *
+ * Besides standard keys like "Name", "Comment" and "Icon" there are
+ * two panel extension specific keys:
+ *
+ * \b X-KDE-Library \n
+ *
+ * Used by the panel to locate the extension DSO (Dynamic Shared Object)
+ * Example: X-KDE-Library=libexampleextension
+ *
+ * \b X-KDE-UniqueExtension \n
+ *
+ * Similar to KApplication and KUniqueApplication there are
+ * two types of panel extensions. Use unique extensions when it makes no
+ * sence to run more than one instance of an extension in the panel. A
+ * good example for unique extensions is the taskbar extension. Use normal
+ * extensions when you need instance specific configuration. An example
+ * is a subpanel extension where you might want to run more than one instances.
+ * X-KDE-UniqueExtension is a boolean key which defaults
+ * to "false". Example: X-KDE-UniqueExtension=true
+ *
+ * Back to panel extension DSOs, the following conventions are used for KDE:
+ * Name: lib<extensionname>extension.la
+ * LDFLAGS: -module -no-undefined
+ *
+ * To implement a panel extension it is not enough to write a class
+ * inheriting from KPanelExtension but you also have to provide a
+ * factory function in your DSO. A sample factory function could look
+ * like this:
+ *
+ * \code
+ *
+ * extern "C"
+ * {
+ * KPanelExtension* init(QWidget *parent, const QString& configFile)
+ * {
+ * KGlobal::locale()->insertCatalogue("exampleextension");
+ * return new ExampleExtension(configFile, KPanelExtension::Normal,
+ * KPanelExtension::About | KPanelExtension::Help | KPanelExtension::Preferences,
+ * parent, "exampleextension");
+ * }
+ * }
+ *
+ * \endcode
+ *
+ * Note: Don't change the factory function signature or the panel will
+ * fail to load your extension.
+ *
+ * @author Matthias Elter <elter@kde.org>
+ **/
+class KDEUI_EXPORT KPanelExtension : public QFrame
+{
+ Q_OBJECT
+
+public:
+
+ /// The type of the extension (TODO)
+ enum Type { Normal = 0, Stretch };
+ // KDE4: Merge these with KPanelApplet's enums
+ /// An action to be taken sometime.
+ enum Action { About = 1, Help = 2, Preferences = 4, ReportBug = 8 };
+ enum Position { Left = 0, Right, Top, Bottom, Floating };
+ enum Alignment { LeftTop = 0, Center, RightBottom };
+ /// @since 3.1
+ enum Size { SizeTiny = 0, SizeSmall, SizeNormal, SizeLarge, SizeCustom };
+
+ /**
+ * Constructs a KPanelExtension just like any other widget.
+ *
+ * @param configFile The configFile handed over in the factory function.
+ * @param t The extension type().
+ * @param actions Standard RMB menu actions supported by the extension (see action() ).
+ * @param parent The pointer to the parent widget handed over in the factory function.
+ * @param name A Qt object name for your extension.
+ **/
+ KPanelExtension(const QString& configFile, Type t = Normal,
+ int actions = 0, QWidget *parent = 0, const char *name = 0);
+
+ /**
+ * Destructor.
+ **/
+ ~KPanelExtension();
+
+ /**
+ * Returns the preferred size for a given Position.
+ *
+ * Every extension should reimplement this function.
+ *
+ * Depending on the panel position the extensions can choose a preferred size for that
+ * location in the Window Manager Dock. Please note that the size can not be larger than the
+ * maxsize given by the handler.
+ **/
+ virtual QSize sizeHint(Position /*p*/, QSize maxsize) const { return maxsize; }
+
+ /**
+ * Always use this KConfig object to save/load your extensions configuration.
+ *
+ * For unique extensions this config object will write to a config file called
+ * \<extensionname\>rc in the users local KDE directory.
+ *
+ * For normal extensions this config object will write to a instance specific config file
+ * called \<extensionname\>\<instanceid\>rc in the users local KDE directory.
+ **/
+ KConfig* config() const { return _config; }
+
+ /**
+ * @return Type indicating the extensions type.
+ * Type
+ **/
+ Type type() const { return _type; }
+
+ /**
+ * @return int indicating the supported RMB menu actions.
+ * Action
+ **/
+ int actions() const { return _actions; }
+
+ /**
+ * Generic action dispatcher. Called when the user selects an item
+ * from the extensions RMB menu.
+ *
+ * Reimplement this function to handle actions.
+ *
+ * For About, Help, Preferences and ReportBug use the convenience handlers
+ * ref about(), help(), preferences(), reportBug()
+ *
+ **/
+ virtual void action( Action a );
+
+
+ /**
+ * Reimplement this function to set a preferred dock position for your extension.
+ * The extension manager will try to place new instances of this extension according
+ * to this setting.
+ * @return Position
+ **/
+ virtual Position preferedPosition() const { return Bottom; }
+
+ /**
+ * @internal
+ **/
+ void setPosition( Position p );
+ /**
+ * @internal
+ **/
+ void setAlignment( Alignment a );
+ /**
+ * @internal
+ * @since 3.1
+ **/
+ void setSize( Size size, int customSize );
+
+ /**
+ * @return the extension's size
+ * @since 3.1
+ **/
+ Size sizeSetting() const;
+
+ /**
+ * @return the custom sizel setting in pixels
+ * @since 3.1
+ **/
+ int customSize() const;
+
+ /**
+ * @return the extension's custom menu, usually the same as the context menu, or 0 if none
+ * @see setCustomMenu(QPopupMenu*)
+ * @since 3.4
+ */
+ QPopupMenu* customMenu() const;
+
+ /**
+ * @return whether or not to set a desktop geometry claiming strut for this panel
+ * defaults to true
+ * @see setReservetrut(bool)
+ * @since 3.4
+ */
+ bool reserveStrut() const;
+
+signals:
+ /**
+ * Emit this signal to make the panel relayout all extensions in the dock, when you want
+ * to change the extensions size.
+ * The panel is going to relayout all extensions based on their preferred size.
+ **/
+ void updateLayout();
+
+ /**
+ * Emit this signal to make the panel maintain focus, e.g. don't autohide
+ * @since 3.4
+ **/
+ void maintainFocus(bool);
+
+protected:
+
+ /**
+ * Is called when the user selects "About" from the extensions RMB menu.
+ * Reimplement this function to launch a about dialog.
+ *
+ * Note that this is called only when your extension supports the About action.
+ * See Action.
+ **/
+ virtual void about() {}
+
+ /**
+ * Is called when the user selects "Help" from the extensions RMB menu.
+ * Reimplement this function to launch a manual or help page.
+ *
+ * Note that this is called only when your extension supports the Help action.
+ * See Action.
+ **/
+ virtual void help() {}
+
+ /**
+ * Is called when the user selects "Preferences" from the extensions RMB menu.
+ * Reimplement this function to launch a preferences dialog or kcontrol module.
+ *
+ * Note that this is called only when your extension supports the preferences action.
+ * See Action.
+ **/
+ virtual void preferences() {}
+
+ /**
+ * Is called when the user selects "Report bug" from the applet's RMB menu.
+ * Reimplement this function to launch a bug reporting dialog.
+ *
+ * Note that this is called only when your applet supports the ReportBug
+ * action.
+ * See Action.
+ **/
+ virtual void reportBug() {}
+
+ /**
+ * @return the extension's position. (left, right, top, bottom)
+ **/
+ Position position() const { return _position; }
+
+ /**
+ * @return the extension's alignment. (left/top, center, or right/bottom)
+ **/
+ Alignment alignment() const { return _alignment; }
+
+ /**
+ * @return the extensions orientation. (horizontal or vertical)
+ **/
+ Orientation orientation();
+
+ /**
+ * @return the appropriate size in pixels for the panel
+ * @since 3.1
+ */
+ int sizeInPixels() const;
+
+ /**
+ * This extension has changed its position.
+ * Reimplement this change handler in order to adjust the look of your
+ * applet.
+ **/
+ virtual void positionChange( Position ) {}
+
+ /**
+ * This extension has changed its alignment.
+ * Reimplement this change handler in order to adjust the look of your
+ * applet.
+ **/
+ virtual void alignmentChange( Alignment ) {}
+
+ /**
+ * Use this method to set the custom menu for this extensions so that it can be shown
+ * at the appropriate places/times that the extension many not itself
+ * be aware of. The extension itself is still responsible for deleting and managing the
+ * the menu.
+ *
+ * If the menu is deleted during the life of the extension, be sure to call this method again
+ * with the new menu (or 0) to avoid crashes
+ * @since 3.4
+ */
+ void setCustomMenu(QPopupMenu*);
+
+ /**
+ * Use this method to set the return value for reserveStrut
+ * @see reserveStrut
+ * @since 3.4
+ */
+ void setReserveStrut(bool shouldUseStrut);
+
+private:
+ Type _type;
+ Position _position;
+ Alignment _alignment;
+ KConfig* _config;
+ int _actions;
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KPanelExtensionPrivate *d;
+};
+
+#endif
diff --git a/kdeui/kpanelmenu.cpp b/kdeui/kpanelmenu.cpp
new file mode 100644
index 000000000..ab1ed3d35
--- /dev/null
+++ b/kdeui/kpanelmenu.cpp
@@ -0,0 +1,158 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+ (c) Michael Goffioul <kdeprint@swing.be>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <kglobal.h>
+#include <kconfig.h>
+#include <qtimer.h>
+
+#include "kpanelmenu.h"
+#include "kpanelmenu.moc"
+//#include "kaccelmanager.h"
+
+
+class KPanelMenuPrivate
+{
+public:
+ bool init;
+ int clearDelay;
+ QString startPath;
+ QTimer t;
+};
+
+KPanelMenu::KPanelMenu(const QString &startDir, QWidget *parent, const char *name)
+ : KPopupMenu(parent, name)
+{
+ init(startDir);
+}
+
+KPanelMenu::KPanelMenu(QWidget *parent, const char *name)
+ : KPopupMenu(parent, name)
+{
+ init();
+}
+
+void KPanelMenu::init(const QString& path)
+{
+ d = new KPanelMenuPrivate;
+
+ setInitialized( false );
+ d->startPath = path;
+
+ connect(this, SIGNAL(activated(int)), SLOT(slotExec(int)));
+ connect(this, SIGNAL(aboutToShow()), SLOT(slotAboutToShow()));
+
+ // setup cache timer
+ KConfig *config = KGlobal::config();
+ config->setGroup("menus");
+ d->clearDelay = config->readNumEntry("MenuCacheTime", 60000); // 1 minute
+
+ //KAcceleratorManager::manage(this);
+ setKeyboardShortcutsEnabled(true);
+}
+
+KPanelMenu::~KPanelMenu()
+{
+ delete d;
+}
+
+void KPanelMenu::slotAboutToShow()
+{
+ // stop the cache timer
+ if(d->clearDelay)
+ d->t.stop();
+
+ // teared off ?
+ if ( isTopLevel() )
+ d->clearDelay = 0;
+
+ internalInitialize();
+}
+
+void KPanelMenu::slotClear()
+{
+ setInitialized( false );
+ clear();
+}
+
+void KPanelMenu::hideEvent(QHideEvent *ev)
+{
+ // start the cache timer
+ if(d->clearDelay) {
+ disconnect(&(d->t), SIGNAL(timeout()), this, SLOT(slotClear()));
+ connect(&(d->t), SIGNAL(timeout()), this, SLOT(slotClear()));
+ d->t.start(d->clearDelay, true);
+ }
+ QPopupMenu::hideEvent(ev);
+}
+
+void KPanelMenu::disableAutoClear()
+{
+ d->clearDelay = 0;
+}
+
+const QString& KPanelMenu::path() const
+{
+ return d->startPath;
+}
+
+void KPanelMenu::setPath(const QString& p)
+{
+ d->startPath = p;
+}
+
+bool KPanelMenu::initialized() const
+{
+ return d->init;
+}
+
+void KPanelMenu::setInitialized(bool on)
+{
+ d->init = on;
+}
+
+void KPanelMenu::reinitialize()
+{
+ deinitialize();
+ // Yes, reinitialize must call initialize(). Otherwise, menus
+ // may not appear in the right place. Don't change this! If
+ // you want delayed initialization, use deinitialize() instead.
+ internalInitialize();
+}
+
+void KPanelMenu::deinitialize()
+{
+ slotClear();
+}
+
+void KPanelMenu::internalInitialize()
+{
+ if( initialized() )
+ return;
+ initialize();
+ setInitialized( true );
+}
+
+void KPanelMenu::virtual_hook( int id, void* data )
+{ KPopupMenu::virtual_hook( id, data ); }
+
diff --git a/kdeui/kpanelmenu.h b/kdeui/kpanelmenu.h
new file mode 100644
index 000000000..61ec7f13b
--- /dev/null
+++ b/kdeui/kpanelmenu.h
@@ -0,0 +1,182 @@
+/*****************************************************************
+
+Copyright (c) 1996-2000 the kicker authors. See file AUTHORS.
+ (c) 2001 Michael Goffioul <kdeprint@swing.be>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __KPANELMENU_H__
+#define __KPANELMENU_H__
+
+#include <qstring.h>
+#include <kpopupmenu.h>
+#include <kgenericfactory.h>
+
+class KPanelMenuPrivate;
+
+/**
+ * @short Base class to build dynamically loaded menu entries for the K-menu, or the panel.
+ *
+ * This class allows to build menu entries that will be dynamically added either to
+ * the K-menu, or to the panel as a normal button. These dynamic menus are located
+ * in shared libraries that will be loaded at runtime by Kicker (the %KDE panel).
+ *
+ * To build such a menu, you have to inherit this class and implement the pure virtual
+ * functions #initialize() and slotExec(). You also have to provide a factory
+ * object in your library, see KLibFactory. This factory is only used to construct
+ * the menu object.
+ *
+ * Finally, you also have to provide a desktop file describing your dynamic menu. The
+ * relevant entries are: Name, Comment, Icon and X-KDE-Library (which contains the
+ * library name without any extension). This desktop file has to be installed in
+ * $KDEDIR/share/apps/kicker/menuext/.
+ *
+ * @author The kicker maintainers, Michael Goffioul <kdeprint@swing.be>
+ */
+class KDEUI_EXPORT KPanelMenu : public KPopupMenu
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Construct a KPanelMenu object. This is the normal constructor to use when
+ * building extrernal menu entries.
+ */
+ KPanelMenu(QWidget *parent=0, const char *name=0);
+ /**
+ * Constructor used internally by Kicker. You don't really want to use it.
+ * @param startDir a directory to associate with this menu
+ * @param parent parent object
+ * @param name name of the object
+ * @see path(), setPath()
+ */
+ KPanelMenu(const QString &startDir, QWidget *parent=0, const char *name=0);
+ /**
+ * Destructor.
+ */
+ virtual ~KPanelMenu();
+
+ /**
+ * Get the directory path associated with this menu, or QString::null if
+ * there's no such associated path.
+ * @return the associated directory path
+ * @see setPath()
+ */
+ const QString& path() const;
+ /**
+ * Set a directory path to be associated with this menu.
+ * @param p the directory path
+ * @see path()
+ */
+ void setPath(const QString &p);
+ /**
+ * Tell if the menu has been initialized, that is it already contains items.
+ * This is useful when you need to know if you have to clear the menu, or to
+ * fill it.
+ * @return the initial state
+ * @see setInitialized(), initialize()
+ */
+ bool initialized() const;
+ /**
+ * Set the initial state. Set it to true when you menu is filled with the items
+ * you want.
+ * @param on the initial state
+ * @see initialized(), initialize()
+ */
+ void setInitialized(bool on);
+
+ /**
+ * Disable the automatic clearing of the menu. Kicker uses a cache system for
+ * its menus. After a specific configurable delay, the menu will be cleared.
+ * Use this function if you want to disable kicker's cache system, and avoid
+ * the clearing of your menu.
+ */
+ void disableAutoClear();
+
+public slots:
+ /**
+ * Reinitialize the menu: the menu is first cleared, the initial state is set
+ * to false, and finally #initialize() is called. Use this if you want to
+ * refill your menu immediately.
+ */
+ void reinitialize();
+ /**
+ * Deinitialize the menu: the menu is cleared and the initialized state is set to
+ * false. #initialize() is NOT called. It will be called before the menu is
+ * next shown, however. Use this slot if you want a delayed reinitialization.
+ * @since 3.1
+ */
+ void deinitialize();
+
+protected slots:
+ /**
+ * This slot is called just before the menu is shown. This allows your menu
+ * to update itself if needed. However you should instead re-implement
+ * #initialize to provide this feature. This function is responsible for
+ * the cache system handling, so if you re-implement it, you should call
+ * the base function also. Calls #initialize().
+ * @see disableAutoClear()
+ */
+ virtual void slotAboutToShow();
+ /**
+ * This is slot is called when an item from the menu has been selected. Your
+ * applet is then supposed to perform some action. You must re-implement this
+ * function.
+ * @param id the ID associated with the selected item
+ */
+ virtual void slotExec(int id) = 0;
+ /**
+ * This slots is called to initialize the menu. It is called automatically by
+ * slotAboutToShow(). By re-implementing this functions, you can reconstruct
+ * the menu before it is being shown. At the end of this function, you should
+ * call setInitialize() with true to tell the system that the menu is OK.
+ * You applet must re-implement this function.
+ * @see slotAboutToShow(), initialized(), setInitialized()
+ */
+ virtual void initialize() = 0;
+ /**
+ * Clears the menu, and update the initial state accordingly.
+ * @see initialized()
+ */
+ void slotClear();
+
+protected:
+ /**
+ * Re-implemented for internal reasons.
+ */
+ virtual void hideEvent(QHideEvent *ev);
+ /**
+ * For internal use only. Used by constructors.
+ */
+ void init(const QString& path = QString::null);
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ void internalInitialize();
+ KPanelMenuPrivate *d;
+};
+
+#define K_EXPORT_KICKER_MENUEXT( libname, classname ) \
+ K_EXPORT_COMPONENT_FACTORY( \
+ kickermenu_##libname, \
+ KGenericFactory<classname>("libkickermenu_" #libname) )
+
+#endif
diff --git a/kdeui/kpartgui.dtd b/kdeui/kpartgui.dtd
new file mode 100644
index 000000000..a3cbb8121
--- /dev/null
+++ b/kdeui/kpartgui.dtd
@@ -0,0 +1,181 @@
+<!-- Originally Copyright (c) 2000 Federico David Sacerdoti <tech@slinuxmachines.com>
+ Modifications/Extensions by Simon Hausmann <hausmann@kde.org>
+ Minor updates by Richard J. Moore <rich@kde.org>
+
+ This DTD module is identified by the PUBLIC and SYSTEM
+ identifiers:
+ PUBLIC "-//KDE Project//KPartGUI DTD//EN"
+ SYSTEM "kpartgui.dtd"
+
+ This DTD should be included at the head of an xmlguibuilder XML file like this:
+ <!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+-->
+
+<!--The root element that must enclose all other tags in the document. This element
+ replaces the kpartgui element used previously.
+
+ NOTE: do not forget to increase the version attribute for each change in
+ your file or the changes will not be taken!!
+ -->
+<!ELEMENT gui ((ActionProperties | MenuBar | ToolBar | Merge | MergeLocal | DefineGroup | MainWindow | StatusBar | Menu | State)*)>
+<!ATTLIST gui
+ name CDATA #REQUIRED
+ version CDATA #REQUIRED
+ library CDATA #IMPLIED
+>
+
+<!-- DEPRECATED: The old root element that must enclose all other tags in the document. -->
+<!ELEMENT kpartgui ((ActionProperties | MenuBar | ToolBar | Merge | MergeLocal | DefineGroup | MainWindow | StatusBar | Menu | State)*)>
+<!ATTLIST kpartgui
+ name CDATA #REQUIRED
+ version CDATA #REQUIRED
+ library CDATA #IMPLIED
+>
+
+<!-- Allows standard actions to be customized -->
+<!ELEMENT ActionProperties (Action+)>
+
+<!-- A menu bar -->
+<!ELEMENT MenuBar ((Menu | Separator | Action | ActionList | Merge | MergeLocal | DefineGroup )*)>
+<!ATTLIST MenuBar
+ name CDATA #IMPLIED
+ group CDATA #IMPLIED
+>
+
+<!-- A tool bar
+ - Attributes: name: a unique name for the toolbar, use mainToolBar for the main one
+ - fullWidth: if true (default), the toolbar extends to the full width of the window
+ - position: the position of the toolbar in the window
+ - iconText: whether to show icon or text or both
+ - iconSize: the size of the icons (0 for default, or usually 22 or 32)
+ - index: the index in the toolbar dock (see QMainWindow::moveToolBar; starts at 0)
+ - offset: the X offset in the toolbar dock (see QMainWindow::moveToolBar)
+ - newline: if true, this toolbar will start a new line (i.e. under the ones before it).
+ - group: optional group name, for named merging (?)
+ - hidden: if true, the toolbar is initially hidden. There should be a menu entry for showing it.
+ - noEdit: if true, the toolbar won't appear in the toolbar editor
+ -->
+<!ELEMENT ToolBar (text?, (Action | Separator | WeakSeparator | ActionList | Merge | MergeLocal | DefineGroup)*)>
+<!ATTLIST ToolBar
+ name CDATA #REQUIRED
+ fullWidth (true|false) "true"
+ position (top|bottom|left|right) "top"
+ iconText (icononly|textonly|icontextright|icontextbottom) #IMPLIED
+ iconSize CDATA #IMPLIED
+ index CDATA #IMPLIED
+ offset CDATA #IMPLIED
+ newline (true|false) "false"
+ group CDATA #IMPLIED
+ hidden (true|false) "false"
+ noEdit (true|false) "false"
+>
+
+<!-- A Menu such as the "File" or "Edit" menu. Can be used to define popup menus as well. -->
+<!ELEMENT Menu (text?, (title | Action | ActionList | Separator | WeakSeparator | TearOffHandle | Merge | MergeLocal | DefineGroup | Menu )*)>
+<!ATTLIST Menu
+ append CDATA #IMPLIED
+ name CDATA #REQUIRED
+ group CDATA #IMPLIED
+ icon CDATA #IMPLIED
+ noMerge (0|1) "0"
+>
+
+<!-- Defines both Standard and app-specific actions. An action can appear in a menu, a toolbar or in a
+ menubar.
+ Attributes:
+ - name of the action: this is matched with the KAction name.
+ - group: this is used to control the placement of the action when merging
+ e.g. a part, it matches the name of a DefineGroup in the mainwindow's rc file.
+ - append: this is used to control the placement of the action during the
+ merging with ui_standards.rc. This is mapped to MergeLocal tags there.
+ Note that this feature is currently only available for the mainwindow, not for parts/plugins.
+ - text, whatsThis, toolTip, shortText, shortcut, icon: all those are mapped
+ to KAction properties.
+ -->
+<!ELEMENT Action EMPTY>
+<!-- We defined only a few standard KAction properties here. Theoritically we can have
+ any property here -->
+<!ATTLIST Action
+ name CDATA #REQUIRED
+ group CDATA #IMPLIED
+ append CDATA #IMPLIED
+ text CDATA #IMPLIED
+ whatsThis CDATA #IMPLIED
+ toolTip CDATA #IMPLIED
+ shortText CDATA #IMPLIED
+ shortcut CDATA #IMPLIED
+ icon CDATA #IMPLIED
+>
+
+<!-- Inserts a separator item into a menubar or toolbar -->
+<!ELEMENT Separator EMPTY>
+<!ATTLIST Separator
+ lineSeparator (true|false) "true"
+ group CDATA #IMPLIED
+>
+
+<!ELEMENT WeakSeparator EMPTY>
+
+<!-- Inserts a tear-off handle into a menu -->
+<!ELEMENT TearOffHandle EMPTY>
+<!ATTLIST TearOffHandle
+ group CDATA #IMPLIED
+>
+
+<!-- Used to insert titles, only for popup menus -->
+<!ELEMENT title (#PCDATA)>
+<!ATTLIST title
+ icon CDATA #IMPLIED
+>
+
+<!-- Used to name a menu, the first letter in is generally preceded by an '&' to specify
+ the menu's shortcut key -->
+<!ELEMENT text (#PCDATA)>
+<!ATTLIST text
+ context CDATA #IMPLIED
+>
+
+<!-- Specifies a dynamic list of actions, each of which can be changed by plugging/unplugging it -->
+<!ELEMENT ActionList EMPTY>
+<!ATTLIST ActionList
+ name CDATA #REQUIRED
+>
+
+<!-- Not explicitly defined or in widely used yet. -->
+<!ELEMENT MainWindow (ANY)>
+
+<!-- Not explicitly defined or in widely used yet. -->
+<!ELEMENT StatusBar (ANY)>
+
+<!-- Specifies the entry index for merging in a gui client -->
+<!ELEMENT Merge EMPTY>
+<!ATTLIST Merge
+ name CDATA #IMPLIED
+>
+
+<!-- Specifies an entry index for merging application defined actions into
+ those with positions fixed by the style guide and ui_standards.rc. This
+ tag should not be used anywhere except ui_standards.rc. -->
+<!ELEMENT MergeLocal EMPTY>
+<!ATTLIST MergeLocal
+ name CDATA #IMPLIED
+>
+
+<!-- Specifies a entry index for merging, similar to the Merge tag, but with a global scope and
+ accessible via the group attribute of other tags -->
+<!ELEMENT DefineGroup EMPTY>
+<!ATTLIST DefineGroup
+ name CDATA #REQUIRED
+>
+
+<!-- Defines a GUI state, esp. which actions to enable and which ones to -->
+<!-- disable on entering this state (see KXMLGUIClient::stateChanged()) -->
+<!ELEMENT State ( enable | disable | (enable, disable))>
+<!ATTLIST State
+ name CDATA #REQUIRED
+>
+
+<!-- used in State to collect actions to be enabled and disabled, resp., -->
+<!-- on entering the state -->
+<!ELEMENT enable (Action+)>
+<!ELEMENT disable (Action+)>
diff --git a/kdeui/kpassdlg.cpp b/kdeui/kpassdlg.cpp
new file mode 100644
index 000000000..6ca6cc6ea
--- /dev/null
+++ b/kdeui/kpassdlg.cpp
@@ -0,0 +1,721 @@
+// vi: ts=8 sts=4 sw=4
+/* This file is part of the KDE libraries
+ Copyright (C) 1998 Pietro Iglio <iglio@fub.it>
+ Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org>
+ Copyright (C) 2004,2005 Andrew Coles <andrew_coles@yahoo.co.uk>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#include <unistd.h>
+
+#include <qwidget.h>
+#include <qlineedit.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qsize.h>
+#include <qevent.h>
+#include <qkeycode.h>
+#include <qcheckbox.h>
+#include <qregexp.h>
+#include <qhbox.h>
+#include <qwhatsthis.h>
+#include <qptrdict.h>
+
+#include <kglobal.h>
+#include <kdebug.h>
+#include <kapplication.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+#include <kaboutdialog.h>
+#include <kconfig.h>
+#include <kstandarddirs.h>
+#include <kprogress.h>
+
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include "kpassdlg.h"
+
+/*
+ * Password line editor.
+ */
+
+// BCI: Add a real d-pointer and put the int into that
+
+static QPtrDict<int>* d_ptr = 0;
+
+static void cleanup_d_ptr() {
+ delete d_ptr;
+}
+
+static int * ourMaxLength( const KPasswordEdit* const e ) {
+ if ( !d_ptr ) {
+ d_ptr = new QPtrDict<int>;
+ d_ptr->setAutoDelete(true);
+ qAddPostRoutine( cleanup_d_ptr );
+ }
+ int* ret = d_ptr->find( (void*) e );
+ if ( ! ret ) {
+ ret = new int;
+ d_ptr->replace( (void*) e, ret );
+ }
+ return ret;
+}
+
+static void delete_d( const KPasswordEdit* const e ) {
+ if ( d_ptr )
+ d_ptr->remove( (void*) e );
+}
+
+const int KPasswordEdit::PassLen = 200;
+
+class KPasswordDialog::KPasswordDialogPrivate
+{
+ public:
+ KPasswordDialogPrivate()
+ : m_MatchLabel( 0 ), iconName( 0 ), allowEmptyPasswords( false ),
+ minimumPasswordLength(0), maximumPasswordLength(KPasswordEdit::PassLen - 1),
+ passwordStrengthWarningLevel(1), m_strengthBar(0),
+ reasonablePasswordLength(8)
+ {}
+ QLabel *m_MatchLabel;
+ QString iconName;
+ bool allowEmptyPasswords;
+ int minimumPasswordLength;
+ int maximumPasswordLength;
+ int passwordStrengthWarningLevel;
+ KProgress* m_strengthBar;
+ int reasonablePasswordLength;
+};
+
+
+KPasswordEdit::KPasswordEdit(QWidget *parent, const char *name)
+ : QLineEdit(parent, name)
+{
+ init();
+
+ KConfig* const cfg = KGlobal::config();
+ KConfigGroupSaver saver(cfg, "Passwords");
+
+ const QString val = cfg->readEntry("EchoMode", "OneStar");
+ if (val == "ThreeStars")
+ m_EchoMode = ThreeStars;
+ else if (val == "NoEcho")
+ m_EchoMode = NoEcho;
+ else
+ m_EchoMode = OneStar;
+
+ setInputMethodEnabled( true );
+}
+
+KPasswordEdit::KPasswordEdit(QWidget *parent, const char *name, int echoMode)
+ : QLineEdit(parent, name), m_EchoMode(echoMode)
+{
+ init();
+}
+
+KPasswordEdit::KPasswordEdit(EchoModes echoMode, QWidget *parent, const char *name)
+ : QLineEdit(parent, name), m_EchoMode(echoMode)
+{
+ init();
+}
+
+KPasswordEdit::KPasswordEdit(EchoMode echoMode, QWidget *parent, const char *name)
+ : QLineEdit(parent, name)
+ , m_EchoMode( echoMode == QLineEdit::NoEcho ? NoEcho : OneStar )
+{
+ init();
+}
+
+void KPasswordEdit::init()
+{
+ setEchoMode(QLineEdit::Password); // Just in case
+ setAcceptDrops(false);
+ int* t = ourMaxLength(this);
+ *t = (PassLen - 1); // the internal max length
+ m_Password = new char[PassLen];
+ m_Password[0] = '\000';
+ m_Length = 0;
+}
+
+KPasswordEdit::~KPasswordEdit()
+{
+ memset(m_Password, 0, PassLen * sizeof(char));
+ delete[] m_Password;
+ delete_d(this);
+}
+
+void KPasswordEdit::insert(const QString &txt)
+{
+ const QCString localTxt = txt.local8Bit();
+ const unsigned int lim = localTxt.length();
+ const int m_MaxLength = maxPasswordLength();
+ for(unsigned int i=0; i < lim; ++i)
+ {
+ const unsigned char ke = localTxt[i];
+ if (m_Length < m_MaxLength)
+ {
+ m_Password[m_Length] = ke;
+ m_Password[++m_Length] = '\000';
+ }
+ }
+ showPass();
+}
+
+void KPasswordEdit::erase()
+{
+ m_Length = 0;
+ memset(m_Password, 0, PassLen * sizeof(char));
+ setText("");
+}
+
+void KPasswordEdit::focusInEvent(QFocusEvent *e)
+{
+ const QString txt = text();
+ setUpdatesEnabled(false);
+ QLineEdit::focusInEvent(e);
+ setUpdatesEnabled(true);
+ setText(txt);
+}
+
+
+void KPasswordEdit::keyPressEvent(QKeyEvent *e)
+{
+ switch (e->key()) {
+ case Key_Return:
+ case Key_Enter:
+ case Key_Escape:
+ e->ignore();
+ break;
+ case Key_Backspace:
+ case Key_Delete:
+ case 0x7f: // Delete
+ if (e->state() & (ControlButton | AltButton))
+ e->ignore();
+ else if (m_Length) {
+ m_Password[--m_Length] = '\000';
+ showPass();
+ }
+ break;
+ default:
+ const unsigned char ke = e->text().local8Bit()[0];
+ if (ke >= 32) {
+ insert(e->text());
+ } else
+ e->ignore();
+ break;
+ }
+}
+
+bool KPasswordEdit::event(QEvent *e) {
+ switch(e->type()) {
+
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseMove:
+ case QEvent::IMStart:
+ case QEvent::IMCompose:
+ return true; //Ignore
+
+ case QEvent::IMEnd:
+ {
+ QIMEvent* const ie = (QIMEvent*) e;
+ if (!ie->text().isEmpty())
+ insert( ie->text() );
+ return true;
+ }
+
+ case QEvent::AccelOverride:
+ {
+ QKeyEvent* const k = (QKeyEvent*) e;
+ switch (k->key()) {
+ case Key_U:
+ if (k->state() & ControlButton) {
+ m_Length = 0;
+ m_Password[m_Length] = '\000';
+ showPass();
+ }
+ }
+ return true; // stop bubbling
+ }
+
+ default:
+ // Do nothing
+ break;
+ }
+ return QLineEdit::event(e);
+}
+
+void KPasswordEdit::showPass()
+{
+ QString tmp;
+
+ switch (m_EchoMode) {
+ case OneStar:
+ tmp.fill('*', m_Length);
+ setText(tmp);
+ break;
+ case ThreeStars:
+ tmp.fill('*', m_Length*3);
+ setText(tmp);
+ break;
+ case NoEcho: default:
+ emit textChanged(QString::null); //To update the password comparison if need be.
+ break;
+ }
+}
+
+void KPasswordEdit::setMaxPasswordLength(int newLength)
+{
+ if (newLength >= PassLen) newLength = PassLen - 1; // belt and braces
+ if (newLength < 0) newLength = 0;
+ int* t = ourMaxLength(this);
+ *t = newLength;
+ while (m_Length > newLength) {
+ m_Password[m_Length] = '\000';
+ --m_Length;
+ }
+ showPass();
+}
+
+int KPasswordEdit::maxPasswordLength() const
+{
+ return *(ourMaxLength(this));
+}
+/*
+ * Password dialog.
+ */
+
+KPasswordDialog::KPasswordDialog(Types type, bool enableKeep, int extraBttn,
+ QWidget *parent, const char *name)
+ : KDialogBase(parent, name, true, "", Ok|Cancel|extraBttn,
+ Ok, true), m_Keep(enableKeep? 1 : 0), m_Type(type), d(new KPasswordDialogPrivate)
+{
+ d->iconName = "password";
+ init();
+}
+
+KPasswordDialog::KPasswordDialog(Types type, bool enableKeep, int extraBttn, const QString& icon,
+ QWidget *parent, const char *name )
+ : KDialogBase(parent, name, true, "", Ok|Cancel|extraBttn,
+ Ok, true), m_Keep(enableKeep? 1 : 0), m_Type(type), d(new KPasswordDialogPrivate)
+{
+ if ( icon.stripWhiteSpace().isEmpty() )
+ d->iconName = "password";
+ else
+ d->iconName = icon;
+ init();
+}
+
+KPasswordDialog::KPasswordDialog(int type, QString prompt, bool enableKeep,
+ int extraBttn)
+ : KDialogBase(0L, "Password Dialog", true, "", Ok|Cancel|extraBttn,
+ Ok, true), m_Keep(enableKeep? 1 : 0), m_Type(type), d(new KPasswordDialogPrivate)
+{
+ d->iconName = "password";
+ init();
+ setPrompt(prompt);
+}
+
+void KPasswordDialog::init()
+{
+ m_Row = 0;
+
+ KConfig* const cfg = KGlobal::config();
+ const KConfigGroupSaver saver(cfg, "Passwords");
+ if (m_Keep && cfg->readBoolEntry("Keep", false))
+ ++m_Keep;
+
+ m_pMain = new QWidget(this);
+ setMainWidget(m_pMain);
+ m_pGrid = new QGridLayout(m_pMain, 10, 3, 0, 0);
+ m_pGrid->addColSpacing(1, 10);
+
+ // Row 1: pixmap + prompt
+ QLabel *lbl;
+ const QPixmap pix( KGlobal::iconLoader()->loadIcon( d->iconName, KIcon::NoGroup, KIcon::SizeHuge, 0, 0, true));
+ if (!pix.isNull()) {
+ lbl = new QLabel(m_pMain);
+ lbl->setPixmap(pix);
+ lbl->setAlignment(AlignHCenter|AlignVCenter);
+ lbl->setFixedSize(lbl->sizeHint());
+ m_pGrid->addWidget(lbl, 0, 0, AlignCenter);
+ }
+
+ m_pHelpLbl = new QLabel(m_pMain);
+ m_pHelpLbl->setAlignment(AlignLeft|AlignVCenter|WordBreak);
+ m_pGrid->addWidget(m_pHelpLbl, 0, 2, AlignLeft);
+ m_pGrid->addRowSpacing(1, 10);
+ m_pGrid->setRowStretch(1, 12);
+
+ // Row 2+: space for 4 extra info lines
+ m_pGrid->addRowSpacing(6, 5);
+ m_pGrid->setRowStretch(6, 12);
+
+ // Row 3: Password editor #1
+ lbl = new QLabel(m_pMain);
+ lbl->setAlignment(AlignLeft|AlignVCenter);
+ lbl->setText(i18n("&Password:"));
+ lbl->setFixedSize(lbl->sizeHint());
+ m_pGrid->addWidget(lbl, 7, 0, AlignLeft);
+
+ QHBoxLayout *h_lay = new QHBoxLayout();
+ m_pGrid->addLayout(h_lay, 7, 2);
+ m_pEdit = new KPasswordEdit(m_pMain);
+ m_pEdit2 = 0;
+ lbl->setBuddy(m_pEdit);
+ QSize size = m_pEdit->sizeHint();
+ m_pEdit->setFixedHeight(size.height());
+ m_pEdit->setMinimumWidth(size.width());
+ h_lay->addWidget(m_pEdit);
+
+ // Row 4: Password editor #2 or keep password checkbox
+
+ if ((m_Type == Password) && m_Keep) {
+ m_pGrid->addRowSpacing(8, 10);
+ m_pGrid->setRowStretch(8, 12);
+ QCheckBox* const cb = new QCheckBox(i18n("&Keep password"), m_pMain);
+ cb->setFixedSize(cb->sizeHint());
+ if (m_Keep > 1)
+ cb->setChecked(true);
+ else
+ m_Keep = 0;
+ connect(cb, SIGNAL(toggled(bool)), SLOT(slotKeep(bool)));
+ m_pGrid->addWidget(cb, 9, 2, AlignLeft|AlignVCenter);
+ } else if (m_Type == NewPassword) {
+ m_pGrid->addRowSpacing(8, 10);
+ lbl = new QLabel(m_pMain);
+ lbl->setAlignment(AlignLeft|AlignVCenter);
+ lbl->setText(i18n("&Verify:"));
+ lbl->setFixedSize(lbl->sizeHint());
+ m_pGrid->addWidget(lbl, 9, 0, AlignLeft);
+
+ h_lay = new QHBoxLayout();
+ m_pGrid->addLayout(h_lay, 9, 2);
+ m_pEdit2 = new KPasswordEdit(m_pMain);
+ lbl->setBuddy(m_pEdit2);
+ size = m_pEdit2->sizeHint();
+ m_pEdit2->setFixedHeight(size.height());
+ m_pEdit2->setMinimumWidth(size.width());
+ h_lay->addWidget(m_pEdit2);
+
+ // Row 6: Password strength meter
+ m_pGrid->addRowSpacing(10, 10);
+ m_pGrid->setRowStretch(10, 12);
+
+ QHBox* const strengthBox = new QHBox(m_pMain);
+ strengthBox->setSpacing(10);
+ m_pGrid->addMultiCellWidget(strengthBox, 11, 11, 0, 2);
+ QLabel* const passStrengthLabel = new QLabel(strengthBox);
+ passStrengthLabel->setAlignment(AlignLeft|AlignVCenter);
+ passStrengthLabel->setText(i18n("Password strength meter:"));
+ d->m_strengthBar = new KProgress(100, strengthBox, "PasswordStrengthMeter");
+ d->m_strengthBar->setPercentageVisible(false);
+
+ const QString strengthBarWhatsThis(i18n("The password strength meter gives an indication of the security "
+ "of the password you have entered. To improve the strength of "
+ "the password, try:\n"
+ " - using a longer password;\n"
+ " - using a mixture of upper- and lower-case letters;\n"
+ " - using numbers or symbols, such as #, as well as letters."));
+ QWhatsThis::add(passStrengthLabel, strengthBarWhatsThis);
+ QWhatsThis::add(d->m_strengthBar, strengthBarWhatsThis);
+
+ // Row 6: Label saying whether the passwords match
+ m_pGrid->addRowSpacing(12, 10);
+ m_pGrid->setRowStretch(12, 12);
+
+ d->m_MatchLabel = new QLabel(m_pMain);
+ d->m_MatchLabel->setAlignment(AlignLeft|AlignVCenter|WordBreak);
+ m_pGrid->addMultiCellWidget(d->m_MatchLabel, 13, 13, 0, 2);
+ d->m_MatchLabel->setText(i18n("Passwords do not match"));
+
+
+ connect( m_pEdit, SIGNAL(textChanged(const QString&)), SLOT(enableOkBtn()) );
+ connect( m_pEdit2, SIGNAL(textChanged(const QString&)), SLOT(enableOkBtn()) );
+ enableOkBtn();
+ }
+
+ erase();
+}
+
+
+KPasswordDialog::~KPasswordDialog()
+{
+ delete d;
+}
+
+
+void KPasswordDialog::clearPassword()
+{
+ m_pEdit->erase();
+}
+
+/* KDE 4: Make it const QString & */
+void KPasswordDialog::setPrompt(QString prompt)
+{
+ m_pHelpLbl->setText(prompt);
+ m_pHelpLbl->setFixedSize(275, m_pHelpLbl->heightForWidth(275));
+}
+
+
+QString KPasswordDialog::prompt() const
+
+{
+ return m_pHelpLbl->text();
+}
+
+
+/* KDE 4: Make them const QString & */
+void KPasswordDialog::addLine(QString key, QString value)
+{
+ if (m_Row > 3)
+ return;
+
+ QLabel *lbl = new QLabel(key, m_pMain);
+ lbl->setAlignment(AlignLeft|AlignTop);
+ lbl->setFixedSize(lbl->sizeHint());
+ m_pGrid->addWidget(lbl, m_Row+2, 0, AlignLeft);
+
+ lbl = new QLabel(value, m_pMain);
+ lbl->setAlignment(AlignTop|WordBreak);
+ lbl->setFixedSize(275, lbl->heightForWidth(275));
+ m_pGrid->addWidget(lbl, m_Row+2, 2, AlignLeft);
+ ++m_Row;
+}
+
+
+void KPasswordDialog::erase()
+{
+ m_pEdit->erase();
+ m_pEdit->setFocus();
+ if (m_Type == NewPassword)
+ m_pEdit2->erase();
+}
+
+
+void KPasswordDialog::slotOk()
+{
+ if (m_Type == NewPassword) {
+ if (strcmp(m_pEdit->password(), m_pEdit2->password())) {
+ KMessageBox::sorry(this, i18n("You entered two different "
+ "passwords. Please try again."));
+ erase();
+ return;
+ }
+ if (d->m_strengthBar && d->m_strengthBar->progress() < d->passwordStrengthWarningLevel) {
+ int retVal = KMessageBox::warningContinueCancel(this,
+ i18n( "The password you have entered has a low strength. "
+ "To improve the strength of "
+ "the password, try:\n"
+ " - using a longer password;\n"
+ " - using a mixture of upper- and lower-case letters;\n"
+ " - using numbers or symbols as well as letters.\n"
+ "\n"
+ "Would you like to use this password anyway?"),
+ i18n("Low Password Strength"));
+ if (retVal == KMessageBox::Cancel) return;
+ }
+ }
+ if (!checkPassword(m_pEdit->password())) {
+ erase();
+ return;
+ }
+ accept();
+}
+
+
+void KPasswordDialog::slotCancel()
+{
+ reject();
+}
+
+
+void KPasswordDialog::slotKeep(bool keep)
+{
+ m_Keep = keep;
+}
+
+
+// static . antlarr: KDE 4: Make it const QString & prompt
+int KPasswordDialog::getPassword(QCString &password, QString prompt,
+ int *keep)
+{
+ const bool enableKeep = (keep && *keep);
+ KPasswordDialog* const dlg = new KPasswordDialog(int(Password), prompt, enableKeep);
+ const int ret = dlg->exec();
+ if (ret == Accepted) {
+ password = dlg->password();
+ if (enableKeep)
+ *keep = dlg->keep();
+ }
+ delete dlg;
+ return ret;
+}
+
+
+// static . antlarr: KDE 4: Make it const QString & prompt
+int KPasswordDialog::getNewPassword(QCString &password, QString prompt)
+{
+ KPasswordDialog* const dlg = new KPasswordDialog(NewPassword, prompt);
+ const int ret = dlg->exec();
+ if (ret == Accepted)
+ password = dlg->password();
+ delete dlg;
+ return ret;
+}
+
+
+// static
+void KPasswordDialog::disableCoreDumps()
+{
+ struct rlimit rlim;
+ rlim.rlim_cur = rlim.rlim_max = 0;
+ setrlimit(RLIMIT_CORE, &rlim);
+}
+
+void KPasswordDialog::virtual_hook( int id, void* data )
+{ KDialogBase::virtual_hook( id, data ); }
+
+void KPasswordDialog::enableOkBtn()
+{
+ if (m_Type == NewPassword) {
+ const bool match = strcmp(m_pEdit->password(), m_pEdit2->password()) == 0
+ && (d->allowEmptyPasswords || m_pEdit->password()[0]);
+
+ const QString pass(m_pEdit->password());
+
+ const int minPasswordLength = minimumPasswordLength();
+
+ if ((int) pass.length() < minPasswordLength) {
+ enableButtonOK(false);
+ } else {
+ enableButtonOK( match );
+ }
+
+ if ( match && d->allowEmptyPasswords && m_pEdit->password()[0] == 0 ) {
+ d->m_MatchLabel->setText( i18n("Password is empty") );
+ } else {
+ if ((int) pass.length() < minPasswordLength) {
+ d->m_MatchLabel->setText(i18n("Password must be at least 1 character long", "Password must be at least %n characters long", minPasswordLength));
+ } else {
+ d->m_MatchLabel->setText( match? i18n("Passwords match")
+ :i18n("Passwords do not match") );
+ }
+ }
+
+ // Password strength calculator
+ // Based on code in the Master Password dialog in Firefox
+ // (pref-masterpass.js)
+ // Original code triple-licensed under the MPL, GPL, and LGPL
+ // so is license-compatible with this file
+
+ const double lengthFactor = d->reasonablePasswordLength / 8.0;
+
+
+ int pwlength = (int) (pass.length() / lengthFactor);
+ if (pwlength > 5) pwlength = 5;
+
+ const QRegExp numRxp("[0-9]", true, false);
+ int numeric = (int) (pass.contains(numRxp) / lengthFactor);
+ if (numeric > 3) numeric = 3;
+
+ const QRegExp symbRxp("\\W", false, false);
+ int numsymbols = (int) (pass.contains(symbRxp) / lengthFactor);
+ if (numsymbols > 3) numsymbols = 3;
+
+ const QRegExp upperRxp("[A-Z]", true, false);
+ int upper = (int) (pass.contains(upperRxp) / lengthFactor);
+ if (upper > 3) upper = 3;
+
+ int pwstrength=((pwlength*10)-20) + (numeric*10) + (numsymbols*15) + (upper*10);
+
+ if ( pwstrength < 0 ) {
+ pwstrength = 0;
+ }
+
+ if ( pwstrength > 100 ) {
+ pwstrength = 100;
+ }
+ d->m_strengthBar->setProgress(pwstrength);
+
+ }
+}
+
+
+void KPasswordDialog::setAllowEmptyPasswords(bool allowed) {
+ d->allowEmptyPasswords = allowed;
+ enableOkBtn();
+}
+
+
+bool KPasswordDialog::allowEmptyPasswords() const {
+ return d->allowEmptyPasswords;
+}
+
+void KPasswordDialog::setMinimumPasswordLength(int minLength) {
+ d->minimumPasswordLength = minLength;
+ enableOkBtn();
+}
+
+int KPasswordDialog::minimumPasswordLength() const {
+ return d->minimumPasswordLength;
+}
+
+void KPasswordDialog::setMaximumPasswordLength(int maxLength) {
+
+ if (maxLength < 0) maxLength = 0;
+ if (maxLength >= KPasswordEdit::PassLen) maxLength = KPasswordEdit::PassLen - 1;
+
+ d->maximumPasswordLength = maxLength;
+
+ m_pEdit->setMaxPasswordLength(maxLength);
+ if (m_pEdit2) m_pEdit2->setMaxPasswordLength(maxLength);
+
+}
+
+int KPasswordDialog::maximumPasswordLength() const {
+ return d->maximumPasswordLength;
+}
+
+// reasonable password length code contributed by Steffen Mthing
+
+void KPasswordDialog::setReasonablePasswordLength(int reasonableLength) {
+
+ if (reasonableLength < 1) reasonableLength = 1;
+ if (reasonableLength >= maximumPasswordLength()) reasonableLength = maximumPasswordLength();
+
+ d->reasonablePasswordLength = reasonableLength;
+
+}
+
+int KPasswordDialog::reasonablePasswordLength() const {
+ return d->reasonablePasswordLength;
+}
+
+
+void KPasswordDialog::setPasswordStrengthWarningLevel(int warningLevel) {
+ if (warningLevel < 0) warningLevel = 0;
+ if (warningLevel > 99) warningLevel = 99;
+ d->passwordStrengthWarningLevel = warningLevel;
+}
+
+int KPasswordDialog::passwordStrengthWarningLevel() const {
+ return d->passwordStrengthWarningLevel;
+}
+
+#include "kpassdlg.moc"
diff --git a/kdeui/kpassdlg.h b/kdeui/kpassdlg.h
new file mode 100644
index 000000000..b3bc80677
--- /dev/null
+++ b/kdeui/kpassdlg.h
@@ -0,0 +1,414 @@
+// vi: ts=8 sts=4 sw=4
+/* This file is part of the KDE libraries
+ Copyright (C) 1998 Pietro Iglio <iglio@fub.it>
+ Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org>
+ Copyright (C) 2004,2005 Andrew Coles <andrew_coles@yahoo.co.uk>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef __KPassDlg_h_included__
+#define __KPassDlg_h_included__
+
+#include <qstring.h>
+#include <qlineedit.h>
+#include <kdialogbase.h>
+
+class QLabel;
+class QGridLayout;
+class QWidget;
+
+/**
+ * @short A safe password input widget.
+ * @author Geert Jansen <geertj@kde.org>
+ *
+ * The widget uses the user's global "echo mode" setting.
+ */
+
+class KDEUI_EXPORT KPasswordEdit
+ : public QLineEdit
+{
+ Q_OBJECT
+
+public:
+ enum EchoModes { OneStar, ThreeStars, NoEcho };
+
+ /**
+ * Constructs a password input widget using the user's global "echo mode" setting.
+ */
+ KPasswordEdit(QWidget *parent=0, const char *name=0);
+ // KDE4: either of the two must go! add default values for parameters
+
+ /**
+ * Constructs a password input widget using echoMode as "echo mode".
+ * Note that echoMode is a QLineEdit::EchoMode.
+ * @since 3.0
+ */
+ KPasswordEdit(EchoMode echoMode, QWidget *parent, const char *name);
+
+ /**
+ * Constructs a password input widget using echoMode as "echo mode".
+ * Note that echoMode is a KPasswordEdit::EchoModes.
+ * @since 3.2
+ */
+ KPasswordEdit(EchoModes echoMode, QWidget *parent, const char *name);
+
+ /**
+ * @deprecated, will be removed in KDE 4.0
+ * Creates a password input widget using echoMode as "echo mode".
+ */
+ KPasswordEdit(QWidget *parent, const char *name, int echoMode) KDE_DEPRECATED;
+
+ /**
+ * Destructs the widget.
+ */
+ ~KPasswordEdit();
+
+ /**
+ * Returns the password. The memory is freed in the destructor
+ * so you should make a copy.
+ */
+ const char *password() const { return m_Password; }
+
+ /**
+ * Erases the current password.
+ */
+ void erase();
+
+ static const int PassLen;
+
+ /**
+ * Set the current maximum password length. If a password longer than the limit
+ * specified is currently entered, it is truncated accordingly.
+ *
+ * The length is capped to lie between 0 and 199 inclusive.
+ *
+ * @param newLength: The new maximum password length
+ * @since 3.4
+ */
+ void setMaxPasswordLength(int newLength);
+
+ /**
+ * Returns the current maximum password length.
+ * @since 3.4
+ */
+ int maxPasswordLength() const;
+
+public slots:
+ /**
+ * Reimplementation
+ */
+ virtual void insert( const QString &);
+
+protected:
+ virtual void keyPressEvent(QKeyEvent *);
+ virtual void focusInEvent(QFocusEvent *e);
+ virtual bool event(QEvent *e);
+
+private:
+ void init();
+ void showPass();
+
+ char *m_Password;
+ int m_EchoMode, m_Length;
+};
+
+
+/**
+ * @short A password input dialog.
+ *
+ * This dialog asks the user to enter a password. The functions you're
+ * probably interested in are the static methods, getPassword() and
+ * getNewPassword().
+ *
+ * <b>Usage example</b>\n
+ *
+ * \code
+ * QCString password;
+ * int result = KPasswordDialog::getPassword(password, i18n("Prompt message"));
+ * if (result == KPasswordDialog::Accepted)
+ * use(password);
+ * \endcode
+ *
+ * \image html kpassworddialog.png "KDE Password Dialog"
+ *
+ * <b>Security notes:</b>\n
+ *
+ * Keeping passwords in memory can be a potential security hole. You should
+ * handle this situation with care.
+ *
+ * @li You may want to use disableCoreDump() to disable core dumps.
+ * Core dumps are dangerous because they are an image of the process memory,
+ * and thus include any passwords that were in memory.
+ *
+ * @li You should delete passwords as soon as they are not needed anymore.
+ * The functions getPassword() and getNewPassword() return the
+ * password as a QCString. I believe this is safer than a QString. A QString
+ * stores its characters internally as 16-bit wide values, so conversions are
+ * needed, both for creating the QString and by using it. The temporary
+ * memory used for these conversion is probably not erased. This could lead
+ * to stray passwords in memory, even if you think you erased all of them.
+ *
+ * @author Geert Jansen <jansen@kde.org>
+ */
+
+class KDEUI_EXPORT KPasswordDialog
+ : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ /**
+ * This enum distinguishes the two operation modes of this dialog:
+ */
+ enum Types {
+ /**
+ * The user is asked to enter a password.
+ */
+ Password,
+
+ /**
+ * The user is asked to enter a password and to confirm it
+ * a second time. This is usually used when the user
+ * changes his password.
+ */
+ NewPassword
+ };
+
+ /**
+ * Constructs a password dialog.
+ *
+ * @param type: if NewPassword is given here, the dialog contains two
+ * input fields, so that the user must confirm his password
+ * and possible typos are detected immediately.
+ * @param enableKeep: if true, a check box is shown in the dialog
+ * which allows the user to keep his password input for later.
+ * @param extraBttn: allows to show additional buttons, KDialogBase.
+ * @param parent Passed to lower level constructor.
+ * @param name Passed to lower level constructor
+ *
+ * @since 3.0
+ */
+ KPasswordDialog(Types type, bool enableKeep, int extraBttn,
+ QWidget *parent=0, const char *name=0);
+
+ /**
+ * @deprecated Variant of the previous constructor without the
+ * possibility to specify a parent. Will be removed in KDE 4.0
+ */
+ KPasswordDialog(int type, QString prompt, bool enableKeep=false,
+ int extraBttn=0) KDE_DEPRECATED;
+ // note that this implicitly deprecates the 'prompt' variants of
+ // getPassword() below. i guess the above constructor needs to be extended.
+
+ /**
+ * Construct a password dialog. Essentially the same as above but allows the
+ * icon in the password dialog to be set via @p iconName.
+ * @param type if NewPassword is given here, the dialog contains two
+ * input fields, so that the user must confirm his password
+ * and possible typos are detected immediately
+ * @param enableKeep: if true, a check box is shown in the dialog
+ * which allows the user to keep his password input for later.
+ * @param extraBttn: allows to show additional buttons.
+ * @param iconName the name of the icon to be shown in the dialog. If empty,
+ * a default icon is used
+ * @param parent Passed to lower level constructor.
+ * @param name Passed to lower level constructor
+ * @since 3.3
+ */
+ KPasswordDialog(Types type, bool enableKeep, int extraBttn, const QString& iconName,
+ QWidget *parent = 0, const char *name = 0);
+
+ /**
+ * Destructs the password dialog.
+ */
+ virtual ~KPasswordDialog();
+
+ /**
+ * Sets the password prompt.
+ */
+ void setPrompt(QString prompt);
+
+ /**
+ * Returns the password prompt.
+ */
+ QString prompt() const;
+
+ /**
+ * Adds a line of information to the dialog.
+ */
+ void addLine(QString key, QString value);
+
+ /**
+ * Allow empty passwords? - Default: false
+ * @since 3.4
+ */
+ void setAllowEmptyPasswords(bool allowed);
+
+ /**
+ * Allow empty passwords?
+ * @since 3.4
+ */
+ bool allowEmptyPasswords() const;
+
+ /**
+ * Minimum acceptable password length.
+ * Default: If empty passwords are forbidden, 1;
+ * Otherwise, 0.
+ *
+ * @param minLength: The new minimum password length
+ * @since 3.4
+ */
+ void setMinimumPasswordLength(int minLength);
+
+ /**
+ * Minimum acceptable password length.
+ * @since 3.4
+ */
+ int minimumPasswordLength() const;
+
+ /**
+ * Maximum acceptable password length. Limited to 199.
+ * Default: No limit, i.e. -1
+ *
+ * @param maxLength: The new maximum password length.
+ * @since 3.4
+ */
+ void setMaximumPasswordLength(int maxLength);
+
+ /**
+ * Maximum acceptable password length.
+ * @since 3.4
+ */
+ int maximumPasswordLength() const;
+
+ /**
+ * Password length that is expected to be reasonably safe.
+ *
+ * Default: 8 - the standard UNIX password length
+ *
+ * @param reasonableLength: The new reasonable password length.
+ * @since 3.4
+ */
+ void setReasonablePasswordLength(int reasonableLength);
+
+ /**
+ * Password length that is expected to be reasonably safe.
+ * @since 3.4
+ */
+ int reasonablePasswordLength() const;
+
+ /**
+ * Set the password strength level below which a warning is given
+ * Value is in the range 0 to 99. Empty passwords score 0;
+ * non-empty passwords score up to 100, depending on their length and whether they
+ * contain numbers, mixed case letters and punctuation.
+ *
+ * Default: 1 - warn if the password has no discernable strength whatsoever
+ * @param warningLevel: The level below which a warning should be given.
+ * @since 3.4
+ */
+ void setPasswordStrengthWarningLevel(int warningLevel);
+
+ /**
+ * Password strength level below which a warning is given
+ * @since 3.4
+ */
+ int passwordStrengthWarningLevel() const;
+
+ /**
+ * Returns the password entered. The memory is freed in the destructor,
+ * so you should make a copy.
+ */
+ const char *password() const { return m_pEdit->password(); }
+
+ /**
+ * Clears the password input field. You might want to use this after the
+ * user failed to enter the correct password.
+ * @since 3.3
+ */
+ void clearPassword();
+
+ /**
+ * Returns true if the user wants to keep the password.
+ */
+ bool keep() const { return m_Keep; }
+
+ /**
+ * Pops up the dialog, asks the user for a password, and returns it.
+ *
+ * @param password The password is returned in this reference parameter.
+ * @param prompt A prompt for the password. This can be a few lines of
+ * information. The text is word broken to fit nicely in the dialog.
+ * @param keep Enable/disable a checkbox controlling password keeping.
+ * If you pass a null pointer, or a pointer to the value 0, the checkbox
+ * is not shown. If you pass a pointer to a nonzero value, the checkbox
+ * is shown and the result is stored in *keep.
+ * @return Result code: Accepted or Rejected.
+ */
+ static int getPassword(QCString &password, QString prompt, int *keep=0L);
+
+ /**
+ * Pops up the dialog, asks the user for a password and returns it. The
+ * user has to enter the password twice to make sure it was entered
+ * correctly.
+ *
+ * @param password The password is returned in this reference parameter.
+ * @param prompt A prompt for the password. This can be a few lines of
+ * information. The text is word broken to fit nicely in the dialog.
+ * @return Result code: Accepted or Rejected.
+ */
+ static int getNewPassword(QCString &password, QString prompt);
+
+ /**
+ * Static helper function that disables core dumps.
+ */
+ static void disableCoreDumps();
+
+protected slots:
+ void slotOk();
+ void slotCancel();
+ void slotKeep(bool);
+
+protected:
+
+ /**
+ * Virtual function that can be overridden to provide password
+ * checking in derived classes. It should return @p true if the
+ * password is valid, @p false otherwise.
+ */
+ virtual bool checkPassword(const char *) { return true; }
+
+private slots:
+ void enableOkBtn();
+
+private:
+ void init();
+ void erase();
+
+ int m_Keep, m_Type, m_Row;
+ QLabel *m_pHelpLbl;
+ QGridLayout *m_pGrid;
+ QWidget *m_pMain;
+ KPasswordEdit *m_pEdit, *m_pEdit2;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KPasswordDialogPrivate;
+ KPasswordDialogPrivate* const d;
+};
+
+
+#endif // __KPassDlg_h_included__
diff --git a/kdeui/kpassivepopup.cpp b/kdeui/kpassivepopup.cpp
new file mode 100644
index 000000000..9da71013b
--- /dev/null
+++ b/kdeui/kpassivepopup.cpp
@@ -0,0 +1,498 @@
+/*
+ * copyright : (C) 2001-2002 by Richard Moore
+ * copyright : (C) 2004-2005 by Sascha Cunz
+ * License : This file is released under the terms of the LGPL, version 2.
+ * email : rich@kde.org
+ * email : sascha.cunz@tiscali.de
+ */
+
+#include <kconfig.h>
+
+#include <qapplication.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qtimer.h>
+#include <qvbox.h>
+#include <qpainter.h>
+#include <qtooltip.h>
+#include <qbitmap.h>
+#include <qpointarray.h>
+
+#include <kdebug.h>
+#include <kdialog.h>
+#include <kpixmap.h>
+#include <kpixmapeffect.h>
+#include <kglobalsettings.h>
+
+#include "config.h"
+#ifdef Q_WS_X11
+#include <netwm.h>
+#endif
+
+#include "kpassivepopup.h"
+#include "kpassivepopup.moc"
+
+class KPassivePopup::Private
+{
+public:
+ int popupStyle;
+ QPointArray surround;
+ QPoint anchor;
+ QPoint fixedPosition;
+};
+
+static const int DEFAULT_POPUP_TYPE = KPassivePopup::Boxed;
+static const int DEFAULT_POPUP_TIME = 6*1000;
+static const int POPUP_FLAGS = Qt::WStyle_Customize | Qt::WDestructiveClose | Qt::WX11BypassWM
+ | Qt::WStyle_StaysOnTop | Qt::WStyle_Tool | Qt::WStyle_NoBorder;
+
+KPassivePopup::KPassivePopup( QWidget *parent, const char *name, WFlags f )
+ : QFrame( 0, name, f ? f : POPUP_FLAGS ),
+ window( parent ? parent->winId() : 0L ), msgView( 0 ), topLayout( 0 ),
+ hideDelay( DEFAULT_POPUP_TIME ), hideTimer( new QTimer( this, "hide_timer" ) ),
+ m_autoDelete( false )
+{
+ init( DEFAULT_POPUP_TYPE );
+}
+
+KPassivePopup::KPassivePopup( WId win, const char *name, WFlags f )
+ : QFrame( 0, name, f ? f : POPUP_FLAGS ),
+ window( win ), msgView( 0 ), topLayout( 0 ),
+ hideDelay( DEFAULT_POPUP_TIME ), hideTimer( new QTimer( this, "hide_timer" ) ),
+ m_autoDelete( false )
+{
+ init( DEFAULT_POPUP_TYPE );
+}
+
+KPassivePopup::KPassivePopup( int popupStyle, QWidget *parent, const char *name, WFlags f )
+ : QFrame( 0, name, f ? f : POPUP_FLAGS ),
+ window( parent ? parent->winId() : 0L ), msgView( 0 ), topLayout( 0 ),
+ hideDelay( DEFAULT_POPUP_TIME ), hideTimer( new QTimer( this, "hide_timer" ) ),
+ m_autoDelete( false )
+{
+ init( popupStyle );
+}
+
+KPassivePopup::KPassivePopup( int popupStyle, WId win, const char *name, WFlags f )
+ : QFrame( 0, name, f ? f : POPUP_FLAGS ),
+ window( win ), msgView( 0 ), topLayout( 0 ),
+ hideDelay( DEFAULT_POPUP_TIME ), hideTimer( new QTimer( this, "hide_timer" ) ),
+ m_autoDelete( false )
+{
+ init( popupStyle );
+}
+
+void KPassivePopup::init( int popupStyle )
+{
+ d = new Private;
+ d->popupStyle = popupStyle;
+ if( popupStyle == Boxed )
+ {
+ setFrameStyle( QFrame::Box| QFrame::Plain );
+ setLineWidth( 2 );
+ }
+ else if( popupStyle == Balloon )
+ {
+ setPalette(QToolTip::palette());
+ setAutoMask(TRUE);
+ }
+ connect( hideTimer, SIGNAL( timeout() ), SLOT( hide() ) );
+ connect( this, SIGNAL( clicked() ), SLOT( hide() ) );
+}
+
+KPassivePopup::~KPassivePopup()
+{
+ delete d;
+}
+
+void KPassivePopup::setView( QWidget *child )
+{
+ delete msgView;
+ msgView = child;
+
+ delete topLayout;
+ topLayout = new QVBoxLayout( this, d->popupStyle == Balloon ? 22 : KDialog::marginHint(), KDialog::spacingHint() );
+ topLayout->addWidget( msgView );
+ topLayout->activate();
+}
+
+void KPassivePopup::setView( const QString &caption, const QString &text,
+ const QPixmap &icon )
+{
+ // kdDebug() << "KPassivePopup::setView " << caption << ", " << text << endl;
+ setView( standardView( caption, text, icon, this ) );
+}
+
+QVBox * KPassivePopup::standardView( const QString& caption,
+ const QString& text,
+ const QPixmap& icon,
+ QWidget *parent )
+{
+ QVBox *vb = new QVBox( parent ? parent : this );
+ vb->setSpacing( KDialog::spacingHint() );
+
+ QHBox *hb=0;
+ if ( !icon.isNull() ) {
+ hb = new QHBox( vb );
+ hb->setMargin( 0 );
+ hb->setSpacing( KDialog::spacingHint() );
+ ttlIcon = new QLabel( hb, "title_icon" );
+ ttlIcon->setPixmap( icon );
+ ttlIcon->setAlignment( AlignLeft );
+ }
+
+ if ( !caption.isEmpty() ) {
+ ttl = new QLabel( caption, hb ? hb : vb, "title_label" );
+ QFont fnt = ttl->font();
+ fnt.setBold( true );
+ ttl->setFont( fnt );
+ ttl->setAlignment( Qt::AlignHCenter );
+ if ( hb )
+ hb->setStretchFactor( ttl, 10 ); // enforce centering
+ }
+
+ if ( !text.isEmpty() ) {
+ msg = new QLabel( text, vb, "msg_label" );
+ msg->setAlignment( AlignLeft );
+ }
+
+ return vb;
+}
+
+void KPassivePopup::setView( const QString &caption, const QString &text )
+{
+ setView( caption, text, QPixmap() );
+}
+
+void KPassivePopup::setTimeout( int delay )
+{
+ hideDelay = delay;
+ if( hideTimer->isActive() )
+ {
+ if( delay ) {
+ hideTimer->changeInterval( delay );
+ } else {
+ hideTimer->stop();
+ }
+ }
+}
+
+void KPassivePopup::setAutoDelete( bool autoDelete )
+{
+ m_autoDelete = autoDelete;
+}
+
+void KPassivePopup::mouseReleaseEvent( QMouseEvent *e )
+{
+ emit clicked();
+ emit clicked( e->pos() );
+}
+
+//
+// Main Implementation
+//
+
+void KPassivePopup::show()
+{
+ if ( size() != sizeHint() )
+ resize( sizeHint() );
+
+ if ( d->fixedPosition.isNull() )
+ positionSelf();
+ else {
+ if( d->popupStyle == Balloon )
+ setAnchor( d->fixedPosition );
+ else
+ move( d->fixedPosition );
+ }
+ QFrame::show();
+
+ int delay = hideDelay;
+ if ( delay < 0 ) {
+ delay = DEFAULT_POPUP_TIME;
+ }
+
+ if ( delay > 0 ) {
+ hideTimer->start( delay );
+ }
+}
+
+void KPassivePopup::show(const QPoint &p)
+{
+ d->fixedPosition = p;
+ show();
+}
+
+void KPassivePopup::hideEvent( QHideEvent * )
+{
+ hideTimer->stop();
+ if ( m_autoDelete )
+ deleteLater();
+}
+
+QRect KPassivePopup::defaultArea() const
+{
+#ifdef Q_WS_X11
+ NETRootInfo info( qt_xdisplay(),
+ NET::NumberOfDesktops |
+ NET::CurrentDesktop |
+ NET::WorkArea,
+ -1, false );
+ info.activate();
+ NETRect workArea = info.workArea( info.currentDesktop() );
+ QRect r;
+ r.setRect( workArea.pos.x, workArea.pos.y, 0, 0 ); // top left
+#else
+ // FIX IT
+ QRect r;
+ r.setRect( 100, 100, 200, 200 ); // top left
+#endif
+ return r;
+}
+
+void KPassivePopup::positionSelf()
+{
+ QRect target;
+
+#ifdef Q_WS_X11
+ if ( !window ) {
+ target = defaultArea();
+ }
+
+ else {
+ NETWinInfo ni( qt_xdisplay(), window, qt_xrootwin(),
+ NET::WMIconGeometry | NET::WMKDESystemTrayWinFor );
+
+ // Figure out where to put the popup. Note that we must handle
+ // windows that skip the taskbar cleanly
+ if ( ni.kdeSystemTrayWinFor() ) {
+ NETRect frame, win;
+ ni.kdeGeometry( frame, win );
+ target.setRect( win.pos.x, win.pos.y,
+ win.size.width, win.size.height );
+ }
+ else if ( ni.state() & NET::SkipTaskbar ) {
+ target = defaultArea();
+ }
+ else {
+ NETRect r = ni.iconGeometry();
+ target.setRect( r.pos.x, r.pos.y, r.size.width, r.size.height );
+ if ( target.isNull() ) { // bogus value, use the exact position
+ NETRect dummy;
+ ni.kdeGeometry( dummy, r );
+ target.setRect( r.pos.x, r.pos.y,
+ r.size.width, r.size.height);
+ }
+ }
+ }
+#else
+ target = defaultArea();
+#endif
+ moveNear( target );
+}
+
+void KPassivePopup::moveNear( QRect target )
+{
+ QPoint pos = target.topLeft();
+ int x = pos.x();
+ int y = pos.y();
+ int w = width();
+ int h = height();
+
+ QRect r = KGlobalSettings::desktopGeometry(QPoint(x+w/2,y+h/2));
+
+ if( d->popupStyle == Balloon )
+ {
+ // find a point to anchor to
+ if( x + w > r.width() ){
+ x = x + target.width();
+ }
+
+ if( y + h > r.height() ){
+ y = y + target.height();
+ }
+ } else
+ {
+ if ( x < r.center().x() )
+ x = x + target.width();
+ else
+ x = x - w;
+
+ // It's apparently trying to go off screen, so display it ALL at the bottom.
+ if ( (y + h) > r.bottom() )
+ y = r.bottom() - h;
+
+ if ( (x + w) > r.right() )
+ x = r.right() - w;
+ }
+ if ( y < r.top() )
+ y = r.top();
+
+ if ( x < r.left() )
+ x = r.left();
+
+ if( d->popupStyle == Balloon )
+ setAnchor( QPoint( x, y ) );
+ else
+ move( x, y );
+}
+
+void KPassivePopup::setAnchor(const QPoint &anchor)
+{
+ d->anchor = anchor;
+ updateMask();
+}
+
+void KPassivePopup::paintEvent( QPaintEvent* pe )
+{
+ if( d->popupStyle == Balloon )
+ {
+ QPainter p;
+ p.begin( this );
+ p.drawPolygon( d->surround );
+ } else
+ QFrame::paintEvent( pe );
+}
+
+void KPassivePopup::updateMask()
+{
+ // get screen-geometry for screen our anchor is on
+ // (geometry can differ from screen to screen!
+ QRect deskRect = KGlobalSettings::desktopGeometry(d->anchor);
+
+ int xh = 70, xl = 40;
+ if( width() < 80 )
+ xh = xl = 40;
+ else if( width() < 110 )
+ xh = width() - 40;
+
+ bool bottom = (d->anchor.y() + height()) > ((deskRect.y() + deskRect.height()-48));
+ bool right = (d->anchor.x() + width()) > ((deskRect.x() + deskRect.width()-48));
+
+ QPoint corners[4] = {
+ QPoint( width() - 50, 10 ),
+ QPoint( 10, 10 ),
+ QPoint( 10, height() - 50 ),
+ QPoint( width() - 50, height() - 50 )
+ };
+
+ QBitmap mask( width(), height(), true );
+ QPainter p( &mask );
+ QBrush brush( Qt::white, Qt::SolidPattern );
+ p.setBrush( brush );
+
+ int i = 0, z = 0;
+ for (; i < 4; ++i) {
+ QPointArray corner;
+ corner.makeArc(corners[i].x(), corners[i].y(), 40, 40, i * 16 * 90, 16 * 90);
+
+ d->surround.resize( z + corner.count() );
+ for (unsigned int s = 0; s < corner.count() - 1; s++) {
+ d->surround.setPoint( z++, corner[s] );
+ }
+
+ if (bottom && i == 2) {
+ if (right) {
+ d->surround.resize( z + 3 );
+ d->surround.setPoint( z++, QPoint( width() - xh, height() - 11 ) );
+ d->surround.setPoint( z++, QPoint( width() - 20, height() ) );
+ d->surround.setPoint( z++, QPoint( width() - xl, height() - 11 ) );
+ } else {
+ d->surround.resize( z + 3 );
+ d->surround.setPoint( z++, QPoint( xl, height() - 11 ) );
+ d->surround.setPoint( z++, QPoint( 20, height() ) );
+ d->surround.setPoint( z++, QPoint( xh, height() - 11 ) );
+ }
+ } else if (!bottom && i == 0) {
+ if (right) {
+ d->surround.resize( z + 3 );
+ d->surround.setPoint( z++, QPoint( width() - xl, 10 ) );
+ d->surround.setPoint( z++, QPoint( width() - 20, 0 ) );
+ d->surround.setPoint( z++, QPoint( width() - xh, 10 ) );
+ } else {
+ d->surround.resize( z + 3 );
+ d->surround.setPoint( z++, QPoint( xh, 10 ) );
+ d->surround.setPoint( z++, QPoint( 20, 0 ) );
+ d->surround.setPoint( z++, QPoint( xl, 10 ) );
+ }
+ }
+ }
+
+ d->surround.resize( z + 1 );
+ d->surround.setPoint( z, d->surround[0] );
+ p.drawPolygon( d->surround );
+ setMask(mask);
+
+ move( right ? d->anchor.x() - width() + 20 : ( d->anchor.x() < 11 ? 11 : d->anchor.x() - 20 ),
+ bottom ? d->anchor.y() - height() : ( d->anchor.y() < 11 ? 11 : d->anchor.y() ) );
+
+ update();
+}
+
+//
+// Convenience Methods
+//
+
+KPassivePopup *KPassivePopup::message( const QString &caption, const QString &text,
+ const QPixmap &icon,
+ QWidget *parent, const char *name, int timeout )
+{
+ return message( DEFAULT_POPUP_TYPE, caption, text, icon, parent, name, timeout );
+}
+
+KPassivePopup *KPassivePopup::message( const QString &text, QWidget *parent, const char *name )
+{
+ return message( DEFAULT_POPUP_TYPE, QString::null, text, QPixmap(), parent, name );
+}
+
+KPassivePopup *KPassivePopup::message( const QString &caption, const QString &text,
+ QWidget *parent, const char *name )
+{
+ return message( DEFAULT_POPUP_TYPE, caption, text, QPixmap(), parent, name );
+}
+
+KPassivePopup *KPassivePopup::message( const QString &caption, const QString &text,
+ const QPixmap &icon, WId parent, const char *name, int timeout )
+{
+ return message( DEFAULT_POPUP_TYPE, caption, text, icon, parent, name, timeout );
+}
+
+KPassivePopup *KPassivePopup::message( int popupStyle, const QString &caption, const QString &text,
+ const QPixmap &icon,
+ QWidget *parent, const char *name, int timeout )
+{
+ KPassivePopup *pop = new KPassivePopup( popupStyle, parent, name );
+ pop->setAutoDelete( true );
+ pop->setView( caption, text, icon );
+ pop->hideDelay = timeout;
+ pop->show();
+
+ return pop;
+}
+
+KPassivePopup *KPassivePopup::message( int popupStyle, const QString &text, QWidget *parent, const char *name )
+{
+ return message( popupStyle, QString::null, text, QPixmap(), parent, name );
+}
+
+KPassivePopup *KPassivePopup::message( int popupStyle, const QString &caption, const QString &text,
+ QWidget *parent, const char *name )
+{
+ return message( popupStyle, caption, text, QPixmap(), parent, name );
+}
+
+KPassivePopup *KPassivePopup::message( int popupStyle, const QString &caption, const QString &text,
+ const QPixmap &icon, WId parent, const char *name, int timeout )
+{
+ KPassivePopup *pop = new KPassivePopup( popupStyle, parent, name );
+ pop->setAutoDelete( true );
+ pop->setView( caption, text, icon );
+ pop->hideDelay = timeout;
+ pop->show();
+
+ return pop;
+}
+
+// Local Variables:
+// c-basic-offset: 4
+// End:
diff --git a/kdeui/kpassivepopup.h b/kdeui/kpassivepopup.h
new file mode 100644
index 000000000..40c1e789b
--- /dev/null
+++ b/kdeui/kpassivepopup.h
@@ -0,0 +1,363 @@
+// -*- c++ -*-
+
+/*
+ * Copyright : (C) 2001-2002 by Richard Moore
+ * Copyright : (C) 2004-2005 by Sascha Cunz
+ * License : This file is released under the terms of the LGPL, version 2.
+ * Email : rich@kde.org
+ * Email : sascha.cunz@tiscali.de
+ */
+
+#ifndef KPASSIVEPOPUP_H
+#define KPASSIVEPOPUP_H
+
+#include <qframe.h>
+
+#include <kdelibs_export.h>
+
+class QBoxLayout;
+class QTimer;
+class QLabel;
+class QVBox;
+
+/**
+ * @short A dialog-like popup that displays messages without interupting the user.
+ *
+ * The simplest uses of KPassivePopup are by using the various message() static
+ * methods. The position the popup appears at depends on the type of the parent window:
+ *
+ * @li Normal Windows: The popup is placed adjacent to the icon of the window.
+ * @li System Tray Windows: The popup is placed adjact to the system tray window itself.
+ * @li Skip Taskbar Windows: The popup is placed adjact to the window
+ * itself if it is visible, and at the edge of the desktop otherwise.
+ *
+ * You also have the option of calling show with a QPoint as a parameter that
+ * removes the automatic placing of KPassivePopup and shows it in the point you want.
+ *
+ * The most basic use of KPassivePopup displays a popup containing a piece of text:
+ * \code
+ * KPassivePopup::message( "This is the message", this );
+ * \endcode
+ * We can create popups with titles and icons too, as this example shows:
+ * \code
+ * QPixmap px;
+ * px.load( "hi32-app-logtracker.png" );
+ * KPassivePopup::message( "Some title", "This is the main text", px, this );
+ * \endcode
+ * For more control over the popup, you can use the setView(QWidget *) method
+ * to create a custom popup.
+ * \code
+ * KPassivePopup *pop = new KPassivePopup( parent );
+ *
+ * QVBox *vb = new QVBox( pop );
+ * (void) new QLabel( vb, "<b>Isn't this great?</b>" );
+ *
+ * QHBox *box = new QHBox( vb );
+ * (void) new QPushButton( box, "Yes" );
+ * (void) new QPushButton( box, "No" );
+ *
+ * pop->setView( vb );
+ * pop->show();
+ * \endcode
+ *
+ * @version $Id$
+ * @since 3.1
+ * @author Richard Moore, rich@kde.org
+ * @author Sascha Cunz, sascha.cunz@tiscali.de
+ */
+class KDEUI_EXPORT KPassivePopup : public QFrame
+{
+ Q_OBJECT
+ Q_PROPERTY (bool autoDelete READ autoDelete WRITE setAutoDelete )
+ Q_PROPERTY (int timeout READ timeout WRITE setTimeout )
+
+public:
+ /**
+ * Styles that a KPassivePopup can have.
+ * @since 3.5
+ */
+ enum PopupStyle
+ {
+ Boxed, ///< Information will appear in a framed box (default)
+ Balloon, ///< Information will appear in a comic-alike balloon
+ CustomStyle=128 ///< Ids greater than this are reserved for use by subclasses
+ };
+
+ /**
+ * Creates a popup for the specified widget.
+ */
+ KPassivePopup( QWidget *parent=0, const char *name=0, WFlags f=0 );
+
+ /**
+ * Creates a popup for the specified window.
+ */
+ KPassivePopup( WId parent, const char *name=0, WFlags f=0 );
+
+ /**
+ * Creates a popup for the specified widget.
+ * @since 3.5
+ */
+ KPassivePopup( int popupStyle, QWidget *parent=0, const char *name=0, WFlags f=0 );
+
+ /**
+ * Creates a popup for the specified window.
+ * @since 3.5
+ */
+ KPassivePopup( int popupStyle, WId parent, const char *name=0, WFlags f=0 );
+
+ /**
+ * Cleans up.
+ */
+ virtual ~KPassivePopup();
+
+ /**
+ * Sets the main view to be the specified widget (which must be a child of the popup).
+ */
+ void setView( QWidget *child );
+
+ /**
+ * Creates a standard view then calls setView(QWidget*) .
+ */
+ void setView( const QString &caption, const QString &text = QString::null );
+
+ /**
+ * Creates a standard view then calls setView(QWidget*) .
+ */
+ virtual void setView( const QString &caption, const QString &text, const QPixmap &icon );
+
+ /**
+ * Returns a widget that is used as standard view if one of the
+ * setView() methods taking the QString arguments is used.
+ * You can use the returned widget to customize the passivepopup while
+ * keeping the look similar to the "standard" passivepopups.
+ *
+ * After customizing the widget, pass it to setView( QWidget* )
+ *
+ * @param caption The window caption (title) on the popup
+ * @param text The text for the popup
+ * @param icon The icon to use for the popup
+ * @param parent The parent widget used for the returned QVBox. If left 0L,
+ * then "this", i.e. the passive popup object will be used.
+ *
+ * @return a QVBox containing the given arguments, looking like the
+ * standard passivepopups.
+ * @see setView( QWidget * )
+ * @see setView( const QString&, const QString& )
+ * @see setView( const QString&, const QString&, const QPixmap& )
+ */
+ QVBox * standardView( const QString& caption, const QString& text,
+ const QPixmap& icon, QWidget *parent = 0L );
+
+ /**
+ * Returns the main view.
+ */
+ QWidget *view() const { return msgView; }
+
+ /**
+ * Returns the delay before the popup is removed automatically.
+ */
+ int timeout() const { return hideDelay; }
+
+ /**
+ * Enables / disables auto-deletion of this widget when the timeout
+ * occurs.
+ * The default is false. If you use the class-methods message(),
+ * auto-delection is turned on by default.
+ */
+ virtual void setAutoDelete( bool autoDelete );
+
+ /**
+ * @returns true if the widget auto-deletes itself when the timeout occurs.
+ * @see setAutoDelete
+ */
+ bool autoDelete() const { return m_autoDelete; }
+
+ /**
+ * Sets the anchor of this balloon. The balloon tries automatically to adjust
+ * itself somehow around the point.
+ * @since 3.5
+ */
+ void setAnchor( const QPoint& anchor );
+
+ // TODO KDE4: give all the statics method a const QPoint p = QPoint() that in
+ // case the point is not null calls the show(cosnt QPoint &p) method instead
+ // the show() one.
+ /**
+ * Convenience method that displays popup with the specified message beside the
+ * icon of the specified widget.
+ * Note that the returned object is destroyed when it is hidden.
+ * @see setAutoDelete
+ */
+ static KPassivePopup *message( const QString &text, QWidget *parent, const char *name=0 );
+
+ /**
+ * Convenience method that displays popup with the specified caption and message
+ * beside the icon of the specified widget.
+ * Note that the returned object is destroyed when it is hidden.
+ * @see setAutoDelete
+ */
+ static KPassivePopup *message( const QString &caption, const QString &text,
+ QWidget *parent, const char *name=0 );
+
+ /**
+ * Convenience method that displays popup with the specified icon, caption and
+ * message beside the icon of the specified widget.
+ * Note that the returned object is destroyed when it is hidden.
+ * @see setAutoDelete
+ */
+ static KPassivePopup *message( const QString &caption, const QString &text,
+ const QPixmap &icon,
+ QWidget *parent, const char *name=0, int timeout = -1 );
+
+ /**
+ * Convenience method that displays popup with the specified icon, caption and
+ * message beside the icon of the specified window.
+ * Note that the returned object is destroyed when it is hidden.
+ * @see setAutoDelete
+ */
+ static KPassivePopup *message( const QString &caption, const QString &text,
+ const QPixmap &icon,
+ WId parent, const char *name=0, int timeout = -1 );
+
+ /**
+ * Convenience method that displays popup with the specified popup-style and message beside the
+ * icon of the specified widget.
+ * Note that the returned object is destroyed when it is hidden.
+ * @see setAutoDelete
+ */
+ static KPassivePopup *message( int popupStyle, const QString &text, QWidget *parent,
+ const char *name=0 );
+
+ /**
+ * Convenience method that displays popup with the specified popup-style, caption and message
+ * beside the icon of the specified widget.
+ * Note that the returned object is destroyed when it is hidden.
+ * @see setAutoDelete
+ */
+ static KPassivePopup *message( int popupStyle, const QString &caption, const QString &text,
+ QWidget *parent, const char *name=0 );
+
+ /**
+ * Convenience method that displays popup with the specified popup-style, icon, caption and
+ * message beside the icon of the specified widget.
+ * Note that the returned object is destroyed when it is hidden.
+ * @see setAutoDelete
+ */
+ static KPassivePopup *message( int popupStyle, const QString &caption, const QString &text,
+ const QPixmap &icon,
+ QWidget *parent, const char *name=0, int timeout = -1 );
+
+ /**
+ * Convenience method that displays popup with the specified popup-style, icon, caption and
+ * message beside the icon of the specified window.
+ * Note that the returned object is destroyed when it is hidden.
+ * @see setAutoDelete
+ */
+ static KPassivePopup *message( int popupStyle, const QString &caption, const QString &text,
+ const QPixmap &icon,
+ WId parent, const char *name=0, int timeout = -1 );
+
+
+public slots:
+ /**
+ * Sets the delay for the popup is removed automatically. Setting the delay to 0
+ * disables the timeout, if you're doing this, you may want to connect the
+ * clicked() signal to the hide() slot.
+ * Setting the delay to -1 makes it use the default value.
+ *
+ * @see timeout
+ */
+ void setTimeout( int delay );
+
+ /**
+ * Reimplemented to reposition the popup.
+ */
+ virtual void show();
+
+ /**
+ * Shows the popup in the given point
+ * @since 3.5
+ */
+ void show(const QPoint &p);
+
+signals:
+ /**
+ * Emitted when the popup is clicked.
+ */
+ void clicked();
+
+ /**
+ * Emitted when the popup is clicked.
+ */
+ void clicked( QPoint pos );
+
+protected:
+ /**
+ * This method positions the popup.
+ */
+ virtual void positionSelf();
+
+ /**
+ * Reimplemented to destroy the object when autoDelete() is
+ * enabled.
+ */
+ virtual void hideEvent( QHideEvent * );
+
+ /**
+ * Moves the popup to be adjacent to the icon of the specified rectangle.
+ */
+ void moveNear( QRect target );
+
+ /**
+ * Reimplemented to detect mouse clicks.
+ */
+ virtual void mouseReleaseEvent( QMouseEvent *e );
+
+ /**
+ * If no relative window (eg taskbar button, system tray window) is
+ * available, use this rectangle (pass it to moveNear()).
+ * Basically KWinModule::workArea() with width and height set to 0
+ * so that moveNear uses the upper-left position.
+ * @return The QRect to be passed to moveNear() if no other is
+ * available.
+ */
+ QRect defaultArea() const;
+
+ /**
+ * Updates the transparency mask. Unused if PopupStyle == Boxed
+ * @since 3.5
+ */
+ void updateMask();
+
+ /**
+ * Overwrite to paint the border when PopupStyle == Balloon.
+ * Unused if PopupStyle == Boxed
+ */
+ virtual void paintEvent( QPaintEvent* pe );
+
+private:
+ void init( int popupStyle );
+
+ WId window;
+ QWidget *msgView;
+ QBoxLayout *topLayout;
+ int hideDelay;
+ QTimer *hideTimer;
+
+ QLabel *ttlIcon;
+ QLabel *ttl;
+ QLabel *msg;
+
+ bool m_autoDelete;
+
+ /* @internal */
+ class Private;
+ Private *d;
+};
+
+#endif // KPASSIVEPOPUP_H
+
+// Local Variables:
+// c-basic-offset: 4
+// End:
+
diff --git a/kdeui/kpixmapio-perf.png b/kdeui/kpixmapio-perf.png
new file mode 100644
index 000000000..9720ccae4
--- /dev/null
+++ b/kdeui/kpixmapio-perf.png
Binary files differ
diff --git a/kdeui/kpixmapio.cpp b/kdeui/kpixmapio.cpp
new file mode 100644
index 000000000..fd2854fb0
--- /dev/null
+++ b/kdeui/kpixmapio.cpp
@@ -0,0 +1,908 @@
+/* vi: ts=8 sts=4 sw=4
+ *
+ *
+ * This file is part of the KDE project, module kdeui.
+ * Copyright (C) 2000 Geert Jansen <jansen@kde.org>.
+ *
+ * You can Freely distribute this program under the GNU Library General
+ * Public License. See the file "COPYING.LIB" for the exact licensing terms.
+ *
+ * kpixmapio.cpp: Fast pixmap <-> image conversion.
+ */
+
+#include "kpixmapio.h"
+#include "config.h"
+
+#include <qimage.h>
+#include <qpixmap.h>
+#include <qcolor.h>
+#include <qglobal.h>
+
+#include <kglobal.h>
+#include <kconfig.h>
+#include <kdebug.h>
+
+#include <sys/types.h>
+#ifdef Q_OS_UNIX
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif
+
+#ifdef Q_WS_X11
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#ifdef HAVE_MITSHM
+#include <X11/extensions/XShm.h>
+#endif
+#ifdef __osf__
+extern "C" int XShmQueryExtension(Display *display);
+#endif
+#else
+#undef HAVE_MITSHM
+#endif
+
+// d pointer
+
+struct KPixmapIOPrivate
+{
+ int shmsize;
+ int shmpolicy;
+ int threshold;
+ int bpp;
+ int byteorder;
+#ifdef Q_WS_X11
+ XImage *ximage;
+#ifdef HAVE_MITSHM
+ XShmSegmentInfo *shminfo;
+ bool first_try;
+#endif
+#else
+ void *ximage;
+#endif
+};
+
+
+// From Qt: Returns the position of the lowest set bit in val.
+
+typedef unsigned char uchar;
+typedef unsigned int uint;
+
+#ifdef HAVE_MITSHM
+static int lowest_bit(uint val)
+{
+ int i;
+ uint test = 1;
+ for (i=0; (!(val & test)) && i<32; i++, test<<=1);
+ return (i == 32) ? -1 : i;
+}
+#endif
+
+/*** KPixmapIO ***/
+
+KPixmapIO::KPixmapIO()
+{
+ m_bShm = false;
+ d = new KPixmapIOPrivate;
+
+#ifdef HAVE_MITSHM
+ setShmPolicy(ShmDontKeep);
+ KConfig *config = KGlobal::config();
+ if (!config->readBoolEntry("UseMitShm", true))
+ return;
+
+ int ignore;
+ if (XQueryExtension(qt_xdisplay(), "MIT-SHM", &ignore, &ignore, &ignore))
+ {
+ if (XShmQueryExtension(qt_xdisplay()))
+ m_bShm = true;
+ }
+ if (!m_bShm)
+ {
+ kdDebug(290) << k_lineinfo << "MIT-SHM not available!\n";
+ d->ximage = 0;
+ d->shminfo = 0;
+ d->shmsize = 0;
+ return;
+ }
+
+ // Sort out bit format. Create a temporary XImage for this.
+ d->shminfo = new XShmSegmentInfo;
+ d->ximage = XShmCreateImage(qt_xdisplay(), (Visual *) QPaintDevice::x11AppVisual(),
+ QPaintDevice::x11AppDepth(), ZPixmap, 0L, d->shminfo, 10, 10);
+ d->bpp = d->ximage->bits_per_pixel;
+ d->first_try = true;
+ int bpp = d->bpp;
+ if (d->ximage->byte_order == LSBFirst)
+ bpp++;
+ int red_shift = lowest_bit(d->ximage->red_mask);
+ int green_shift = lowest_bit(d->ximage->green_mask);
+ int blue_shift = lowest_bit(d->ximage->blue_mask);
+ XDestroyImage(d->ximage); d->ximage = 0L;
+ d->shmsize = 0;
+
+ // Offer discrete possibilities for the bitformat. Each will have its
+ // own routine. The general algorithm using bitshifts is much too slow;
+ // this has to be done for every pixel!
+
+ if ((bpp == 32) && (red_shift == 16) && (green_shift == 8) &&
+ (blue_shift == 0))
+ d->byteorder = bo32_ARGB;
+ else if ((bpp == 32) && (red_shift == 0) && (green_shift == 8) &&
+ (blue_shift == 16))
+ d->byteorder = bo32_BGRA;
+ else if ((bpp == 33) && (red_shift == 16) && (green_shift == 8) &&
+ (blue_shift == 0))
+ d->byteorder = bo32_BGRA;
+ else if ((bpp == 24) && (red_shift == 16) && (green_shift == 8) &&
+ (blue_shift == 0))
+ d->byteorder = bo24_RGB;
+ else if ((bpp == 24) && (red_shift == 0) && (green_shift == 8) &&
+ (blue_shift == 16))
+ d->byteorder = bo24_BGR;
+ else if ((bpp == 25) && (red_shift == 16) && (green_shift == 8) &&
+ (blue_shift == 0))
+ d->byteorder = bo24_BGR;
+ else if ((bpp == 16) && (red_shift == 11) && (green_shift == 5) &&
+ (blue_shift == 0))
+ d->byteorder = bo16_RGB_565;
+ else if ((bpp == 16) && (red_shift == 10) && (green_shift == 5) &&
+ (blue_shift == 0))
+ d->byteorder = bo16_RGB_555;
+ else if ((bpp == 17) && (red_shift == 11) && (green_shift == 5) &&
+ (blue_shift == 0))
+ d->byteorder = bo16_BGR_565;
+ else if ((bpp == 17) && (red_shift == 10) && (green_shift == 5) &&
+ (blue_shift == 0))
+ d->byteorder = bo16_BGR_555;
+ else if ((bpp == 8) || (bpp == 9))
+ d->byteorder = bo8;
+ else
+ {
+ m_bShm = false;
+ kdWarning(290) << "Byte order not supported!" << endl;
+ kdWarning(290) << "red = " << red_shift
+ << ", green = " << green_shift
+ << ", blue = " << blue_shift << endl;
+ kdWarning(290) << "Please report to <jansen@kde.org>\n";
+ }
+#else
+ d->shmsize = 0;
+ d->ximage = 0;
+#endif
+}
+
+
+KPixmapIO::~KPixmapIO()
+{
+ destroyXImage();
+ destroyShmSegment();
+#ifdef HAVE_MITSHM
+ delete d->shminfo;
+#endif
+ delete d;
+}
+
+
+QPixmap KPixmapIO::convertToPixmap(const QImage &img)
+{
+ int size = img.width() * img.height();
+ if (m_bShm && (img.depth() > 1) && (d->bpp > 8) && (size > d->threshold))
+ {
+ QPixmap dst(img.width(), img.height());
+ putImage(&dst, 0, 0, &img);
+ return dst;
+ } else
+ {
+ QPixmap dst;
+ dst.convertFromImage(img);
+ return dst;
+ }
+
+}
+
+
+QImage KPixmapIO::convertToImage(const QPixmap &pm)
+{
+ QImage image;
+ int size = pm.width() * pm.height();
+ if (m_bShm && (d->bpp >= 8) && (size > d->threshold))
+ image = getImage(&pm, 0, 0, pm.width(), pm.height());
+ else
+ image = pm.convertToImage();
+ return image;
+}
+
+
+void KPixmapIO::putImage(QPixmap *dst, const QPoint &offset,
+ const QImage *src)
+{
+ putImage(dst, offset.x(), offset.y(), src);
+}
+
+
+void KPixmapIO::putImage(QPixmap *dst, int dx, int dy, const QImage *src)
+{
+ int size = src->width() * src->height();
+ bool fallback = true;
+ if (m_bShm && (src->depth() > 1) && (d->bpp > 8) && (size > d->threshold))
+ {
+#ifdef HAVE_MITSHM
+ if( initXImage(src->width(), src->height()))
+ {
+ convertToXImage(*src);
+ XShmPutImage(qt_xdisplay(), dst->handle(), qt_xget_temp_gc(qt_xscreen(), false), d->ximage,
+ dx, dy, 0, 0, src->width(), src->height(), false);
+ // coolo: do we really need this here? I see no good for it
+ XSync(qt_xdisplay(), false);
+ doneXImage();
+ fallback = false;
+ }
+#endif
+ }
+ if( fallback )
+ {
+ QPixmap pix;
+ pix.convertFromImage(*src);
+ bitBlt(dst, dx, dy, &pix, 0, 0, pix.width(), pix.height());
+ }
+}
+
+
+QImage KPixmapIO::getImage(const QPixmap *src, const QRect &rect)
+{
+ return getImage(src, rect.x(), rect.y(), rect.width(), rect.height());
+}
+
+
+QImage KPixmapIO::getImage(const QPixmap *src, int sx, int sy, int sw, int sh)
+{
+ QImage image;
+ int size = src->width() * src->height();
+ bool fallback = true;
+ if ((m_bShm) && (d->bpp >= 8) && (size > d->threshold))
+ {
+#ifdef HAVE_MITSHM
+ if( initXImage(sw, sh))
+ {
+ XShmGetImage(qt_xdisplay(), src->handle(), d->ximage, sx, sy, AllPlanes);
+ image = convertFromXImage();
+ doneXImage();
+ fallback = false;
+ }
+#endif
+ }
+ if( fallback )
+ {
+ QPixmap pix(sw, sh);
+ bitBlt(&pix, 0, 0, src, sx, sy, sw, sh);
+ image = pix.convertToImage();
+ }
+ return image;
+}
+
+
+#ifdef HAVE_MITSHM
+
+void KPixmapIO::preAllocShm(int size)
+{
+ destroyXImage();
+ createShmSegment(size);
+}
+
+
+void KPixmapIO::setShmPolicy(int policy)
+{
+ switch (policy)
+ {
+ case ShmDontKeep:
+ d->shmpolicy = ShmDontKeep;
+ d->threshold = 5000;
+ break;
+ case ShmKeepAndGrow:
+ d->shmpolicy = ShmKeepAndGrow;
+ d->threshold = 2000;
+ break;
+ default:
+ break;
+ }
+}
+
+
+bool KPixmapIO::initXImage(int w, int h)
+{
+ if (d->ximage && (w == d->ximage->width) && (h == d->ximage->height))
+ return true;
+
+ if( !createXImage(w, h))
+ return false;
+ int size = d->ximage->bytes_per_line * d->ximage->height;
+ if (size > d->shmsize)
+ {
+ if( !createShmSegment(size))
+ {
+ destroyXImage();
+ return false;
+ }
+ }
+ d->ximage->data = d->shminfo->shmaddr;
+ return true;
+}
+
+
+void KPixmapIO::doneXImage()
+{
+ if (d->shmpolicy == ShmDontKeep)
+ {
+ destroyXImage();
+ destroyShmSegment();
+ }
+}
+
+
+void KPixmapIO::destroyXImage()
+{
+ if (d->ximage)
+ {
+ XDestroyImage(d->ximage);
+ d->ximage = 0L;
+ }
+}
+
+
+bool KPixmapIO::createXImage(int w, int h)
+{
+ destroyXImage();
+ d->ximage = XShmCreateImage(qt_xdisplay(), (Visual *) QPaintDevice::x11AppVisual(),
+ QPaintDevice::x11AppDepth(), ZPixmap, 0L, d->shminfo, w, h);
+ return d->ximage != None;
+}
+
+
+void KPixmapIO::destroyShmSegment()
+{
+ if (d->shmsize)
+ {
+ XShmDetach(qt_xdisplay(), d->shminfo);
+ shmdt(d->shminfo->shmaddr);
+ shmctl(d->shminfo->shmid, IPC_RMID, 0);
+ d->shmsize = 0;
+ }
+}
+
+static bool use_xshm = true;
+static unsigned long kpixmapio_serial;
+static int (*old_errhandler)(Display *dpy, XErrorEvent *ev) = 0;
+
+static int kpixmapio_errorhandler(Display *dpy, XErrorEvent *ev)
+{
+ if(ev->serial == kpixmapio_serial) {
+ /* assuming that xshm errors mean it can't be used at all
+ (e.g. remote display) */
+ use_xshm = false;
+ kdDebug(290) << "Disabling Xshm" << endl;
+ return 0;
+ } else {
+ // another error
+ return old_errhandler(dpy, ev);
+ }
+}
+
+bool KPixmapIO::createShmSegment(int size)
+{
+ destroyShmSegment();
+ d->shminfo->shmid = shmget(IPC_PRIVATE, size, IPC_CREAT|0600);
+ if ( d->shminfo->shmid < 0)
+ {
+ kdWarning(290) << "Could not get shared memory segment.\n";
+ m_bShm = false;
+ return false;
+ }
+
+ d->shminfo->shmaddr = (char *) shmat(d->shminfo->shmid, 0, 0);
+ if (d->shminfo->shmaddr == (char *)-1)
+ {
+ kdWarning(290) << "Could not attach shared memory segment.\n";
+ m_bShm = false;
+ shmctl(d->shminfo->shmid, IPC_RMID, 0);
+ return false;
+ }
+
+ d->shminfo->readOnly = false;
+
+ if (d->first_try) {
+ // make sure that we don't get errors of old stuff
+ XSync(qt_xdisplay(), False);
+ old_errhandler = XSetErrorHandler(kpixmapio_errorhandler);
+ kpixmapio_serial = NextRequest(qt_xdisplay());
+ }
+
+ if ( !XShmAttach(qt_xdisplay(), d->shminfo))
+ {
+ kdWarning() << "X-Server could not attach shared memory segment.\n";
+ m_bShm = false;
+ shmdt(d->shminfo->shmaddr);
+ shmctl(d->shminfo->shmid, IPC_RMID, 0);
+ }
+
+ if (d->first_try) {
+ XSync(qt_xdisplay(), false);
+
+ if (!use_xshm)
+ m_bShm = false;
+
+ XSetErrorHandler(old_errhandler);
+ d->first_try = false;
+ }
+ d->shmsize = size;
+
+ return m_bShm;
+}
+
+
+/*
+ * The following functions convertToXImage/convertFromXImage are a little
+ * long. This is because of speed, I want to get as much out of the inner
+ * loop as possible.
+ */
+
+QImage KPixmapIO::convertFromXImage()
+{
+ int x, y;
+ int width = d->ximage->width, height = d->ximage->height;
+ int bpl = d->ximage->bytes_per_line;
+ char *data = d->ximage->data;
+
+ QImage image;
+ if (d->bpp == 8)
+ {
+ image.create(width, height, 8);
+
+ // Query color map. Don't remove unused entries as a speed
+ // optmization.
+ int i, ncells = 256;
+ XColor *cmap = new XColor[ncells];
+ for (i=0; i<ncells; i++)
+ cmap[i].pixel = i;
+ XQueryColors(qt_xdisplay(), QPaintDevice::x11AppColormap(),
+ cmap, ncells);
+ image.setNumColors(ncells);
+ for (i=0; i<ncells; i++)
+ image.setColor(i, qRgb(cmap[i].red, cmap[i].green, cmap[i].blue >> 8));
+ } else
+ image.create(width, height, 32);
+
+ switch (d->byteorder)
+ {
+
+ case bo8:
+ {
+ for (y=0; y<height; y++)
+ memcpy(image.scanLine(y), data + y*bpl, width);
+ break;
+ }
+
+ case bo16_RGB_565:
+ case bo16_BGR_565:
+ {
+ Q_INT32 pixel, *src;
+ QRgb *dst, val;
+ for (y=0; y<height; y++)
+ {
+ src = (Q_INT32 *) (data + y*bpl);
+ dst = (QRgb *) image.scanLine(y);
+ for (x=0; x<width/2; x++)
+ {
+ pixel = *src++;
+ val = ((pixel & 0xf800) << 8) | ((pixel & 0x7e0) << 5) |
+ ((pixel & 0x1f) << 3);
+ *dst++ = val;
+ pixel >>= 16;
+ val = ((pixel & 0xf800) << 8) | ((pixel & 0x7e0) << 5) |
+ ((pixel & 0x1f) << 3);
+ *dst++ = val;
+ }
+ if (width%2)
+ {
+ pixel = *src++;
+ val = ((pixel & 0xf800) << 8) | ((pixel & 0x7e0) << 5) |
+ ((pixel & 0x1f) << 3);
+ *dst++ = val;
+ }
+ }
+ break;
+ }
+
+ case bo16_RGB_555:
+ case bo16_BGR_555:
+ {
+ Q_INT32 pixel, *src;
+ QRgb *dst, val;
+ for (y=0; y<height; y++)
+ {
+ src = (Q_INT32 *) (data + y*bpl);
+ dst = (QRgb *) image.scanLine(y);
+ for (x=0; x<width/2; x++)
+ {
+ pixel = *src++;
+ val = ((pixel & 0x7c00) << 9) | ((pixel & 0x3e0) << 6) |
+ ((pixel & 0x1f) << 3);
+ *dst++ = val;
+ pixel >>= 16;
+ val = ((pixel & 0x7c00) << 9) | ((pixel & 0x3e0) << 6) |
+ ((pixel & 0x1f) << 3);
+ *dst++ = val;
+ }
+ if (width%2)
+ {
+ pixel = *src++;
+ val = ((pixel & 0x7c00) << 9) | ((pixel & 0x3e0) << 6) |
+ ((pixel & 0x1f) << 3);
+ *dst++ = val;
+ }
+ }
+ break;
+ }
+
+ case bo24_RGB:
+ {
+ char *src;
+ QRgb *dst;
+ int w1 = width/4;
+ Q_INT32 d1, d2, d3;
+ for (y=0; y<height; y++)
+ {
+ src = data + y*bpl;
+ dst = (QRgb *) image.scanLine(y);
+ for (x=0; x<w1; x++)
+ {
+ d1 = *((Q_INT32 *)src);
+ d2 = *((Q_INT32 *)src + 1);
+ d3 = *((Q_INT32 *)src + 2);
+ src += 12;
+ *dst++ = d1;
+ *dst++ = (d1 >> 24) | (d2 << 8);
+ *dst++ = (d3 << 16) | (d2 >> 16);
+ *dst++ = d3 >> 8;
+ }
+ for (x=w1*4; x<width; x++)
+ {
+ d1 = *src++ << 16;
+ d1 += *src++ << 8;
+ d1 += *src++;
+ *dst++ = d1;
+ }
+ }
+ break;
+ }
+
+ case bo24_BGR:
+ {
+ char *src;
+ QRgb *dst;
+ int w1 = width/4;
+ Q_INT32 d1, d2, d3;
+ for (y=0; y<height; y++)
+ {
+ src = data + y*bpl;
+ dst = (QRgb *) image.scanLine(y);
+ for (x=0; x<w1; x++)
+ {
+ d1 = *((Q_INT32 *)src);
+ d2 = *((Q_INT32 *)src + 1);
+ d3 = *((Q_INT32 *)src + 2);
+ src += 12;
+ *dst++ = d1;
+ *dst++ = (d1 >> 24) | (d2 << 8);
+ *dst++ = (d3 << 16) | (d2 >> 16);
+ *dst++ = d3 >> 8;
+ }
+ for (x=w1*4; x<width; x++)
+ {
+ d1 = *src++;
+ d1 += *src++ << 8;
+ d1 += *src++ << 16;
+ *dst++ = d1;
+ }
+ }
+ break;
+ }
+
+ case bo32_ARGB:
+ case bo32_BGRA:
+ {
+ for (y=0; y<height; y++)
+ memcpy(image.scanLine(y), data + y*bpl, width*4);
+ break;
+ }
+
+ }
+
+ return image;
+}
+
+
+void KPixmapIO::convertToXImage(const QImage &img)
+{
+ int x, y;
+ int width = d->ximage->width, height = d->ximage->height;
+ int bpl = d->ximage->bytes_per_line;
+ char *data = d->ximage->data;
+
+ switch (d->byteorder)
+ {
+
+ case bo16_RGB_555:
+ case bo16_BGR_555:
+
+ if (img.depth() == 32)
+ {
+ QRgb *src, pixel;
+ Q_INT32 *dst, val;
+ for (y=0; y<height; y++)
+ {
+ src = (QRgb *) img.scanLine(y);
+ dst = (Q_INT32 *) (data + y*bpl);
+ for (x=0; x<width/2; x++)
+ {
+ pixel = *src++;
+ val = ((pixel & 0xf80000) >> 9) | ((pixel & 0xf800) >> 6) |
+ ((pixel & 0xff) >> 3);
+ pixel = *src++;
+ val |= (((pixel & 0xf80000) >> 9) | ((pixel & 0xf800) >> 6) |
+ ((pixel & 0xff) >> 3)) << 16;
+ *dst++ = val;
+ }
+ if (width%2)
+ {
+ pixel = *src++;
+ *((Q_INT16 *)dst) = ((pixel & 0xf80000) >> 9) |
+ ((pixel & 0xf800) >> 6) | ((pixel & 0xff) >> 3);
+ }
+ }
+ } else
+ {
+ uchar *src;
+ Q_INT32 val, *dst;
+ QRgb pixel, *clut = img.colorTable();
+ for (y=0; y<height; y++)
+ {
+ src = img.scanLine(y);
+ dst = (Q_INT32 *) (data + y*bpl);
+ for (x=0; x<width/2; x++)
+ {
+ pixel = clut[*src++];
+ val = ((pixel & 0xf80000) >> 9) | ((pixel & 0xf800) >> 6) |
+ ((pixel & 0xff) >> 3);
+ pixel = clut[*src++];
+ val |= (((pixel & 0xf80000) >> 9) | ((pixel & 0xf800) >> 6) |
+ ((pixel & 0xff) >> 3)) << 16;
+ *dst++ = val;
+ }
+ if (width%2)
+ {
+ pixel = clut[*src++];
+ *((Q_INT16 *)dst) = ((pixel & 0xf80000) >> 9) |
+ ((pixel & 0xf800) >> 6) | ((pixel & 0xff) >> 3);
+ }
+ }
+ }
+ break;
+
+ case bo16_RGB_565:
+ case bo16_BGR_565:
+
+ if (img.depth() == 32)
+ {
+ QRgb *src, pixel;
+ Q_INT32 *dst, val;
+ for (y=0; y<height; y++)
+ {
+ src = (QRgb *) img.scanLine(y);
+ dst = (Q_INT32 *) (data + y*bpl);
+ for (x=0; x<width/2; x++)
+ {
+ pixel = *src++;
+ val = ((pixel & 0xf80000) >> 8) | ((pixel & 0xfc00) >> 5) |
+ ((pixel & 0xff) >> 3);
+ pixel = *src++;
+ val |= (((pixel & 0xf80000) >> 8) | ((pixel & 0xfc00) >> 5) |
+ ((pixel & 0xff) >> 3)) << 16;
+ *dst++ = val;
+ }
+ if (width%2)
+ {
+ pixel = *src++;
+ *((Q_INT16 *)dst) = ((pixel & 0xf80000) >> 8) |
+ ((pixel & 0xfc00) >> 5) | ((pixel & 0xff) >> 3);
+ }
+ }
+ } else
+ {
+ uchar *src;
+ Q_INT32 val, *dst;
+ QRgb pixel, *clut = img.colorTable();
+ for (y=0; y<height; y++)
+ {
+ src = img.scanLine(y);
+ dst = (Q_INT32 *) (data + y*bpl);
+ for (x=0; x<width/2; x++)
+ {
+ pixel = clut[*src++];
+ val = ((pixel & 0xf80000) >> 8) | ((pixel & 0xfc00) >> 5) |
+ ((pixel & 0xff) >> 3);
+ pixel = clut[*src++];
+ val |= (((pixel & 0xf80000) >> 8) | ((pixel & 0xfc00) >> 5) |
+ ((pixel & 0xff) >> 3)) << 16;
+ *dst++ = val;
+ }
+ if (width%2)
+ {
+ pixel = clut[*src++];
+ *((Q_INT16 *)dst) = ((pixel & 0xf80000) >> 8) |
+ ((pixel & 0xfc00) >> 5) | ((pixel & 0xff) >> 3);
+ }
+ }
+ }
+ break;
+
+ case bo24_RGB:
+
+ if (img.depth() == 32)
+ {
+ char *dst;
+ int w1 = width/4;
+ QRgb *src, d1, d2, d3, d4;
+ for (y=0; y<height; y++)
+ {
+ src = (QRgb *) img.scanLine(y);
+ dst = data + y*bpl;
+ for (x=0; x<w1; x++)
+ {
+ d1 = (*src++ & 0xffffff);
+ d2 = (*src++ & 0xffffff);
+ d3 = (*src++ & 0xffffff);
+ d4 = (*src++ & 0xffffff);
+ *((Q_INT32 *)dst) = d1 | (d2 << 24);
+ *((Q_INT32 *)dst+1) = (d2 >> 8) | (d3 << 16);
+ *((Q_INT32 *)dst+2) = (d4 << 8) | (d3 >> 16);
+ dst += 12;
+ }
+ for (x=w1*4; x<width; x++)
+ {
+ d1 = *src++;
+ *dst++ = qRed(d1);
+ *dst++ = qGreen(d1);
+ *dst++ = qBlue(d1);
+ }
+ }
+ } else
+ {
+ uchar *src, *dst;
+ int w1 = width/4;
+ QRgb *clut = img.colorTable(), d1, d2, d3, d4;
+ for (y=0; y<height; y++)
+ {
+ src = img.scanLine(y);
+ dst = (uchar *) data + y*bpl;
+ for (x=0; x<w1; x++)
+ {
+ d1 = (clut[*src++] & 0xffffff);
+ d2 = (clut[*src++] & 0xffffff);
+ d3 = (clut[*src++] & 0xffffff);
+ d4 = (clut[*src++] & 0xffffff);
+ *((Q_INT32 *)dst) = d1 | (d2 << 24);
+ *((Q_INT32 *)dst+1) = (d2 >> 8) | (d3 << 16);
+ *((Q_INT32 *)dst+2) = (d4 << 8) | (d3 >> 16);
+ dst += 12;
+ }
+ for (x=w1*4; x<width; x++)
+ {
+ d1 = clut[*src++];
+ *dst++ = qRed(d1);
+ *dst++ = qGreen(d1);
+ *dst++ = qBlue(d1);
+ }
+ }
+ }
+ break;
+
+ case bo24_BGR:
+
+ if (img.depth() == 32)
+ {
+ char *dst;
+ QRgb *src, d1, d2, d3, d4;
+ int w1 = width/4;
+ for (y=0; y<height; y++)
+ {
+ src = (QRgb *) img.scanLine(y);
+ dst = data + y*bpl;
+ for (x=0; x<w1; x++)
+ {
+ d1 = (*src++ & 0xffffff);
+ d2 = (*src++ & 0xffffff);
+ d3 = (*src++ & 0xffffff);
+ d4 = (*src++ & 0xffffff);
+ *((Q_INT32 *)dst) = d1 | (d2 << 24);
+ *((Q_INT32 *)dst+1) = (d2 >> 8) | (d3 << 16);
+ *((Q_INT32 *)dst+2) = (d4 << 8) | (d3 >> 16);
+ dst += 12;
+ }
+ for (x=w1*4; x<width; x++)
+ {
+ d1 = *src++;
+ *dst++ = qBlue(d1);
+ *dst++ = qGreen(d1);
+ *dst++ = qRed(d1);
+ }
+ }
+ } else
+ {
+ uchar *src, *dst;
+ int w1 = width/4;
+ QRgb *clut = img.colorTable(), d1, d2, d3, d4;
+ for (y=0; y<height; y++)
+ {
+ src = img.scanLine(y);
+ dst = (uchar *) data + y*bpl;
+ for (x=0; x<w1; x++)
+ {
+ d1 = (clut[*src++] & 0xffffff);
+ d2 = (clut[*src++] & 0xffffff);
+ d3 = (clut[*src++] & 0xffffff);
+ d4 = (clut[*src++] & 0xffffff);
+ *((Q_INT32 *)dst) = d1 | (d2 << 24);
+ *((Q_INT32 *)dst+1) = (d2 >> 8) | (d3 << 16);
+ *((Q_INT32 *)dst+2) = (d4 << 8) | (d3 >> 16);
+ dst += 12;
+ }
+ for (x=w1*4; x<width; x++)
+ {
+ d1 = clut[*src++];
+ *dst++ = qBlue(d1);
+ *dst++ = qGreen(d1);
+ *dst++ = qRed(d1);
+ }
+ }
+ }
+ break;
+
+ case bo32_ARGB:
+ case bo32_BGRA:
+
+ if (img.depth() == 32)
+ {
+ for (y=0; y<height; y++)
+ memcpy(data + y*bpl, img.scanLine(y), width*4);
+ } else
+ {
+ uchar *src;
+ QRgb *dst, *clut = img.colorTable();
+ for (y=0; y<height; y++)
+ {
+ src = img.scanLine(y);
+ dst = (QRgb *) (data + y*bpl);
+ for (x=0; x<width; x++)
+ *dst++ = clut[*src++];
+ }
+ }
+ break;
+
+ }
+}
+
+#else
+
+void KPixmapIO::preAllocShm(int) {}
+void KPixmapIO::setShmPolicy(int) {}
+bool KPixmapIO::initXImage(int, int) { return false; }
+void KPixmapIO::doneXImage() {}
+bool KPixmapIO::createXImage(int, int) { return false; }
+void KPixmapIO::destroyXImage() {}
+bool KPixmapIO::createShmSegment(int) { return false; }
+void KPixmapIO::destroyShmSegment() {}
+QImage KPixmapIO::convertFromXImage() { return QImage(); }
+void KPixmapIO::convertToXImage(const QImage &) {}
+
+#endif // HAVE_MITSHM
diff --git a/kdeui/kpixmapio.h b/kdeui/kpixmapio.h
new file mode 100644
index 000000000..26d84d39c
--- /dev/null
+++ b/kdeui/kpixmapio.h
@@ -0,0 +1,185 @@
+/* vi: ts=8 sts=4 sw=4
+ *
+ *
+ * This file is part of the KDE project, module kdeui.
+ * Copyright (C) 2000 Geert Jansen <jansen@kde.org>
+ *
+ * You can Freely distribute this program under the GNU Library General
+ * Public License. See the file "COPYING.LIB" for the exact licensing terms.
+ */
+
+#ifndef __KPixmapIO_h_Included__
+#define __KPixmapIO_h_Included__
+
+#include <kdelibs_export.h>
+
+class QPixmap;
+class QImage;
+class QPoint;
+class QRect;
+struct KPixmapIOPrivate;
+/**
+ * @short Fast QImage to/from QPixmap conversion.
+ * @author Geert Jansen <jansen@kde.org>
+ * @version $Id$
+ *
+ * KPixmapIO implements a fast path for QPixmap to/from QImage conversions.
+ * It uses the MIT-SHM shared memory extension for this. If this extension is
+ * not available, it will fall back to standard Qt methods.
+ *
+ * <b>Typical usage:</b>\n
+ *
+ * You can use KPixmapIO for load/saving pixmaps.
+ *
+ * \code
+ * KPixmapIO io;
+ * pixmap = io.convertToPixmap(image);
+ * image = io.convertToImage(pixmap);
+ * \endcode
+ *
+ * It also has functionality for partially updating/saving pixmaps, see
+ * putImage and getImage.
+ *
+ * <b>KPixmapIO vs. Qt speed comparison</b>\n
+ *
+ * Speed measurements were taken. These show that usage of KPixmapIO for
+ * images up to a certain threshold size, offers no speed advantage over
+ * the Qt routines. Below you can see a plot of these measurements.
+ *
+ * @image html kpixmapio-perf.png "Performance of KPixmapIO"
+ *
+ * The threshold size, amongst other causes, is determined by the shared
+ * memory allocation policy. If the policy is @p ShmDontKeep, the
+ * shared memory segment is discarded right after usage, and thus needs to
+ * be allocated before each transfer. This introduces a a setup penalty not
+ * present when the policy is @p ShmKeepAndGrow. In this case the
+ * shared memory segment is kept and resized when necessary, until the
+ * KPixmapIO object is destroyed.
+ *
+ * The default policy is @p ShmDontKeep. This policy makes sense when
+ * loading pixmaps once. The corresponding threshold is taken at 5.000
+ * pixels as suggested by experiments. Below this threshold, KPixmapIO
+ * will not use shared memory and fall back on the Qt routines.
+ *
+ * When the policy is @p ShmKeepAndGrow, the threshold is taken at
+ * 2.000 pixels. Using this policy, you might want to use preAllocShm
+ * to pre-allocate a certain amount of shared memory, in order to avoid
+ * resizes. This allocation policy makes sense in a multimedia type
+ * application where you are constantly updating the screen.
+ *
+ * Above a couple times the threshold size, KPixmapIO's and Qt's speed become
+ * linear in the number of pixels, KPixmapIO being at least 2, and mostly around
+ * 4 times faster than Qt, depending on the screen and image depth.
+ *
+ * Speed difference seems to be the most at 16 bpp, followed by 32 and 24
+ * bpp respectively. This can be explained by the relatively poor
+ * implementation of 16 bit RGB packing in Qt, while at 32 bpp we need to
+ * transfer more data, and thus gain more, than at 24 bpp.
+ *
+ * <b>Conclusion:</b>\n
+ *
+ * For large pixmaps, there's a definite speed improvement when using
+ * KPixmapIO. On the other hand, there's no speed improvement for small
+ * pixmaps. When you know you're only transferring small pixmaps, there's no
+ * point in using it.
+ */
+
+class KDEUI_EXPORT KPixmapIO
+{
+public:
+ KPixmapIO();
+ ~KPixmapIO();
+
+ /**
+ * Convert an image to a pixmap.
+ * @param image The image to convert.
+ * @return The pixmap containing the image.
+ */
+ QPixmap convertToPixmap(const QImage &image);
+
+ /**
+ * Convert a pixmap to an image.
+ * @param pixmap The pixmap to convert.
+ * @return The image.
+ */
+ QImage convertToImage(const QPixmap &pixmap);
+
+ /**
+ * Bitblt an image onto a pixmap.
+ * @param dst The destination pixmap.
+ * @param dx Destination x offset.
+ * @param dy Destination y offset.
+ * @param src The image to load.
+ */
+ void putImage(QPixmap *dst, int dx, int dy, const QImage *src);
+
+ /**
+ * This function is identical to the one above. It only differs in the
+ * arguments it accepts.
+ */
+ void putImage(QPixmap *dst, const QPoint &offset, const QImage *src);
+
+ /**
+ * Transfer (a part of) a pixmap to an image.
+ * @param src The source pixmap.
+ * @param sx Source x offset.
+ * @param sy Source y offset.
+ * @param sw Source width.
+ * @param sh Source height.
+ * @return The image.
+ */
+ QImage getImage(const QPixmap *src, int sx, int sy, int sw, int sh);
+
+ /**
+ * This function is identical to the one above. It only differs in the
+ * arguments it accepts.
+ */
+ QImage getImage(const QPixmap *src, const QRect &rect);
+
+ /**
+ * Shared memory allocation policies.
+ */
+ enum ShmPolicies {
+ ShmDontKeep,
+ ShmKeepAndGrow
+ };
+
+ /**
+ * Set the shared memory allocation policy. See the introduction for
+ * KPixmapIO for a discussion.
+ * @param policy The alloction policy.
+ */
+ void setShmPolicy(int policy);
+
+ /**
+ * Pre-allocate shared memory. KPixmapIO will be able to transfer images
+ * up to this size without resizing.
+ * @param size The size of the image in @p pixels.
+ */
+ void preAllocShm(int size);
+
+private:
+ /*
+ * Supported XImage byte orders. The notation ARGB means bytes
+ * containing A:R:G:B succeed in memory.
+ */
+ enum ByteOrders {
+ bo32_ARGB, bo32_BGRA, bo24_RGB, bo24_BGR,
+ bo16_RGB_565, bo16_BGR_565, bo16_RGB_555,
+ bo16_BGR_555, bo8
+ };
+
+ bool m_bShm;
+ bool initXImage(int w, int h);
+ void doneXImage();
+ bool createXImage(int w, int h);
+ void destroyXImage();
+ bool createShmSegment(int size);
+ void destroyShmSegment();
+ void convertToXImage(const QImage &);
+ QImage convertFromXImage();
+private:
+ KPixmapIOPrivate* d;
+};
+
+#endif // __KPixmapIO_h_Included__
diff --git a/kdeui/kpixmapregionselectordialog.cpp b/kdeui/kpixmapregionselectordialog.cpp
new file mode 100644
index 000000000..ee9d185ea
--- /dev/null
+++ b/kdeui/kpixmapregionselectordialog.cpp
@@ -0,0 +1,127 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2004 Antonio Larrosa <larrosa@kde.org
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kpixmapregionselectordialog.h"
+#include <kdialogbase.h>
+#include <qdialog.h>
+#include <qdesktopwidget.h>
+#include <klocale.h>
+#include <kdialog.h>
+
+KPixmapRegionSelectorDialog::KPixmapRegionSelectorDialog(QWidget *parent,
+ const char *name, bool modal ) : KDialogBase(parent, name, modal, i18n("Select Region of Image"), Help|Ok|Cancel, Ok, true )
+{
+ QVBox *vbox=new QVBox(this);
+ new QLabel(i18n("Please click and drag on the image to select the region of interest:"), vbox);
+ m_pixmapSelectorWidget= new KPixmapRegionSelectorWidget(vbox);
+
+ vbox->setSpacing( KDialog::spacingHint() );
+
+ setMainWidget(vbox);
+}
+
+KPixmapRegionSelectorDialog::~KPixmapRegionSelectorDialog()
+{
+}
+
+QRect KPixmapRegionSelectorDialog::getSelectedRegion(const QPixmap &pixmap, QWidget *parent )
+{
+ KPixmapRegionSelectorDialog dialog(parent);
+
+ dialog.pixmapRegionSelectorWidget()->setPixmap(pixmap);
+
+ QDesktopWidget desktopWidget;
+ QRect screen=desktopWidget.availableGeometry();
+ dialog.pixmapRegionSelectorWidget()->setMaximumWidgetSize(
+ (int)(screen.width()*4.0/5), (int)(screen.height()*4.0/5));
+
+ int result = dialog.exec();
+
+ QRect rect;
+
+ if ( result == QDialog::Accepted )
+ rect = dialog.pixmapRegionSelectorWidget()->unzoomedSelectedRegion();
+
+ return rect;
+}
+
+QRect KPixmapRegionSelectorDialog::getSelectedRegion(const QPixmap &pixmap, int aspectRatioWidth, int aspectRatioHeight, QWidget *parent )
+{
+ KPixmapRegionSelectorDialog dialog(parent);
+
+ dialog.pixmapRegionSelectorWidget()->setPixmap(pixmap);
+ dialog.pixmapRegionSelectorWidget()->setSelectionAspectRatio(aspectRatioWidth,aspectRatioHeight);
+
+ QDesktopWidget desktopWidget;
+ QRect screen=desktopWidget.availableGeometry();
+ dialog.pixmapRegionSelectorWidget()->setMaximumWidgetSize(
+ (int)(screen.width()*4.0/5), (int)(screen.height()*4.0/5));
+
+ int result = dialog.exec();
+
+ QRect rect;
+
+ if ( result == QDialog::Accepted )
+ rect = dialog.pixmapRegionSelectorWidget()->unzoomedSelectedRegion();
+
+ return rect;
+}
+
+QImage KPixmapRegionSelectorDialog::getSelectedImage(const QPixmap &pixmap, QWidget *parent )
+{
+ KPixmapRegionSelectorDialog dialog(parent);
+
+ dialog.pixmapRegionSelectorWidget()->setPixmap(pixmap);
+
+ QDesktopWidget desktopWidget;
+ QRect screen=desktopWidget.availableGeometry();
+ dialog.pixmapRegionSelectorWidget()->setMaximumWidgetSize(
+ (int)(screen.width()*4.0/5), (int)(screen.height()*4.0/5));
+ int result = dialog.exec();
+
+ QImage image;
+
+ if ( result == QDialog::Accepted )
+ image = dialog.pixmapRegionSelectorWidget()->selectedImage();
+
+ return image;
+}
+
+QImage KPixmapRegionSelectorDialog::getSelectedImage(const QPixmap &pixmap, int aspectRatioWidth, int aspectRatioHeight, QWidget *parent )
+{
+ KPixmapRegionSelectorDialog dialog(parent);
+
+ dialog.pixmapRegionSelectorWidget()->setPixmap(pixmap);
+ dialog.pixmapRegionSelectorWidget()->setSelectionAspectRatio(aspectRatioWidth,aspectRatioHeight);
+
+ QDesktopWidget desktopWidget;
+ QRect screen=desktopWidget.availableGeometry();
+ dialog.pixmapRegionSelectorWidget()->setMaximumWidgetSize(
+ (int)(screen.width()*4.0/5), (int)(screen.height()*4.0/5));
+
+ int result = dialog.exec();
+
+ QImage image;
+
+ if ( result == QDialog::Accepted )
+ image = dialog.pixmapRegionSelectorWidget()->selectedImage();
+
+ return image;
+}
+
diff --git a/kdeui/kpixmapregionselectordialog.h b/kdeui/kpixmapregionselectordialog.h
new file mode 100644
index 000000000..88c315fe9
--- /dev/null
+++ b/kdeui/kpixmapregionselectordialog.h
@@ -0,0 +1,107 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2004 Antonio Larrosa <larrosa@kde.org
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __KPIXMAPREGIONSELECTORDIALOG_H__
+#define __KPIXMAPREGIONSELECTORDIALOG_H__
+
+#include <qimage.h>
+
+#include <kdialogbase.h>
+#include <kpixmapregionselectorwidget.h>
+
+/**
+ * A dialog that uses a KPixmapRegionSelectorWidget to allow the user
+ * to select a region of an image. If you want to use special features
+ * like forcing the selected area to have a fixed aspect ratio, you can use
+ * @see pixmapRegionSelectorWidget() to get the pointer to the
+ * KPixmapRegionSelectorWidget object and set the desired options there.
+ *
+ * There are some convenience methods that allow to easily show a dialog
+ * for the user to select a region of an image, and just care about the selected
+ * image.
+ *
+ * @author Antonio Larrosa <larrosa@kde.org>
+ * @since 3.4
+ */
+class KDEUI_EXPORT KPixmapRegionSelectorDialog : public KDialogBase
+{
+public:
+ /**
+ * The constructor of an empty KPixmapRegionSelectorDialog, you have to call
+ * later the setPixmap method of the KPixmapRegionSelectorWidget widget of
+ * the new object.
+ */
+ KPixmapRegionSelectorDialog(QWidget *parent=0L, const char *name=0L,
+ bool modal = false );
+ /**
+ * The destructor of the dialog
+ */
+ ~KPixmapRegionSelectorDialog();
+
+ /**
+ * @returns the KPixmapRegionSelectorWidget widget so that additional
+ * parameters can be set by using it.
+ */
+ KPixmapRegionSelectorWidget *pixmapRegionSelectorWidget() const
+ { return m_pixmapSelectorWidget; }
+
+ /**
+ * Creates a modal dialog, lets the user to select a region of the @p pixmap
+ * and returns when the dialog is closed.
+ *
+ * @returns the selected rectangle, or an invalid rectangle if the user
+ * pressed the Cancel button.
+ */
+ static QRect getSelectedRegion(const QPixmap &pixmap, QWidget *parent = 0L );
+
+ /**
+ * Creates a modal dialog, lets the user to select a region of the @p pixmap
+ * with the same aspect ratio than @p aspectRatioWidth x @p aspectRatioHeight
+ * and returns when the dialog is closed.
+ *
+ * @returns the selected rectangle, or an invalid rectangle if the user
+ * pressed the Cancel button.
+ */
+ static QRect getSelectedRegion(const QPixmap &pixmap, int aspectRatioWidth, int aspectRatioHeight, QWidget *parent = 0L );
+
+ /**
+ * Creates a modal dialog, lets the user to select a region of the @p pixmap
+ * and returns when the dialog is closed.
+ *
+ * @returns the selected image, or an invalid image if the user
+ * pressed the Cancel button.
+ */
+ static QImage getSelectedImage(const QPixmap &pixmap, QWidget *parent = 0L );
+
+ /**
+ * Creates a modal dialog, lets the user to select a region of the @p pixmap
+ * with the same aspect ratio than @p aspectRatioWidth x @p aspectRatioHeight
+ * and returns when the dialog is closed.
+ *
+ * @returns the selected image, or an invalid image if the user
+ * pressed the Cancel button.
+ */
+ static QImage getSelectedImage(const QPixmap &pixmap, int aspectRatioWidth, int aspectRatioHeight, QWidget *parent = 0L );
+
+protected:
+ KPixmapRegionSelectorWidget *m_pixmapSelectorWidget;
+};
+
+
+#endif
diff --git a/kdeui/kpixmapregionselectorwidget.cpp b/kdeui/kpixmapregionselectorwidget.cpp
new file mode 100644
index 000000000..da2be5f92
--- /dev/null
+++ b/kdeui/kpixmapregionselectorwidget.cpp
@@ -0,0 +1,450 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2004 Antonio Larrosa <larrosa@kde.org
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+/* NOTE: There are two copies of this .h and the .cpp file, with subtle differences.
+ * One copy is in kdelibs/kdeui, and the other copy is in kdepim/libkdepim
+ * This is because kdepim has to remain backwards compatible. Any changes
+ * to either file should be made to the other.
+ */
+
+#include "kpixmapregionselectorwidget.h"
+#include <qpainter.h>
+#include <qcolor.h>
+#include <qimage.h>
+#include <qlayout.h>
+#include <kimageeffect.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kpopupmenu.h>
+#include <kaction.h>
+#include <stdlib.h>
+#include <qcursor.h>
+#include <qapplication.h>
+
+KPixmapRegionSelectorWidget::KPixmapRegionSelectorWidget( QWidget *parent,
+ const char *name) : QWidget( parent, name)
+{
+ QHBoxLayout * hboxLayout=new QHBoxLayout( this );
+
+ hboxLayout->addStretch();
+ QVBoxLayout * vboxLayout=new QVBoxLayout( hboxLayout );
+
+ vboxLayout->addStretch();
+ m_label = new QLabel(this, "pixmapHolder");
+ m_label->setBackgroundMode( Qt::NoBackground );
+ m_label->installEventFilter( this );
+
+ vboxLayout->addWidget(m_label);
+ vboxLayout->addStretch();
+
+ hboxLayout->addStretch();
+
+ m_forcedAspectRatio=0;
+
+ m_zoomFactor=1.0;
+}
+
+KPixmapRegionSelectorWidget::~KPixmapRegionSelectorWidget()
+{
+}
+
+void KPixmapRegionSelectorWidget::setPixmap( const QPixmap &pixmap )
+{
+ Q_ASSERT(!pixmap.isNull()); //This class isn't designed to deal with null pixmaps.
+ m_originalPixmap = pixmap;
+ m_unzoomedPixmap = pixmap;
+ m_label->setPixmap( pixmap );
+ resetSelection();
+}
+
+void KPixmapRegionSelectorWidget::resetSelection()
+{
+ m_selectedRegion = m_originalPixmap.rect();
+ updatePixmap();
+}
+
+QRect KPixmapRegionSelectorWidget::selectedRegion() const
+{
+ return m_selectedRegion;
+}
+
+void KPixmapRegionSelectorWidget::setSelectedRegion(const QRect &rect)
+{
+ if (!rect.isValid()) resetSelection();
+ else
+ {
+ m_selectedRegion=rect;
+ updatePixmap();
+
+ QRect r=unzoomedSelectedRegion();
+ }
+}
+
+void KPixmapRegionSelectorWidget::updatePixmap()
+{
+ Q_ASSERT(!m_originalPixmap.isNull()); if(m_originalPixmap.isNull()) { m_label->setPixmap(m_originalPixmap); return; }
+ if (m_selectedRegion.width()>m_originalPixmap.width()) m_selectedRegion.setWidth( m_originalPixmap.width() );
+ if (m_selectedRegion.height()>m_originalPixmap.height()) m_selectedRegion.setHeight( m_originalPixmap.height() );
+
+ QPainter painter;
+ if (m_linedPixmap.isNull())
+ {
+ m_linedPixmap = m_originalPixmap;
+
+ painter.begin(&m_linedPixmap);
+ painter.setRasterOp( Qt::XorROP );
+ painter.fillRect(0,0,m_linedPixmap.width(), m_linedPixmap.height(),
+ QBrush( QColor(255,255,255), Qt::BDiagPattern) );
+ painter.end();
+
+ QImage image=m_linedPixmap.convertToImage();
+ image=KImageEffect::fade(image, (float)0.4, QColor(0,0,0));
+ m_linedPixmap.convertFromImage(image);
+ }
+
+ QPixmap pixmap = m_linedPixmap;
+
+ painter.begin(&pixmap);
+ painter.drawPixmap( m_selectedRegion.topLeft(),
+ m_originalPixmap, m_selectedRegion );
+
+ painter.setPen( QColor(255,255,255) );
+ painter.setRasterOp( Qt::XorROP );
+
+ painter.drawRect( m_selectedRegion );
+
+ painter.end();
+
+ m_label->setPixmap(pixmap);
+}
+
+
+KPopupMenu *KPixmapRegionSelectorWidget::createPopupMenu()
+{
+ KPopupMenu *popup=new KPopupMenu(this, "PixmapRegionSelectorPopup");
+ popup->insertTitle(i18n("Image Operations"));
+
+ KAction *action = new KAction(i18n("&Rotate Clockwise"), "rotate_cw",
+ 0, this, SLOT(rotateClockwise()),
+ popup, "rotateclockwise");
+ action->plug(popup);
+
+ action = new KAction(i18n("Rotate &Counterclockwise"), "rotate_ccw",
+ 0, this, SLOT(rotateCounterclockwise()),
+ popup, "rotatecounterclockwise");
+ action->plug(popup);
+
+/*
+ I wonder if it would be appropiate to have here an "Open with..." option to
+ edit the image (antlarr)
+*/
+ return popup;
+}
+
+void KPixmapRegionSelectorWidget::rotate(KImageEffect::RotateDirection direction)
+{
+ int w=m_originalPixmap.width();
+ int h=m_originalPixmap.height();
+ QImage img=m_unzoomedPixmap.convertToImage();
+ img= KImageEffect::rotate(img, direction);
+ m_unzoomedPixmap.convertFromImage(img);
+
+ img=m_originalPixmap.convertToImage();
+ img= KImageEffect::rotate(img, direction);
+ m_originalPixmap.convertFromImage(img);
+
+ m_linedPixmap=QPixmap();
+
+ if (m_forcedAspectRatio>0 && m_forcedAspectRatio!=1)
+ resetSelection();
+ else
+ {
+ switch (direction)
+ {
+ case ( KImageEffect::Rotate90 ):
+ {
+ int x=h-m_selectedRegion.y()-m_selectedRegion.height();
+ int y=m_selectedRegion.x();
+ m_selectedRegion.setRect(x, y, m_selectedRegion.height(), m_selectedRegion.width() );
+ updatePixmap();
+ } break;
+ case ( KImageEffect::Rotate270 ):
+ {
+ int x=m_selectedRegion.y();
+ int y=w-m_selectedRegion.x()-m_selectedRegion.width();
+ m_selectedRegion.setRect(x, y, m_selectedRegion.height(), m_selectedRegion.width() );
+ updatePixmap();
+ } break;
+ default: resetSelection();
+ }
+ }
+}
+
+void KPixmapRegionSelectorWidget::rotateClockwise()
+{
+ rotate(KImageEffect::Rotate90);
+}
+
+void KPixmapRegionSelectorWidget::rotateCounterclockwise()
+{
+ rotate(KImageEffect::Rotate270);
+}
+
+bool KPixmapRegionSelectorWidget::eventFilter(QObject *obj, QEvent *ev)
+{
+ if ( ev->type() == QEvent::MouseButtonPress )
+ {
+ QMouseEvent *mev= (QMouseEvent *)(ev);
+ //kdDebug() << QString("click at %1,%2").arg( mev->x() ).arg( mev->y() ) << endl;
+
+ if ( mev->button() == RightButton )
+ {
+ KPopupMenu *popup = createPopupMenu( );
+ popup->exec( mev->globalPos() );
+ delete popup;
+ return TRUE;
+ };
+
+ QCursor cursor;
+
+ if ( m_selectedRegion.contains( mev->pos() )
+ && m_selectedRegion!=m_originalPixmap.rect() )
+ {
+ m_state=Moving;
+ cursor.setShape( Qt::SizeAllCursor );
+ }
+ else
+ {
+ m_state=Resizing;
+ cursor.setShape( Qt::CrossCursor );
+ }
+ QApplication::setOverrideCursor(cursor);
+
+ m_tempFirstClick=mev->pos();
+
+
+ return TRUE;
+ }
+
+ if ( ev->type() == QEvent::MouseMove )
+ {
+ QMouseEvent *mev= (QMouseEvent *)(ev);
+
+ //kdDebug() << QString("move to %1,%2").arg( mev->x() ).arg( mev->y() ) << endl;
+
+ if ( m_state == Resizing )
+ {
+ setSelectedRegion (
+ calcSelectionRectangle( m_tempFirstClick, mev->pos() ) );
+ }
+ else if (m_state == Moving )
+ {
+ int mevx = mev->x();
+ int mevy = mev->y();
+ bool mouseOutside=false;
+ if ( mevx < 0 )
+ {
+ m_selectedRegion.moveBy(-m_selectedRegion.x(),0);
+ mouseOutside=true;
+ }
+ else if ( mevx > m_originalPixmap.width() )
+ {
+ m_selectedRegion.moveBy(m_originalPixmap.width()-m_selectedRegion.width()-m_selectedRegion.x(),0);
+ mouseOutside=true;
+ }
+ if ( mevy < 0 )
+ {
+ m_selectedRegion.moveBy(0,-m_selectedRegion.y());
+ mouseOutside=true;
+ }
+ else if ( mevy > m_originalPixmap.height() )
+ {
+ m_selectedRegion.moveBy(0,m_originalPixmap.height()-m_selectedRegion.height()-m_selectedRegion.y());
+ mouseOutside=true;
+ }
+ if (mouseOutside) { updatePixmap(); return TRUE; };
+
+ m_selectedRegion.moveBy( mev->x()-m_tempFirstClick.x(),
+ mev->y()-m_tempFirstClick.y() );
+
+ // Check that the region has not fallen outside the image
+ if (m_selectedRegion.x() < 0)
+ m_selectedRegion.moveBy(-m_selectedRegion.x(),0);
+ else if (m_selectedRegion.right() > m_originalPixmap.width())
+ m_selectedRegion.moveBy(-(m_selectedRegion.right()-m_originalPixmap.width()),0);
+
+ if (m_selectedRegion.y() < 0)
+ m_selectedRegion.moveBy(0,-m_selectedRegion.y());
+ else if (m_selectedRegion.bottom() > m_originalPixmap.height())
+ m_selectedRegion.moveBy(0,-(m_selectedRegion.bottom()-m_originalPixmap.height()));
+
+ m_tempFirstClick=mev->pos();
+ updatePixmap();
+ }
+ return TRUE;
+ }
+
+ if ( ev->type() == QEvent::MouseButtonRelease )
+ {
+ QMouseEvent *mev= (QMouseEvent *)(ev);
+
+ if ( m_state == Resizing && mev->pos() == m_tempFirstClick)
+ resetSelection();
+
+ m_state=None;
+ QApplication::restoreOverrideCursor();
+
+ return TRUE;
+ }
+
+ QWidget::eventFilter(obj, ev);
+ return FALSE;
+}
+
+QRect KPixmapRegionSelectorWidget::calcSelectionRectangle( const QPoint & startPoint, const QPoint & _endPoint )
+{
+ QPoint endPoint = _endPoint;
+ if ( endPoint.x() < 0 ) endPoint.setX(0);
+ else if ( endPoint.x() > m_originalPixmap.width() ) endPoint.setX(m_originalPixmap.width());
+ if ( endPoint.y() < 0 ) endPoint.setY(0);
+ else if ( endPoint.y() > m_originalPixmap.height() ) endPoint.setY(m_originalPixmap.height());
+ int w=abs(startPoint.x()-endPoint.x());
+ int h=abs(startPoint.y()-endPoint.y());
+
+ if (m_forcedAspectRatio>0)
+ {
+ double aspectRatio=w/double(h);
+
+ if (aspectRatio>m_forcedAspectRatio)
+ h=(int)(w/m_forcedAspectRatio);
+ else
+ w=(int)(h*m_forcedAspectRatio);
+ }
+
+ int x,y;
+ if ( startPoint.x() < endPoint.x() )
+ x=startPoint.x();
+ else
+ x=startPoint.x()-w;
+ if ( startPoint.y() < endPoint.y() )
+ y=startPoint.y();
+ else
+ y=startPoint.y()-h;
+
+ if (x<0)
+ {
+ w+=x;
+ x=0;
+ h=(int)(w/m_forcedAspectRatio);
+
+ if ( startPoint.y() > endPoint.y() )
+ y=startPoint.y()-h;
+ }
+ else if (x+w>m_originalPixmap.width())
+ {
+ w=m_originalPixmap.width()-x;
+ h=(int)(w/m_forcedAspectRatio);
+
+ if ( startPoint.y() > endPoint.y() )
+ y=startPoint.y()-h;
+ }
+ if (y<0)
+ {
+ h+=y;
+ y=0;
+ w=(int)(h*m_forcedAspectRatio);
+
+ if ( startPoint.x() > endPoint.x() )
+ x=startPoint.x()-w;
+ }
+ else if (y+h>m_originalPixmap.height())
+ {
+ h=m_originalPixmap.height()-y;
+ w=(int)(h*m_forcedAspectRatio);
+
+ if ( startPoint.x() > endPoint.x() )
+ x=startPoint.x()-w;
+ }
+
+ return QRect(x,y,w,h);
+}
+
+QRect KPixmapRegionSelectorWidget::unzoomedSelectedRegion() const
+{
+ return QRect((int)(m_selectedRegion.x()/m_zoomFactor),
+ (int)(m_selectedRegion.y()/m_zoomFactor),
+ (int)(m_selectedRegion.width()/m_zoomFactor),
+ (int)(m_selectedRegion.height()/m_zoomFactor));
+}
+
+QImage KPixmapRegionSelectorWidget::selectedImage() const
+{
+ QImage origImage=m_unzoomedPixmap.convertToImage();
+ return origImage.copy(unzoomedSelectedRegion());
+}
+
+void KPixmapRegionSelectorWidget::setSelectionAspectRatio(int width, int height)
+{
+ m_forcedAspectRatio=width/double(height);
+}
+
+void KPixmapRegionSelectorWidget::setFreeSelectionAspectRatio()
+{
+ m_forcedAspectRatio=0;
+}
+
+void KPixmapRegionSelectorWidget::setMaximumWidgetSize(int width, int height)
+{
+ m_maxWidth=width;
+ m_maxHeight=height;
+
+ m_originalPixmap=m_unzoomedPixmap;
+ if (m_selectedRegion == m_originalPixmap.rect()) m_selectedRegion=QRect();
+
+// kdDebug() << QString(" original Pixmap :") << m_originalPixmap.rect() << endl;
+// kdDebug() << QString(" unzoomed Pixmap : %1 x %2 ").arg(m_unzoomedPixmap.width()).arg(m_unzoomedPixmap.height()) << endl;
+
+ if ( !m_originalPixmap.isNull() &&
+ ( m_originalPixmap.width() > m_maxWidth ||
+ m_originalPixmap.height() > m_maxHeight ) )
+ {
+ /* We have to resize the pixmap to get it complete on the screen */
+ QImage image=m_originalPixmap.convertToImage();
+ m_originalPixmap.convertFromImage( image.smoothScale( width, height, QImage::ScaleMin ) );
+ double oldZoomFactor = m_zoomFactor;
+ m_zoomFactor=m_originalPixmap.width()/(double)m_unzoomedPixmap.width();
+
+ if (m_selectedRegion.isValid())
+ {
+ m_selectedRegion=
+ QRect((int)(m_selectedRegion.x()*m_zoomFactor/oldZoomFactor),
+ (int)(m_selectedRegion.y()*m_zoomFactor/oldZoomFactor),
+ (int)(m_selectedRegion.width()*m_zoomFactor/oldZoomFactor),
+ (int)(m_selectedRegion.height()*m_zoomFactor/oldZoomFactor) );
+ }
+ }
+
+ if (!m_selectedRegion.isValid()) m_selectedRegion = m_originalPixmap.rect();
+
+ m_linedPixmap=QPixmap();
+ updatePixmap();
+ resize(m_label->width(), m_label->height());
+}
+
+#include "kpixmapregionselectorwidget.moc"
diff --git a/kdeui/kpixmapregionselectorwidget.h b/kdeui/kpixmapregionselectorwidget.h
new file mode 100644
index 000000000..c865aa2a8
--- /dev/null
+++ b/kdeui/kpixmapregionselectorwidget.h
@@ -0,0 +1,170 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2004 Antonio Larrosa <larrosa@kde.org
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __KPIXMAPREGIONSELECTORWIDGET_H__
+#define __KPIXMAPREGIONSELECTORWIDGET_H__
+#include <qvbox.h>
+#include <qpixmap.h>
+#include <qrect.h>
+#include <qlabel.h>
+#include <kimageeffect.h>
+
+class KPopupMenu;
+
+#include <kdelibs_export.h>
+
+/**
+ * KPixmapRegionSelectorWidget is a widget that shows a picture and provides the
+ * user with a friendly way to select a rectangular subregion of the pixmap.
+ *
+ * NOTE: There are two copies of this .h and the .cpp file, with subtle differences.
+ * One copy is in kdelibs/kdeui, and the other copy is in kdepim/libkdepim
+ * This is because kdepim has to remain backwards compatible. Any changes
+ * to either file should be made to the other.
+ *
+ * @author Antonio Larrosa <larrosa@kde.org>
+ * @since 3.4
+ */
+class KDEUI_EXPORT KPixmapRegionSelectorWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ /**
+ * Constructor for a KPixmapRegionSelectorWidget.
+ */
+ KPixmapRegionSelectorWidget( QWidget *parent = 0L, const char *name=0L);
+
+ /**
+ * Destructor for a KPixmapRegionSelectorWidget
+ */
+ ~KPixmapRegionSelectorWidget();
+
+ /**
+ * Sets the pixmap which will be shown for the user to select a region from.
+ * @param pixmap The pixmap. Must be non-null.
+ *
+ */
+ void setPixmap( const QPixmap &pixmap );
+
+ /**
+ * @return the original whole pixmap that we're using in this widget as the
+ * pixmap the user is selecting a region from.
+ */
+ QPixmap pixmap() const { return m_unzoomedPixmap; }
+
+ /**
+ * Sets the selected region to be @p rect (in zoomed pixmap coordinates)
+ */
+ void setSelectedRegion(const QRect &rect);
+
+ /**
+ * Returns the selected region ( in zoomed pixmap coordinates )
+ */
+ QRect selectedRegion() const;
+
+ /**
+ * Returns the selected region ( in unzoomed, original pixmap coordinates )
+ */
+ QRect unzoomedSelectedRegion() const;
+
+ /**
+ * Resets the selection to use the whole image
+ */
+ void resetSelection();
+
+ /**
+ * @returns a QImage object with just the region the user selected from the
+ * image
+ */
+ QImage selectedImage() const;
+
+ /**
+ * Sets the aspect ration that the selected subimage should have. The way to
+ * select it, is specifying an example valid @p width and @p height.
+ * @see setFreeSelectionAspectRatio()
+ */
+ void setSelectionAspectRatio(int width, int height);
+
+ /**
+ * Allows the user to do a selection which has any aspect ratio. This is
+ * the default.
+ * @see setSelectionAspectRatio()
+ */
+ void setFreeSelectionAspectRatio();
+
+ /**
+ * Sets the maximum size for the widget. If the image is larger than this
+ * (either horizontally or vertically), it's scaled to adjust to the maximum
+ * size (preserving the aspect ratio)
+ */
+ void setMaximumWidgetSize( int width, int height );
+
+ /**
+ * Rotates the image as specified by the @p direction parameter, also tries
+ * to rotate the selected region so that it doesn't change, as long as the
+ * forced aspect ratio setting is respected, in other case, the selected region
+ * is resetted.
+ */
+ void rotate(KImageEffect::RotateDirection direction);
+
+public slots:
+ /**
+ * Rotates the current image 90º clockwise
+ */
+ void rotateClockwise();
+ /**
+ * Rotates the current image 90º counterclockwise
+ */
+ void rotateCounterclockwise();
+
+protected:
+ /**
+ * Creates a KPopupMenu with the menu that appears when clicking with the right button on the label
+ */
+ virtual KPopupMenu *createPopupMenu();
+
+private:
+ bool eventFilter(QObject *obj, QEvent *ev);
+
+ /**
+ * Recalculates the pixmap that is shown based on the current selected area,
+ * the original image, etc.
+ */
+ void updatePixmap();
+
+ QRect calcSelectionRectangle( const QPoint &startPoint, const QPoint & endPoint );
+
+ enum CursorState { None=0, Resizing, Moving };
+ CursorState m_state;
+
+ QPixmap m_unzoomedPixmap;
+ QPixmap m_originalPixmap;
+ QPixmap m_linedPixmap;
+ QRect m_selectedRegion;
+ QLabel *m_label;
+
+ QPoint m_tempFirstClick;
+ double m_forcedAspectRatio;
+
+ int m_maxWidth, m_maxHeight;
+ double m_zoomFactor;
+};
+
+#endif
+
diff --git a/kdeui/kpopupmenu.cpp b/kdeui/kpopupmenu.cpp
new file mode 100644
index 000000000..6f7fbf374
--- /dev/null
+++ b/kdeui/kpopupmenu.cpp
@@ -0,0 +1,689 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Daniel M. Duley <mosfet@kde.org>
+ Copyright (C) 2002 Hamish Rodda <rodda@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#include <qcursor.h>
+#include <qpainter.h>
+#include <qtimer.h>
+#include <qfontmetrics.h>
+#include <qstyle.h>
+
+#include "kpopupmenu.h"
+
+#include <kdebug.h>
+#include <kapplication.h>
+
+KPopupTitle::KPopupTitle(QWidget *parent, const char *name)
+ : QWidget(parent, name)
+{
+ setMinimumSize(16, fontMetrics().height()+8);
+}
+
+KPopupTitle::KPopupTitle(KPixmapEffect::GradientType /* gradient */,
+ const QColor &/* color */, const QColor &/* textColor */,
+ QWidget *parent, const char *name)
+ : QWidget(parent, name)
+{
+ calcSize();
+}
+
+KPopupTitle::KPopupTitle(const KPixmap & /* background */, const QColor &/* color */,
+ const QColor &/* textColor */, QWidget *parent,
+ const char *name)
+ : QWidget(parent, name)
+{
+ calcSize();
+}
+
+void KPopupTitle::setTitle(const QString &text, const QPixmap *icon)
+{
+ titleStr = text;
+ if (icon)
+ miniicon = *icon;
+ else
+ miniicon.resize(0, 0);
+
+ calcSize();
+}
+
+void KPopupTitle::setText( const QString &text )
+{
+ titleStr = text;
+ calcSize();
+}
+
+void KPopupTitle::setIcon( const QPixmap &pix )
+{
+ miniicon = pix;
+ calcSize();
+}
+
+void KPopupTitle::calcSize()
+{
+ QFont f = font();
+ f.setBold(true);
+ int w = miniicon.width()+QFontMetrics(f).width(titleStr);
+ int h = QMAX( fontMetrics().height(), miniicon.height() );
+ setMinimumSize( w+16, h+8 );
+}
+
+void KPopupTitle::paintEvent(QPaintEvent *)
+{
+ QRect r(rect());
+ QPainter p(this);
+ kapp->style().drawPrimitive(QStyle::PE_HeaderSection, &p, r, palette().active());
+
+ if (!miniicon.isNull())
+ p.drawPixmap(4, (r.height()-miniicon.height())/2, miniicon);
+
+ if (!titleStr.isNull())
+ {
+ p.setPen(palette().active().text());
+ QFont f = p.font();
+ f.setBold(true);
+ p.setFont(f);
+ if(!miniicon.isNull())
+ {
+ p.drawText(miniicon.width()+8, 0, width()-(miniicon.width()+8),
+ height(), AlignLeft | AlignVCenter | SingleLine,
+ titleStr);
+ }
+ else
+ {
+ p.drawText(0, 0, width(), height(),
+ AlignCenter | SingleLine, titleStr);
+ }
+ }
+}
+
+QSize KPopupTitle::sizeHint() const
+{
+ return minimumSize();
+}
+
+class KPopupMenu::KPopupMenuPrivate
+{
+public:
+ KPopupMenuPrivate ()
+ : noMatches(false)
+ , shortcuts(false)
+ , autoExec(false)
+ , lastHitIndex(-1)
+ , state(Qt::NoButton)
+ , m_ctxMenu(0)
+ {}
+
+ ~KPopupMenuPrivate ()
+ {
+ delete m_ctxMenu;
+ }
+
+ QString m_lastTitle;
+
+ // variables for keyboard navigation
+ QTimer clearTimer;
+
+ bool noMatches : 1;
+ bool shortcuts : 1;
+ bool autoExec : 1;
+
+ QString keySeq;
+ QString originalText;
+
+ int lastHitIndex;
+ Qt::ButtonState state;
+
+ // support for RMB menus on menus
+ QPopupMenu* m_ctxMenu;
+ static bool s_continueCtxMenuShow;
+ static int s_highlightedItem;
+ static KPopupMenu* s_contextedMenu;
+};
+
+int KPopupMenu::KPopupMenuPrivate::s_highlightedItem(-1);
+KPopupMenu* KPopupMenu::KPopupMenuPrivate::s_contextedMenu(0);
+bool KPopupMenu::KPopupMenuPrivate::s_continueCtxMenuShow(true);
+
+KPopupMenu::KPopupMenu(QWidget *parent, const char *name)
+ : QPopupMenu(parent, name)
+{
+ d = new KPopupMenuPrivate;
+ resetKeyboardVars();
+ connect(&(d->clearTimer), SIGNAL(timeout()), SLOT(resetKeyboardVars()));
+}
+
+KPopupMenu::~KPopupMenu()
+{
+ if (KPopupMenuPrivate::s_contextedMenu == this)
+ {
+ KPopupMenuPrivate::s_contextedMenu = 0;
+ KPopupMenuPrivate::s_highlightedItem = -1;
+ }
+
+ delete d;
+}
+
+int KPopupMenu::insertTitle(const QString &text, int id, int index)
+{
+ KPopupTitle *titleItem = new KPopupTitle();
+ titleItem->setTitle(text);
+ int ret = insertItem(titleItem, id, index);
+ setItemEnabled(ret, false);
+ return ret;
+}
+
+int KPopupMenu::insertTitle(const QPixmap &icon, const QString &text, int id,
+ int index)
+{
+ KPopupTitle *titleItem = new KPopupTitle();
+ titleItem->setTitle(text, &icon);
+ int ret = insertItem(titleItem, id, index);
+ setItemEnabled(ret, false);
+ return ret;
+}
+
+void KPopupMenu::changeTitle(int id, const QString &text)
+{
+ QMenuItem *item = findItem(id);
+ if(item){
+ if(item->widget())
+ ((KPopupTitle *)item->widget())->setTitle(text);
+#ifndef NDEBUG
+ else
+ kdWarning() << "KPopupMenu: changeTitle() called with non-title id "<< id << endl;
+#endif
+ }
+#ifndef NDEBUG
+ else
+ kdWarning() << "KPopupMenu: changeTitle() called with invalid id " << id << endl;
+#endif
+}
+
+void KPopupMenu::changeTitle(int id, const QPixmap &icon, const QString &text)
+{
+ QMenuItem *item = findItem(id);
+ if(item){
+ if(item->widget())
+ ((KPopupTitle *)item->widget())->setTitle(text, &icon);
+#ifndef NDEBUG
+ else
+ kdWarning() << "KPopupMenu: changeTitle() called with non-title id "<< id << endl;
+#endif
+ }
+#ifndef NDEBUG
+ else
+ kdWarning() << "KPopupMenu: changeTitle() called with invalid id " << id << endl;
+#endif
+}
+
+QString KPopupMenu::title(int id) const
+{
+ if(id == -1) // obsolete
+ return d->m_lastTitle;
+ QMenuItem *item = findItem(id);
+ if(item){
+ if(item->widget())
+ return ((KPopupTitle *)item->widget())->title();
+ else
+ qWarning("KPopupMenu: title() called with non-title id %d.", id);
+ }
+ else
+ qWarning("KPopupMenu: title() called with invalid id %d.", id);
+ return QString::null;
+}
+
+QPixmap KPopupMenu::titlePixmap(int id) const
+{
+ QMenuItem *item = findItem(id);
+ if(item){
+ if(item->widget())
+ return ((KPopupTitle *)item->widget())->icon();
+ else
+ qWarning("KPopupMenu: titlePixmap() called with non-title id %d.", id);
+ }
+ else
+ qWarning("KPopupMenu: titlePixmap() called with invalid id %d.", id);
+ QPixmap tmp;
+ return tmp;
+}
+
+/**
+ * This is re-implemented for keyboard navigation.
+ */
+void KPopupMenu::closeEvent(QCloseEvent*e)
+{
+ if (d->shortcuts)
+ resetKeyboardVars();
+ QPopupMenu::closeEvent(e);
+}
+
+void KPopupMenu::activateItemAt(int index)
+{
+ d->state = Qt::NoButton;
+ QPopupMenu::activateItemAt(index);
+}
+
+Qt::ButtonState KPopupMenu::state() const
+{
+ return d->state;
+}
+
+void KPopupMenu::keyPressEvent(QKeyEvent* e)
+{
+ d->state = Qt::NoButton;
+ if (!d->shortcuts) {
+ // continue event processing by Qpopup
+ //e->ignore();
+ d->state = e->state();
+ QPopupMenu::keyPressEvent(e);
+ return;
+ }
+
+ int i = 0;
+ bool firstpass = true;
+ QString keyString = e->text();
+
+ // check for common commands dealt with by QPopup
+ int key = e->key();
+ if (key == Key_Escape || key == Key_Return || key == Key_Enter
+ || key == Key_Up || key == Key_Down || key == Key_Left
+ || key == Key_Right || key == Key_F1) {
+
+ resetKeyboardVars();
+ // continue event processing by Qpopup
+ //e->ignore();
+ d->state = e->state();
+ QPopupMenu::keyPressEvent(e);
+ return;
+ } else if ( key == Key_Shift || key == Key_Control || key == Key_Alt || key == Key_Meta )
+ return QPopupMenu::keyPressEvent(e);
+
+ // check to see if the user wants to remove a key from the sequence (backspace)
+ // or clear the sequence (delete)
+ if (!d->keySeq.isNull()) {
+
+ if (key == Key_Backspace) {
+
+ if (d->keySeq.length() == 1) {
+ resetKeyboardVars();
+ return;
+ }
+
+ // keep the last sequence in keyString
+ keyString = d->keySeq.left(d->keySeq.length() - 1);
+
+ // allow sequence matching to be tried again
+ resetKeyboardVars();
+
+ } else if (key == Key_Delete) {
+ resetKeyboardVars();
+
+ // clear active item
+ setActiveItem(0);
+ return;
+
+ } else if (d->noMatches) {
+ // clear if there are no matches
+ resetKeyboardVars();
+
+ // clear active item
+ setActiveItem(0);
+
+ } else {
+ // the key sequence is not a null string
+ // therefore the lastHitIndex is valid
+ i = d->lastHitIndex;
+ }
+ } else if (key == Key_Backspace && parentMenu) {
+ // backspace with no chars in the buffer... go back a menu.
+ hide();
+ resetKeyboardVars();
+ return;
+ }
+
+ d->keySeq += keyString;
+ int seqLen = d->keySeq.length();
+
+ for (; i < (int)count(); i++) {
+ // compare typed text with text of this entry
+ int j = idAt(i);
+
+ // don't search disabled entries
+ if (!isItemEnabled(j))
+ continue;
+
+ QString thisText;
+
+ // retrieve the right text
+ // (the last selected item one may have additional ampersands)
+ if (i == d->lastHitIndex)
+ thisText = d->originalText;
+ else
+ thisText = text(j);
+
+ // if there is an accelerator present, remove it
+ if ((int)accel(j) != 0)
+ thisText = thisText.replace("&", QString::null);
+
+ // chop text to the search length
+ thisText = thisText.left(seqLen);
+
+ // do the search
+ if (!thisText.find(d->keySeq, 0, false)) {
+
+ if (firstpass) {
+ // match
+ setActiveItem(i);
+
+ // check to see if we're underlining a different item
+ if (d->lastHitIndex != i)
+ // yes; revert the underlining
+ changeItem(idAt(d->lastHitIndex), d->originalText);
+
+ // set the original text if it's a different item
+ if (d->lastHitIndex != i || d->lastHitIndex == -1)
+ d->originalText = text(j);
+
+ // underline the currently selected item
+ changeItem(j, underlineText(d->originalText, d->keySeq.length()));
+
+ // remember what's going on
+ d->lastHitIndex = i;
+
+ // start/restart the clear timer
+ d->clearTimer.start(5000, true);
+
+ // go around for another try, to see if we can execute
+ firstpass = false;
+ } else {
+ // don't allow execution
+ return;
+ }
+ }
+
+ // fall through to allow execution
+ }
+
+ if (!firstpass) {
+ if (d->autoExec) {
+ // activate anything
+ activateItemAt(d->lastHitIndex);
+ resetKeyboardVars();
+
+ } else if (findItem(idAt(d->lastHitIndex)) &&
+ findItem(idAt(d->lastHitIndex))->popup()) {
+ // only activate sub-menus
+ activateItemAt(d->lastHitIndex);
+ resetKeyboardVars();
+ }
+
+ return;
+ }
+
+ // no matches whatsoever, clean up
+ resetKeyboardVars(true);
+ //e->ignore();
+ QPopupMenu::keyPressEvent(e);
+}
+
+bool KPopupMenu::focusNextPrevChild( bool next )
+{
+ resetKeyboardVars();
+ return QPopupMenu::focusNextPrevChild( next );
+}
+
+QString KPopupMenu::underlineText(const QString& text, uint length)
+{
+ QString ret = text;
+ for (uint i = 0; i < length; i++) {
+ if (ret[2*i] != '&')
+ ret.insert(2*i, "&");
+ }
+ return ret;
+}
+
+void KPopupMenu::resetKeyboardVars(bool noMatches /* = false */)
+{
+ // Clean up keyboard variables
+ if (d->lastHitIndex != -1) {
+ changeItem(idAt(d->lastHitIndex), d->originalText);
+ d->lastHitIndex = -1;
+ }
+
+ if (!noMatches) {
+ d->keySeq = QString::null;
+ }
+
+ d->noMatches = noMatches;
+}
+
+void KPopupMenu::setKeyboardShortcutsEnabled(bool enable)
+{
+ d->shortcuts = enable;
+}
+
+void KPopupMenu::setKeyboardShortcutsExecute(bool enable)
+{
+ d->autoExec = enable;
+}
+/**
+ * End keyboard navigation.
+ */
+
+/**
+ * RMB menus on menus
+ */
+
+void KPopupMenu::mousePressEvent(QMouseEvent* e)
+{
+ if (d->m_ctxMenu && d->m_ctxMenu->isVisible())
+ {
+ // hide on a second context menu event
+ d->m_ctxMenu->hide();
+ }
+
+ QPopupMenu::mousePressEvent(e);
+}
+
+void KPopupMenu::mouseReleaseEvent(QMouseEvent* e)
+{
+ // Save the button, and the modifiers from state()
+ d->state = Qt::ButtonState(e->button() | (e->state() & KeyButtonMask));
+
+ if ( !d->m_ctxMenu || !d->m_ctxMenu->isVisible() )
+ QPopupMenu::mouseReleaseEvent(e);
+}
+
+QPopupMenu* KPopupMenu::contextMenu()
+{
+ if (!d->m_ctxMenu)
+ {
+ d->m_ctxMenu = new QPopupMenu(this);
+ connect(d->m_ctxMenu, SIGNAL(aboutToHide()), this, SLOT(ctxMenuHiding()));
+ }
+
+ return d->m_ctxMenu;
+}
+
+const QPopupMenu* KPopupMenu::contextMenu() const
+{
+ return const_cast< KPopupMenu* >( this )->contextMenu();
+}
+
+void KPopupMenu::hideContextMenu()
+{
+ KPopupMenuPrivate::s_continueCtxMenuShow = false;
+}
+
+int KPopupMenu::contextMenuFocusItem()
+{
+ return KPopupMenuPrivate::s_highlightedItem;
+}
+
+KPopupMenu* KPopupMenu::contextMenuFocus()
+{
+ return KPopupMenuPrivate::s_contextedMenu;
+}
+
+void KPopupMenu::itemHighlighted(int /* whichItem */)
+{
+ if (!d->m_ctxMenu || !d->m_ctxMenu->isVisible())
+ {
+ return;
+ }
+
+ d->m_ctxMenu->hide();
+ showCtxMenu(mapFromGlobal(QCursor::pos()));
+}
+
+void KPopupMenu::showCtxMenu(QPoint pos)
+{
+ QMenuItem* item = findItem(KPopupMenuPrivate::s_highlightedItem);
+ if (item)
+ {
+ QPopupMenu* subMenu = item->popup();
+ if (subMenu)
+ {
+ disconnect(subMenu, SIGNAL(aboutToShow()), this, SLOT(ctxMenuHideShowingMenu()));
+ }
+ }
+
+ KPopupMenuPrivate::s_highlightedItem = idAt(pos);
+
+ if (KPopupMenuPrivate::s_highlightedItem == -1)
+ {
+ KPopupMenuPrivate::s_contextedMenu = 0;
+ return;
+ }
+
+ emit aboutToShowContextMenu(this, KPopupMenuPrivate::s_highlightedItem, d->m_ctxMenu);
+
+ QPopupMenu* subMenu = findItem(KPopupMenuPrivate::s_highlightedItem)->popup();
+ if (subMenu)
+ {
+ connect(subMenu, SIGNAL(aboutToShow()), SLOT(ctxMenuHideShowingMenu()));
+ QTimer::singleShot(100, subMenu, SLOT(hide()));
+ }
+
+ if (!KPopupMenuPrivate::s_continueCtxMenuShow)
+ {
+ KPopupMenuPrivate::s_continueCtxMenuShow = true;
+ return;
+ }
+
+ KPopupMenuPrivate::s_contextedMenu = this;
+ d->m_ctxMenu->popup(this->mapToGlobal(pos));
+ connect(this, SIGNAL(highlighted(int)), this, SLOT(itemHighlighted(int)));
+}
+
+/*
+ * this method helps prevent submenus popping up while we have a context menu
+ * showing
+ */
+void KPopupMenu::ctxMenuHideShowingMenu()
+{
+ QMenuItem* item = findItem(KPopupMenuPrivate::s_highlightedItem);
+ if (item)
+ {
+ QPopupMenu* subMenu = item->popup();
+ if (subMenu)
+ {
+ QTimer::singleShot(0, subMenu, SLOT(hide()));
+ }
+ }
+}
+
+void KPopupMenu::ctxMenuHiding()
+{
+ if (KPopupMenuPrivate::s_highlightedItem)
+ {
+ QPopupMenu* subMenu = findItem(KPopupMenuPrivate::s_highlightedItem)->popup();
+ if (subMenu)
+ {
+ disconnect(subMenu, SIGNAL(aboutToShow()), this, SLOT(ctxMenuHideShowingMenu()));
+ }
+ }
+
+ disconnect(this, SIGNAL(highlighted(int)), this, SLOT(itemHighlighted(int)));
+ KPopupMenuPrivate::s_continueCtxMenuShow = true;
+}
+
+void KPopupMenu::contextMenuEvent(QContextMenuEvent* e)
+{
+ if (d->m_ctxMenu)
+ {
+ if (e->reason() == QContextMenuEvent::Mouse)
+ {
+ showCtxMenu(e->pos());
+ }
+ else if (actItem != -1)
+ {
+ showCtxMenu(itemGeometry(actItem).center());
+ }
+
+ e->accept();
+ return;
+ }
+
+ QPopupMenu::contextMenuEvent(e);
+}
+
+void KPopupMenu::hideEvent(QHideEvent*)
+{
+ if (d->m_ctxMenu && d->m_ctxMenu->isVisible())
+ {
+ // we need to block signals here when the ctxMenu is showing
+ // to prevent the QPopupMenu::activated(int) signal from emitting
+ // when hiding with a context menu, the user doesn't expect the
+ // menu to actually do anything.
+ // since hideEvent gets called very late in the process of hiding
+ // (deep within QWidget::hide) the activated(int) signal is the
+ // last signal to be emitted, even after things like aboutToHide()
+ // AJS
+ blockSignals(true);
+ d->m_ctxMenu->hide();
+ blockSignals(false);
+ }
+}
+/**
+ * end of RMB menus on menus support
+ */
+
+// Obsolete
+KPopupMenu::KPopupMenu(const QString& title, QWidget *parent, const char *name)
+ : QPopupMenu(parent, name)
+{
+ d = new KPopupMenuPrivate;
+ insertTitle(title);
+}
+
+// Obsolete
+void KPopupMenu::setTitle(const QString &title)
+{
+ KPopupTitle *titleItem = new KPopupTitle();
+ titleItem->setTitle(title);
+ insertItem(titleItem);
+ d->m_lastTitle = title;
+}
+
+void KPopupTitle::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void KPopupMenu::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "kpopupmenu.moc"
diff --git a/kdeui/kpopupmenu.h b/kdeui/kpopupmenu.h
new file mode 100644
index 000000000..7c392b61e
--- /dev/null
+++ b/kdeui/kpopupmenu.h
@@ -0,0 +1,281 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Daniel M. Duley <mosfet@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef _KPOPUP_H
+#define _KPOPUP_H "$Id$"
+
+#define INCLUDE_MENUITEM_DEF
+
+#include <qpopupmenu.h>
+#include <kpixmapeffect.h>
+#include <kpixmap.h>
+#include <kdelibs_export.h>
+/**
+ * @short KPopupMenu title widget.
+ *
+ * Title widget for use in KPopupMenu.
+ *
+ * You usually don't have to create this manually since
+ * KPopupMenu::insertTitle will do it for you, but it is allowed if
+ * you wish to customize it's look.
+ *
+ * @author Daniel M. Duley <mosfet@kde.org>
+ */
+class KDEUI_EXPORT KPopupTitle : public QWidget
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Constructs a title widget with the user specified gradient, pixmap,
+ * and colors.
+ */
+ KPopupTitle(QWidget *parent=0, const char *name=0);
+ /**
+ * @deprecated
+ * Constructs a title widget with the specified gradient and colors.
+ */
+ KPopupTitle(KPixmapEffect::GradientType gradient, const QColor &color,
+ const QColor &textColor, QWidget *parent=0,
+ const char *name=0) KDE_DEPRECATED;
+ /**
+ * @deprecated
+ * Constructs a title widget with the specified pixmap and colors.
+ */
+ KPopupTitle(const KPixmap &background, const QColor &color,
+ const QColor &textColor, QWidget *parent=0,
+ const char *name=0) KDE_DEPRECATED;
+ /**
+ * Sets the title string and optional icon for the title widget.
+ *
+ * You will want to call this before inserting into a menu.
+ */
+ void setTitle(const QString &text, const QPixmap *icon=0);
+ /**
+ * Returns the current title.
+ */
+ QString title() const { return titleStr; }
+ /**
+ * Returns the current icon.
+ */
+ QPixmap icon() const { return miniicon; }
+
+ QSize sizeHint() const;
+
+public slots:
+ /// @since 3.1
+ void setText( const QString &text );
+ /// @since 3.1
+ void setIcon( const QPixmap &pix );
+
+protected:
+ void calcSize();
+ void paintEvent(QPaintEvent *ev);
+
+ // Remove in KDE4
+ KPixmapEffect::GradientType grType;
+ QString titleStr;
+ // Remove in KDE4
+ KPixmap fill;
+ QPixmap miniicon;
+ QColor fgColor, bgColor, grHigh, grLow;
+ bool useGradient;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KPopupTitlePrivate;
+ KPopupTitlePrivate *d;
+};
+
+/**
+ * @short A menu with title items.
+ *
+ * KPopupMenu is a class for menus with standard title items and keyboard
+ * accessibility for popups with many options and/or varying options. It acts
+ * identically to QPopupMenu, with the addition of insertTitle(),
+ * changeTitle(), setKeyboardShortcutsEnabled() and
+ * setKeyboardShortcutsExecute() methods.
+ *
+ * The titles support a text string, an icon, plus user defined gradients,
+ * colors, and background pixmaps.
+ *
+ * The keyboard search algorithm is incremental with additional underlining
+ * for user feedback.
+ *
+ * @author Daniel M. Duley <mosfet@kde.org>
+ * @author Hamish Rodda <rodda@kde.org>
+ */
+class KDEUI_EXPORT KPopupMenu : public QPopupMenu {
+ Q_OBJECT
+public:
+ /**
+ * Constructs a KPopupMenu.
+ */
+ KPopupMenu(QWidget *parent=0, const char *name=0);
+
+ /**
+ * Destructs the object
+ */
+ ~KPopupMenu();
+
+ /**
+ * Inserts a title item with no icon.
+ */
+ int insertTitle(const QString &text, int id=-1, int index=-1);
+ /**
+ * Inserts a title item with the given icon and title.
+ */
+ int insertTitle(const QPixmap &icon, const QString &text, int id=-1,
+ int index=-1);
+ /**
+ * Changes the title of the item at the specified id. If a icon was
+ * previously set it is cleared.
+ */
+ void changeTitle(int id, const QString &text);
+ /**
+ * Changes the title and icon of the title item at the specified id.
+ */
+ void changeTitle(int id, const QPixmap &icon, const QString &text);
+ /**
+ * Returns the title of the title item at the specified id. The default
+ * id of -1 is for backwards compatibility only, you should always specify
+ * the id.
+ */
+ QString title(int id=-1) const;
+ /**
+ * Returns the icon of the title item at the specified id.
+ */
+ QPixmap titlePixmap(int id) const;
+
+ /**
+ * Enables keyboard navigation by searching for the entered key sequence.
+ * Also underlines the currently selected item, providing feedback on the search.
+ *
+ * Defaults to off.
+ *
+ * WARNING: calls to text() of currently keyboard-selected items will
+ * contain additional ampersand characters.
+ *
+ * WARNING: though pre-existing keyboard shortcuts will not interfere with the
+ * operation of this feature, they may be confusing to the user as the existing
+ * shortcuts will not work.
+ * @since 3.1
+ */
+ void setKeyboardShortcutsEnabled(bool enable);
+
+ /**
+ * Enables execution of the menu item once it is uniquely specified.
+ * Defaults to off.
+ * @since 3.1
+ */
+ void setKeyboardShortcutsExecute(bool enable);
+
+ /**
+ * @deprecated
+ * Obsolete method provided for backwards compatibility only. Use the
+ * normal constructor and insertTitle instead.
+ */
+ KPopupMenu(const QString &title, QWidget *parent=0, const char *name=0) KDE_DEPRECATED;
+
+ /**
+ * @deprecated
+ * Obsolete method provided for backwards compatibility only. Use
+ * insertTitle and changeTitle instead.
+ */
+ void setTitle(const QString &title) KDE_DEPRECATED;
+
+ /**
+ * Returns the context menu associated with this menu
+ * @since 3.2
+ */
+ QPopupMenu* contextMenu();
+
+ /**
+ * Returns the context menu associated with this menu
+ * @since 3.2
+ */
+ const QPopupMenu* contextMenu() const;
+
+ /**
+ * Hides the context menu if shown
+ * @since 3.2
+ */
+ void hideContextMenu();
+
+ /**
+ * Returns the KPopupMenu associated with the current context menu
+ * @since 3.2
+ */
+ static KPopupMenu* contextMenuFocus();
+
+ /**
+ * returns the ID of the menuitem associated with the current context menu
+ * @since 3.2
+ */
+ static int contextMenuFocusItem();
+
+ /**
+ * Reimplemented for internal purposes
+ * @since 3.4
+ */
+ virtual void activateItemAt(int index);
+ /**
+ * Return the state of the mouse button and keyboard modifiers
+ * when the last menuitem was activated.
+ * @since 3.4
+ */
+ Qt::ButtonState state() const;
+
+signals:
+ /**
+ * connect to this signal to be notified when a context menu is about to be shown
+ * @param menu The menu that the context menu is about to be shown for
+ * @param menuItem The menu item that the context menu is currently on
+ * @param ctxMenu The context menu itself
+ * @since 3.2
+ */
+ void aboutToShowContextMenu(KPopupMenu* menu, int menuItem, QPopupMenu* ctxMenu);
+
+protected:
+ virtual void closeEvent(QCloseEvent *);
+ virtual void keyPressEvent(QKeyEvent* e);
+ /// @since 3.4
+ virtual void mouseReleaseEvent(QMouseEvent* e);
+ virtual void mousePressEvent(QMouseEvent* e);
+ virtual bool focusNextPrevChild( bool next );
+ virtual void contextMenuEvent(QContextMenuEvent *e);
+ virtual void hideEvent(QHideEvent*);
+
+ virtual void virtual_hook( int id, void* data );
+
+protected slots:
+ /// @since 3.1
+ QString underlineText(const QString& text, uint length);
+ /// @since 3.1
+ void resetKeyboardVars(bool noMatches = false);
+ void itemHighlighted(int whichItem);
+ void showCtxMenu(QPoint pos);
+ void ctxMenuHiding();
+ void ctxMenuHideShowingMenu();
+
+private:
+ class KPopupMenuPrivate;
+ KPopupMenuPrivate *d;
+};
+
+#endif
diff --git a/kdeui/kprogress.cpp b/kdeui/kprogress.cpp
new file mode 100644
index 000000000..89d41205d
--- /dev/null
+++ b/kdeui/kprogress.cpp
@@ -0,0 +1,414 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1996 Martynas Kunigelis
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+/**
+ * KProgress -- a progress indicator widget for KDE.
+ */
+
+#include <stdlib.h>
+#include <limits.h>
+
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qstring.h>
+#include <qregexp.h>
+#include <qstyle.h>
+#include <qtimer.h>
+
+#include "kprogress.h"
+
+#include <kapplication.h>
+#include <klocale.h>
+#include <kwin.h>
+
+KProgress::KProgress(QWidget *parent, const char *name, WFlags f)
+ : QProgressBar(parent, name, f),
+ mFormat("%p%")
+{
+ setProgress(0);
+}
+
+KProgress::KProgress(int totalSteps, QWidget *parent, const char *name, WFlags f)
+ : QProgressBar(totalSteps, parent, name, f),
+ mFormat("%p%")
+{
+ setProgress(0);
+}
+
+KProgress::~KProgress()
+{
+}
+
+void KProgress::advance(int offset)
+{
+ setProgress(progress() + offset);
+}
+
+void KProgress::setTotalSteps(int totalSteps)
+{
+ QProgressBar::setTotalSteps(totalSteps);
+
+ if (totalSteps)
+ {
+ emit percentageChanged((progress() * 100) / totalSteps);
+ }
+}
+
+void KProgress::setProgress(int progress)
+{
+ QProgressBar::setProgress(progress);
+
+ if (totalSteps())
+ {
+ emit percentageChanged((progress * 100) / totalSteps());
+ }
+}
+
+// ### KDE 4 remove
+void KProgress::setValue(int progress)
+{
+ setProgress(progress);
+}
+
+// ### KDE 4 remove
+void KProgress::setRange(int /*min*/, int max)
+{
+ setTotalSteps(max);
+}
+
+// ### KDE 4 remove
+int KProgress::maxValue()
+{
+ return totalSteps();
+}
+
+void KProgress::setTextEnabled(bool enable)
+{
+ setPercentageVisible(enable);
+}
+
+bool KProgress::textEnabled() const
+{
+ return percentageVisible();
+}
+
+void KProgress::setFormat(const QString & format)
+{
+ mFormat = format;
+ if (mFormat != "%p%")
+ setCenterIndicator(true);
+}
+
+QString KProgress::format() const
+{
+ return mFormat;
+}
+
+// ### KDE 4 remove
+int KProgress::value() const
+{
+ return progress();
+}
+
+bool KProgress::setIndicator(QString &indicator, int progress, int totalSteps)
+{
+ if (!totalSteps)
+ return false;
+ QString newString(mFormat);
+ newString.replace(QString::fromLatin1("%v"),
+ QString::number(progress));
+ newString.replace(QString::fromLatin1("%m"),
+ QString::number(totalSteps));
+
+ if (totalSteps > INT_MAX / 1000) {
+ progress /= 1000;
+ totalSteps /= 1000;
+ }
+
+ newString.replace(QString::fromLatin1("%p"),
+ QString::number((progress * 100) / totalSteps));
+
+ if (newString != indicator)
+ {
+ indicator = newString;
+ return true;
+ }
+
+ return false;
+}
+
+struct KProgressDialog::KProgressDialogPrivate
+{
+ KProgressDialogPrivate() : cancelButtonShown(true)
+ {
+ }
+
+ bool cancelButtonShown;
+};
+
+/*
+ * KProgressDialog implementation
+ */
+KProgressDialog::KProgressDialog(QWidget* parent, const char* name,
+ const QString& caption, const QString& text,
+ bool modal)
+ : KDialogBase(KDialogBase::Plain, caption, KDialogBase::Cancel,
+ KDialogBase::Cancel, parent, name, modal),
+ mAutoClose(true),
+ mAutoReset(false),
+ mCancelled(false),
+ mAllowCancel(true),
+ mShown(false),
+ mMinDuration(2000),
+ d(new KProgressDialogPrivate)
+{
+#ifdef Q_WS_X11
+ KWin::setIcons(winId(), kapp->icon(), kapp->miniIcon());
+#endif
+ mShowTimer = new QTimer(this);
+
+ showButton(KDialogBase::Close, false);
+ mCancelText = actionButton(KDialogBase::Cancel)->text();
+
+ QFrame* mainWidget = plainPage();
+ QVBoxLayout* layout = new QVBoxLayout(mainWidget, 10);
+
+ mLabel = new QLabel(text, mainWidget);
+ layout->addWidget(mLabel);
+
+ mProgressBar = new KProgress(mainWidget);
+ layout->addWidget(mProgressBar);
+
+ connect(mProgressBar, SIGNAL(percentageChanged(int)),
+ this, SLOT(slotAutoActions(int)));
+ connect(mShowTimer, SIGNAL(timeout()), this, SLOT(slotAutoShow()));
+ mShowTimer->start(mMinDuration, true);
+}
+
+KProgressDialog::~KProgressDialog()
+{
+ delete d;
+}
+
+void KProgressDialog::slotAutoShow()
+{
+ if (mShown || mCancelled)
+ {
+ return;
+ }
+
+ show();
+ kapp->processEvents();
+}
+
+void KProgressDialog::slotCancel()
+{
+ mCancelled = true;
+
+ if (mAllowCancel)
+ {
+ KDialogBase::slotCancel();
+ }
+}
+
+bool KProgressDialog::wasCancelled()
+{
+ return mCancelled;
+}
+
+void KProgressDialog::ignoreCancel()
+{
+ mCancelled = false;
+}
+
+bool KProgressDialog::wasCancelled() const
+{
+ return mCancelled;
+}
+
+void KProgressDialog::setMinimumDuration(int ms)
+{
+ mMinDuration = ms;
+ if (!mShown)
+ {
+ mShowTimer->stop();
+ mShowTimer->start(mMinDuration, true);
+ }
+}
+
+int KProgressDialog::minimumDuration()
+{
+ return mMinDuration;
+}
+
+int KProgressDialog::minimumDuration() const
+{
+ return mMinDuration;
+}
+
+void KProgressDialog::setAllowCancel(bool allowCancel)
+{
+ mAllowCancel = allowCancel;
+ showCancelButton(allowCancel);
+}
+
+// ### KDE 4 remove
+bool KProgressDialog::allowCancel()
+{
+ return mAllowCancel;
+}
+
+bool KProgressDialog::allowCancel() const
+{
+ return mAllowCancel;
+}
+
+KProgress* KProgressDialog::progressBar()
+{
+ return mProgressBar;
+}
+
+const KProgress* KProgressDialog::progressBar() const
+{
+ return mProgressBar;
+}
+
+void KProgressDialog::setLabel(const QString& text)
+{
+ mLabel->setText(text);
+}
+
+// ### KDE 4 remove
+QString KProgressDialog::labelText()
+{
+ return mLabel->text();
+}
+
+QString KProgressDialog::labelText() const
+{
+ return mLabel->text();
+}
+
+void KProgressDialog::showCancelButton(bool show)
+{
+ showButtonCancel(show);
+}
+
+// ### KDE 4 remove
+bool KProgressDialog::autoClose()
+{
+ return mAutoClose;
+}
+
+bool KProgressDialog::autoClose() const
+{
+ return mAutoClose;
+}
+
+void KProgressDialog::setAutoClose(bool autoClose)
+{
+ mAutoClose = autoClose;
+}
+
+// ### KDE 4 remove
+bool KProgressDialog::autoReset()
+{
+ return mAutoReset;
+}
+
+bool KProgressDialog::autoReset() const
+{
+ return mAutoReset;
+}
+
+void KProgressDialog::setAutoReset(bool autoReset)
+{
+ mAutoReset = autoReset;
+}
+
+void KProgressDialog::setButtonText(const QString& text)
+{
+ mCancelText = text;
+ setButtonCancel(text);
+}
+
+// ### KDE 4 remove
+QString KProgressDialog::buttonText()
+{
+ return mCancelText;
+}
+
+QString KProgressDialog::buttonText() const
+{
+ return mCancelText;
+}
+
+void KProgressDialog::slotAutoActions(int percentage)
+{
+ if (percentage < 100)
+ {
+ if (!d->cancelButtonShown)
+ {
+ setButtonCancel(mCancelText);
+ d->cancelButtonShown = true;
+ }
+ return;
+ }
+
+ mShowTimer->stop();
+
+ if (mAutoReset)
+ {
+ mProgressBar->setProgress(0);
+ }
+ else
+ {
+ setAllowCancel(true);
+ setButtonCancel(KStdGuiItem::close());
+ d->cancelButtonShown = false;
+ }
+
+ if (mAutoClose)
+ {
+ if (mShown)
+ {
+ hide();
+ }
+ else
+ {
+ emit finished();
+ }
+ }
+}
+
+void KProgressDialog::show()
+{
+ KDialogBase::show();
+ mShown = true;
+}
+
+
+void KProgress::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void KProgressDialog::virtual_hook( int id, void* data )
+{ KDialogBase::virtual_hook( id, data ); }
+
+#include "kprogress.moc"
diff --git a/kdeui/kprogress.h b/kdeui/kprogress.h
new file mode 100644
index 000000000..28ed989c7
--- /dev/null
+++ b/kdeui/kprogress.h
@@ -0,0 +1,401 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1996 Martynas Kunigelis
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+/*****************************************************************************
+* *
+* KProgress -- progress indicator widget for KDE *
+* Original QRangeControl-based version written by Martynas Kunigelis *
+* Current QProgressBar based version by Aaron Seigo *
+* *
+*****************************************************************************/
+
+#ifndef _KPROGRESS_H
+#define _KPROGRESS_H "$Id$"
+
+#include <qprogressbar.h>
+#include <kdialogbase.h>
+
+/**
+ * @short A progress indicator widget.
+ *
+ * KProgress is derived from QProgressBar, so
+ * you can use all the methods from that class. The only real difference
+ * is that a signal is emitted on changes to the value and you do not need
+ * to subclass KProgress just to change the format of the indicator text.
+ *
+ * \b Details \n
+ *
+ * \image html kprogress.png "KDE Progress Widget"
+ *
+ * @author Aaron Seigo
+ */
+class KDEUI_EXPORT KProgress : public QProgressBar
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Construct a progress bar.
+ */
+ KProgress(QWidget *parent=0, const char *name=0, WFlags f = 0);
+
+ /**
+ * Construct a progress bar with a total number of steps.
+ * The totalSteps is the total number of steps that need to be completed for the operation which this progress
+ * bar represents. For example, if the operation is to examine 50 files, this value would be 50. Before examining
+ * the first file, call setProgress(0); call setProgress(50) after examining the last file.
+ */
+ KProgress(int totalSteps, QWidget *parent=0, const char *name=0, WFlags f = 0);
+
+ /**
+ * Destruct the progress bar.
+ */
+ ~KProgress();
+
+ /**
+ * If this is set to @p true, the progress text will be displayed.
+ *
+ */
+ void setTextEnabled(bool);
+
+ /**
+ * @deprecated Retrieves the current status, use progress() instead
+ *
+ * @see setValue()
+ */
+ // ### Remove this KDE 4.0
+ int value() const KDE_DEPRECATED;
+
+ /**
+ * Returns @p true if progress text will be displayed,
+ * @p false otherwise.
+ *
+ * @see setFormat()
+ */
+ bool textEnabled() const;
+
+ /**
+ * Retrieve the current format for printing status text.
+ * @see setFormat()
+ */
+ QString format() const;
+
+ /**
+ * @deprecated but kept for source compatibility with KDE2's KProgress.
+ * Use setTotalSteps() instead
+ */
+ // ### Remove this KDE 4.0
+ void setRange(int min, int max) KDE_DEPRECATED;
+
+ /**
+ * @deprecated Use totalSteps() instead
+ */
+ // ### Remove this KDE 4.0
+ int maxValue() KDE_DEPRECATED;
+
+public slots:
+
+ /**
+ * Set the format of the text to use to display status.
+ *
+ * The default format is "%p%" (which looks like "42%".)
+ *
+ * Note: Setting the format to anything other then "%p%" will force centerIndicator to true,
+ * since it's often impossible to layout a progressbar with a more general format with the
+ * indicator string anywhere else.
+ *
+ * @param format "%p" is replaced by percentage done, "%v" is replaced by actual
+ * value, "%m" is replaced by the maximum value.
+ */
+ void setFormat(const QString & format);
+
+ /**
+ * Set the current total number of steps in the action that the progress bar
+ * is representing.
+ */
+ void setTotalSteps(int totalSteps);
+
+ /**
+ * Set the current value of the progress bar to @p progress.
+ */
+ virtual void setProgress(int progress);
+
+ /**
+ * @deprecated Use setProgress(int) instead
+ */
+ // ### Remove this KDE 4.0
+ void setValue(int progress);
+
+ /**
+ * Advance the progress bar by @p offset.
+ *
+ * This method is
+ * provided for convenience and is equivalent with
+ * setProgress(progress()+offset).
+ */
+ virtual void advance(int offset);
+
+signals:
+ /**
+ * Emitted when the state of the progress bar changes.
+ */
+ void percentageChanged(int);
+
+protected:
+ virtual bool setIndicator(QString & indicator, int progress, int totalSteps);
+
+private:
+ QString mFormat;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KProgressPrivate;
+ KProgressPrivate *d;
+};
+
+/**
+ * KProgressDialog provides a dialog with a text label, a progress bar
+ * and an optional cancel button with a KDE look 'n feel.
+ *
+ * Since knowing how long it can take to complete an action and it is
+ * undesirable to show a dialog for a split second before hiding it,
+ * there are a few ways to control the timing behavior of KProgressDialog.
+ * There is a time out that can be set before showing the dialog as well
+ * as an option to autohide or keep displaying the dialog once complete.
+ *
+ * All the functionality of KProgress is available through direct access
+ * to the progress bar widget via progressBar();
+ *
+ * @short A dialog with a progress bar
+ * @author Aaron J. Seigo
+ */
+class KDEUI_EXPORT KProgressDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Constructs a KProgressDialog
+ *
+ * @param parent Parent of the widget
+ * @param name Widget name
+ * @param caption Text to display in window title bar
+ * @param text Text to display in the dialog
+ * @param modal Set to true to make the dialog modal
+ */
+ KProgressDialog(QWidget* parent = 0, const char* name = 0,
+ const QString& caption = QString::null,
+ const QString& text = QString::null,
+ bool modal = false);
+
+ /**
+ * Destructor
+ */
+ ~KProgressDialog();
+
+ /**
+ * Returns the KProgress used in this dialog.
+ * To set the number of steps or other progress bar related
+ * settings, access the KProgress object directly via this method.
+ */
+ KProgress* progressBar();
+
+ /**
+ * Returns the KProgress used in this dialog.
+ * To set the number of steps or other progress bar related
+ * settings, access the KProgress object directly via this method.
+ */
+ const KProgress* progressBar() const;
+
+ /**
+ * Sets the text in the dialog
+ *
+ * @param text the text to display
+ */
+ void setLabel(const QString & text);
+
+ /**
+ * Returns the current dialog text
+ * @deprecated
+ */
+ // ### Remove this KDE 4.0
+ QString labelText() KDE_DEPRECATED;
+
+ /**
+ * Returns the current dialog text
+ */
+ QString labelText() const;
+
+ /**
+ * Sets whether or not the user can cancel the process.
+ * If the dialog is cancellable, the Cancel button will be shown
+ * and the user can close the window using the window decorations.
+ * If the process is not (or should not be) interuptable,
+ * set the dialog to be modal and not cancellable.
+ *
+ * @param allowCancel Set to true to make the dialog non-closable
+ */
+ void setAllowCancel(bool allowCancel);
+
+ /**
+ * Returns true if the dialog can be canceled, false otherwise
+ * @deprecated
+ */
+ // ### Remove this KDE 4.0
+ bool allowCancel() KDE_DEPRECATED;
+
+ /**
+ * Returns true if the dialog can be canceled, false otherwise
+ */
+ bool allowCancel() const;
+
+ /**
+ * Sets whether the cancel button is visible. setAllowCancel(false)
+ * implies showCancelButton(false)
+ *
+ * @param show Whether or not the cancel button should be shown
+ */
+ void showCancelButton(bool show);
+
+ /**
+ * Sets whether the dialog should close automagically when
+ * all the steps in the KProgress have been completed.
+ */
+ void setAutoClose(bool close);
+
+ /**
+ * Returns true if the dialog will close upon completion,
+ * or false otherwise
+ */
+ // ### Remove this KDE 4.0
+ bool autoClose();
+
+ /**
+ * Returns true if the dialog will close upon completion,
+ * or false otherwise
+ */
+ bool autoClose() const;
+
+ /**
+ * Sets whether the dialog should reset the KProgress dialog
+ * back to 0 steps compelete when all steps have been completed.
+ * This is useful for KProgressDialogs that will be reused.
+ */
+ void setAutoReset(bool autoReset);
+
+ /**
+ * Returns true if the KProgress widget will be reset
+ * upon completion, or false otherwise
+ */
+ // ### Remove this KDE 4.0
+ bool autoReset();
+
+ /**
+ * Returns true if the KProgress widget will be reset
+ * upon completion, or false otherwise
+ */
+ bool autoReset() const;
+
+ /**
+ * Returns true if the dialog was closed or canceled
+ * before completion. If the dialog is not cancellable
+ * it will always return false.
+ */
+ // ### Remove this KDE 4.0
+ bool wasCancelled();
+
+ /**
+ * Returns true if the dialog was closed or canceled
+ * before completion. If the dialog is not cancellable
+ * it will always return false.
+ */
+ bool wasCancelled() const;
+
+ /**
+ * Ignores the last cancel action if the cancel button was
+ * pressed. Useful for kdialog when combined with a KMessageBox
+ * to display a message like "Are you sure you want to cancel?"
+ * @since 3.5.5
+ */
+ void ignoreCancel();
+
+ /**
+ * Sets the text to appear on the cancel button.
+ */
+ void setButtonText(const QString&);
+
+ /**
+ * Returns the text on the cancel button
+ * @deprecated
+ */
+ // ### Remove this KDE 4.0
+ QString buttonText() KDE_DEPRECATED;
+
+ /**
+ * Returns the text on the cancel button
+ */
+ QString buttonText() const;
+
+ /**
+ * Set the minimum number of milliseconds to wait before
+ * actually showing the dialog
+ */
+ void setMinimumDuration(int ms);
+
+ /**
+ * Returns the wait duration in milliseconds
+ * @deprecated
+ */
+ // ### Remove this KDE 4.0
+ int minimumDuration() KDE_DEPRECATED;
+
+ /**
+ * Returns the wait duration in milliseconds
+ */
+ int minimumDuration() const;
+
+ /**
+ * Reimplemented for internal reasons, the API is not affected.
+ */
+ virtual void show();
+
+ protected slots:
+ void slotAutoShow();
+ void slotAutoActions(int percentage);
+ void slotCancel();
+
+ private:
+ // ### Move these member variables to d in KDE 4.0
+ bool mAutoClose;
+ bool mAutoReset;
+ bool mCancelled;
+ bool mAllowCancel;
+ bool mShown;
+ QString mCancelText;
+ QLabel* mLabel;
+ KProgress* mProgressBar;
+ QTimer* mShowTimer;
+ int mMinDuration;
+ protected:
+ virtual void virtual_hook( int id, void* data );
+ private:
+ struct KProgressDialogPrivate;
+ KProgressDialogPrivate *d;
+};
+
+#endif
diff --git a/kdeui/kpushbutton.cpp b/kdeui/kpushbutton.cpp
new file mode 100644
index 000000000..a755fe3b3
--- /dev/null
+++ b/kdeui/kpushbutton.cpp
@@ -0,0 +1,220 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kpushbutton.h"
+
+#include <qdragobject.h>
+#include <qwhatsthis.h>
+#include <qtooltip.h>
+
+#include "config.h"
+
+#include <kglobalsettings.h>
+#include <kconfig.h>
+#include <kglobal.h>
+#include <kipc.h>
+#include <kapplication.h>
+
+class KPushButton::KPushButtonPrivate
+{
+public:
+ KGuiItem item;
+ KStdGuiItem::StdItem itemType;
+};
+
+bool KPushButton::s_useIcons = false;
+
+KPushButton::KPushButton( QWidget *parent, const char *name )
+ : QPushButton( parent, name ),
+ m_dragEnabled( false )
+{
+ init( KGuiItem( "" ) );
+}
+
+KPushButton::KPushButton( const QString &text, QWidget *parent,
+ const char *name)
+ : QPushButton( parent, name ),
+ m_dragEnabled( false )
+{
+ init( KGuiItem( text ) );
+}
+
+KPushButton::KPushButton( const QIconSet &icon, const QString &text,
+ QWidget *parent, const char *name )
+ : QPushButton( text, parent, name ),
+ m_dragEnabled( false )
+{
+ init( KGuiItem( text, icon ) );
+}
+
+KPushButton::KPushButton( const KGuiItem &item, QWidget *parent,
+ const char *name )
+ : QPushButton( parent, name ),
+ m_dragEnabled( false )
+{
+ init( item );
+}
+
+KPushButton::~KPushButton()
+{
+ if( d )
+ {
+ delete d;
+ d = 0L;
+ }
+}
+
+void KPushButton::init( const KGuiItem &item )
+{
+ d = new KPushButtonPrivate;
+ d->item = item;
+ d->itemType = (KStdGuiItem::StdItem) 0;
+
+ // call QPushButton's implementation since we don't need to
+ // set the GUI items text or check the state of the icon set
+ QPushButton::setText( d->item.text() );
+
+ static bool initialized = false;
+ if ( !initialized ) {
+ readSettings();
+ initialized = true;
+ }
+
+ setIconSet( d->item.iconSet() );
+
+ setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ) );
+
+ QToolTip::add( this, item.toolTip() );
+
+ QWhatsThis::add( this, item.whatsThis() );
+
+ if (kapp)
+ {
+ connect( kapp, SIGNAL( settingsChanged(int) ),
+ SLOT( slotSettingsChanged(int) ) );
+ kapp->addKipcEventMask( KIPC::SettingsChanged );
+ }
+}
+
+void KPushButton::readSettings()
+{
+ s_useIcons = KGlobalSettings::showIconsOnPushButtons();
+}
+
+void KPushButton::setGuiItem( const KGuiItem& item )
+{
+ d->item = item;
+
+ // call QPushButton's implementation since we don't need to
+ // set the GUI items text or check the state of the icon set
+ QPushButton::setText( d->item.text() );
+ setIconSet( d->item.iconSet() );
+ QWhatsThis::add( this, d->item.whatsThis() );
+
+ // Do not add a tooltip to the button automatically as 99% of the time the
+ // tooltip is redundant to the button text and it results in QTipManager
+ // invoking an eventHandler on the QApplication which breaks certain apps
+ // like KDesktop which are sensitive to such things
+// QToolTip::add( this, d->item.toolTip() );
+}
+
+void KPushButton::setGuiItem( KStdGuiItem::StdItem item )
+{
+ setGuiItem( KStdGuiItem::guiItem(item) );
+ d->itemType = item;
+}
+
+KStdGuiItem::StdItem KPushButton::guiItem() const
+{
+ return d->itemType;
+}
+
+void KPushButton::setText( const QString &text )
+{
+ QPushButton::setText(text);
+
+ // we need to re-evaluate the icon set when the text
+ // is removed, or when it is supplied
+ if (text.isEmpty() != d->item.text().isEmpty())
+ setIconSet(d->item.iconSet());
+
+ d->item.setText(text);
+}
+
+void KPushButton::setIconSet( const QIconSet &iconSet )
+{
+ d->item.setIconSet(iconSet);
+
+ if ( s_useIcons || text().isEmpty() )
+ QPushButton::setIconSet( iconSet );
+ else
+ QPushButton::setIconSet( QIconSet() );
+}
+
+void KPushButton::slotSettingsChanged( int /* category */ )
+{
+ readSettings();
+ setIconSet( d->item.iconSet() );
+}
+
+void KPushButton::setDragEnabled( bool enable )
+{
+ m_dragEnabled = enable;
+}
+
+void KPushButton::mousePressEvent( QMouseEvent *e )
+{
+ if ( m_dragEnabled )
+ startPos = e->pos();
+ QPushButton::mousePressEvent( e );
+}
+
+void KPushButton::mouseMoveEvent( QMouseEvent *e )
+{
+ if ( !m_dragEnabled )
+ {
+ QPushButton::mouseMoveEvent( e );
+ return;
+ }
+
+ if ( (e->state() & LeftButton) &&
+ (e->pos() - startPos).manhattanLength() >
+ KGlobalSettings::dndEventDelay() )
+ {
+ startDrag();
+ setDown( false );
+ }
+}
+
+QDragObject * KPushButton::dragObject()
+{
+ return 0L;
+}
+
+void KPushButton::startDrag()
+{
+ QDragObject *d = dragObject();
+ if ( d )
+ d->dragCopy();
+}
+
+void KPushButton::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "kpushbutton.moc"
diff --git a/kdeui/kpushbutton.h b/kdeui/kpushbutton.h
new file mode 100644
index 000000000..637cfceb3
--- /dev/null
+++ b/kdeui/kpushbutton.h
@@ -0,0 +1,161 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KPUSHBUTTON_H
+#define KPUSHBUTTON_H
+
+#include <qpoint.h>
+#include <qpushbutton.h>
+#include <kguiitem.h>
+#include <kstdguiitem.h>
+
+class QDragObject;
+/**
+ * This is nothing but a QPushButton with drag-support and KGuiItem support. You have to call
+ * setDragEnabled( true ) and override the virtual method
+ * dragObject() to specify the QDragObject to be used.
+ *
+ * @short A QPushButton with drag-support and KGuiItem support
+ * @author Carsten Pfeiffer <pfeiffer@kde.org>
+ */
+class KDEUI_EXPORT KPushButton : public QPushButton
+{
+ Q_OBJECT
+ Q_PROPERTY(int stdItem READ guiItm WRITE setGuiItm )
+ Q_PROPERTY(bool isDragEnabled READ isDragEnabled WRITE setDragEnabled)
+
+public:
+
+ /**
+ * Default constructor.
+ */
+ KPushButton( QWidget *parent, const char *name=0 );
+
+ /**
+ * Constructor, that sets the button-text to @p text
+ */
+ KPushButton( const QString &text, QWidget *parent, const char *name=0);
+
+ /**
+ * Constructor, that sets an icon and the button-text to @p text
+ */
+ KPushButton( const QIconSet &icon, const QString &text,
+ QWidget *parent, const char *name=0 );
+
+ /**
+ * Constructor that takes a KGuiItem for the text, the icon, the tooltip
+ * and the what's this help
+ */
+ KPushButton( const KGuiItem &item, QWidget *parent, const char *name = 0 );
+
+ /**
+ * Destructs the button.
+ */
+ ~KPushButton();
+
+ /**
+ * Enables/disables drag-support. Default is disabled.
+ */
+ void setDragEnabled( bool enable );
+
+ /**
+ * @returns if drag support is enabled or not.
+ */
+ bool isDragEnabled() const { return m_dragEnabled; }
+
+ /**
+ * Sets the KGuiItem for this button.
+ */
+ void setGuiItem( const KGuiItem& item );
+
+ /**
+ * Sets the standard KGuiItem for this button.
+ * @since 3.4
+ */
+ void setGuiItem( KStdGuiItem::StdItem item );
+
+ /**
+ * Reads the standard KGuiItem for this button.
+ * @since 3.4
+ */
+ KStdGuiItem::StdItem guiItem() const;
+
+ // Hack for Qt designer
+ void setGuiItm(int itm ) { setGuiItem( (KStdGuiItem::StdItem)itm );}
+ int guiItm() const { return (int)guiItem(); }
+
+ /**
+ * Sets the Icon Set for this button. It also takes into account hte
+ * KGlobalSettings::showIconsOnPushButtons() setting.
+ */
+ void setIconSet( const QIconSet &iconSet );
+
+ /**
+ * Sets the text of the button
+ */
+ void setText( const QString &text );
+
+protected:
+ /**
+ * Reimplement this and return the QDragObject that should be used
+ * for the drag.
+ * Default implementation returns 0L, so that no drag is initiated.
+ */
+ virtual QDragObject * dragObject();
+
+ /**
+ * Reimplemented to add drag-support
+ */
+ virtual void mousePressEvent( QMouseEvent * );
+ /**
+ * Reimplemented to add drag-support
+ */
+ virtual void mouseMoveEvent( QMouseEvent * );
+
+ /**
+ * Starts a drag (dragCopy() by default) using dragObject()
+ */
+ virtual void startDrag();
+
+private:
+ bool m_dragEnabled;
+ QPoint startPos;
+
+private slots:
+ void slotSettingsChanged( int category );
+
+private:
+ /**
+ * Internal.
+ * Initialize the KPushButton instance
+ */
+ void init( const KGuiItem &item );
+
+ void readSettings();
+ static bool s_useIcons;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KPushButtonPrivate;
+ KPushButtonPrivate *d;
+
+};
+
+#endif // KPUSHBUTTON_H
diff --git a/kdeui/krestrictedline.cpp b/kdeui/krestrictedline.cpp
new file mode 100644
index 000000000..1847017d5
--- /dev/null
+++ b/kdeui/krestrictedline.cpp
@@ -0,0 +1,81 @@
+/*
+ *
+ *
+ * Implementation of KRestrictedLine
+ *
+ * Copyright (C) 1997 Michael Wiedmann, <mw@miwie.in-berlin.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <qkeycode.h>
+
+#include "krestrictedline.h"
+
+KRestrictedLine::KRestrictedLine( QWidget *parent,
+ const char *name,
+ const QString& valid )
+ : KLineEdit( parent, name )
+{
+ qsValidChars = valid;
+}
+
+KRestrictedLine::~KRestrictedLine()
+{
+ ;
+}
+
+
+void KRestrictedLine::keyPressEvent( QKeyEvent *e )
+{
+ // let QLineEdit process "special" keys and return/enter
+ // so that we still can use the default key binding
+ if (e->key() == Key_Enter || e->key() == Key_Return || e->key() == Key_Delete || e->ascii() < 32)
+ {
+ QLineEdit::keyPressEvent(e);
+ return;
+ }
+
+ // do we have a list of valid chars &&
+ // is the pressed key in the list of valid chars?
+ if (!qsValidChars.isEmpty() && !qsValidChars.contains(e->ascii()))
+ {
+ // invalid char, emit signal and return
+ emit (invalidChar(e->key()));
+ return;
+ }
+ else
+ // valid char: let QLineEdit process this key as usual
+ QLineEdit::keyPressEvent(e);
+
+ return;
+}
+
+
+void KRestrictedLine::setValidChars( const QString& valid)
+{
+ qsValidChars = valid;
+}
+
+QString KRestrictedLine::validChars() const
+{
+ return qsValidChars;
+}
+
+void KRestrictedLine::virtual_hook( int id, void* data )
+{ KLineEdit::virtual_hook( id, data ); }
+
+#include "krestrictedline.moc"
diff --git a/kdeui/krestrictedline.h b/kdeui/krestrictedline.h
new file mode 100644
index 000000000..884b25782
--- /dev/null
+++ b/kdeui/krestrictedline.h
@@ -0,0 +1,95 @@
+/*
+ *
+ * $Id$
+ *
+ * Definition of KRestrictedLine
+ *
+ * Copyright (C) 1997 Michael Wiedmann, <mw@miwie.in-berlin.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef KRESTRICTEDLINE_H
+#define KRESTRICTEDLINE_H
+
+#include <klineedit.h>
+
+/**
+ * @short A line editor for restricted character sets.
+ *
+ * The KRestrictedLine widget is a variant of QLineEdit which
+ * accepts only a restricted set of characters as input.
+ * All other characters will be discarded and the signal invalidChar()
+ * will be emitted for each of them.
+ *
+ * Valid characters can be passed as a QString to the constructor
+ * or set afterwards via setValidChars().
+ * The default key bindings of QLineEdit are still in effect.
+ *
+ * @author Michael Wiedmann <mw@miwie.in-berlin.de>
+ */
+class KDEUI_EXPORT KRestrictedLine : public KLineEdit
+{
+ Q_OBJECT
+ Q_PROPERTY( QString validChars READ validChars WRITE setValidChars )
+
+public:
+
+ /**
+ * Constructor: This contructor takes three - optional - arguments.
+ * The first two parameters are simply passed on to QLineEdit.
+ * @param parent pointer to the parent widget
+ * @param name pointer to the name of this widget
+ * @param valid pointer to set of valid characters
+ */
+ KRestrictedLine( QWidget *parent=0, const char *name=0,
+ const QString& valid = QString::null);
+
+ /**
+ * Destructs the restricted line editor.
+ */
+ ~KRestrictedLine();
+
+ /**
+ * All characters in the string valid are treated as
+ * acceptable characters.
+ */
+ void setValidChars(const QString& valid);
+ /**
+ * @return the string of acceptable characters.
+ */
+ QString validChars() const;
+
+signals:
+
+ /**
+ * Emitted when an invalid character was typed.
+ */
+ void invalidChar(int);
+
+protected:
+ void keyPressEvent( QKeyEvent *e );
+
+private:
+ /// QString of valid characters for this line
+ QString qsValidChars;
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KRestrictedLinePrivate* d;
+};
+
+#endif // KRESTRICTEDLINE_H
diff --git a/kdeui/krootpixmap.cpp b/kdeui/krootpixmap.cpp
new file mode 100644
index 000000000..5f9591b5b
--- /dev/null
+++ b/kdeui/krootpixmap.cpp
@@ -0,0 +1,332 @@
+/* vi: ts=8 sts=4 sw=4
+ *
+ *
+ * This file is part of the KDE project, module kdeui.
+ * Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org>
+ *
+ * You can Freely distribute this program under the GNU Library
+ * General Public License. See the file "COPYING.LIB" for the exact
+ * licensing terms.
+ */
+
+#include <qwidget.h>
+#include <qtimer.h>
+#include <qrect.h>
+#include <qimage.h>
+
+#include <kapplication.h>
+#include <kimageeffect.h>
+#include <kpixmapio.h>
+#include <kwinmodule.h>
+#include <kwin.h>
+#include <kdebug.h>
+#include <netwm.h>
+#include <dcopclient.h>
+#include <dcopref.h>
+
+#include <ksharedpixmap.h>
+#include <krootpixmap.h>
+
+
+static QString wallpaperForDesktop(int desktop)
+{
+ return DCOPRef("kdesktop", "KBackgroundIface").call("currentWallpaper", desktop);
+}
+
+class KRootPixmapData
+{
+public:
+ QWidget *toplevel;
+#ifdef Q_WS_X11
+ KWinModule *kwin;
+#endif
+};
+
+
+KRootPixmap::KRootPixmap( QWidget *widget, const char *name )
+ : QObject(widget, name ? name : "KRootPixmap" ), m_Desk(0), m_pWidget(widget)
+{
+ init();
+}
+
+KRootPixmap::KRootPixmap( QWidget *widget, QObject *parent, const char *name )
+ : QObject( parent, name ? name : "KRootPixmap" ), m_Desk(0), m_pWidget(widget)
+{
+ init();
+}
+
+void KRootPixmap::init()
+{
+ d = new KRootPixmapData;
+ m_Fade = 0;
+ m_pPixmap = new KSharedPixmap; //ordinary KPixmap on win32
+ m_pTimer = new QTimer( this );
+ m_bInit = false;
+ m_bActive = false;
+ m_bCustomPaint = false;
+
+ connect(kapp, SIGNAL(backgroundChanged(int)), SLOT(slotBackgroundChanged(int)));
+ connect(m_pTimer, SIGNAL(timeout()), SLOT(repaint()));
+#ifdef Q_WS_X11
+ connect(m_pPixmap, SIGNAL(done(bool)), SLOT(slotDone(bool)));
+
+ d->kwin = new KWinModule( this );
+ connect(d->kwin, SIGNAL(windowChanged(WId, unsigned int)), SLOT(desktopChanged(WId, unsigned int)));
+ connect(d->kwin, SIGNAL(currentDesktopChanged(int)), SLOT(desktopChanged(int)));
+#endif
+
+ d->toplevel = m_pWidget->topLevelWidget();
+ d->toplevel->installEventFilter(this);
+ m_pWidget->installEventFilter(this);
+}
+
+KRootPixmap::~KRootPixmap()
+{
+ delete m_pPixmap;
+ delete d;
+}
+
+
+int KRootPixmap::currentDesktop() const
+{
+#ifdef Q_WS_X11
+ NETRootInfo rinfo( qt_xdisplay(), NET::CurrentDesktop );
+ rinfo.activate();
+ return rinfo.currentDesktop();
+#else
+ //OK?
+ return QApplication::desktop()->screenNumber(m_pWidget);
+#endif
+}
+
+
+void KRootPixmap::start()
+{
+ if (m_bActive)
+ return;
+
+ m_bActive = true;
+ if ( !isAvailable() )
+ {
+ // We will get a KIPC message when the shared pixmap is available.
+ enableExports();
+ return;
+ }
+ if (m_bInit)
+ repaint(true);
+}
+
+
+void KRootPixmap::stop()
+{
+ m_bActive = false;
+ m_pTimer->stop();
+}
+
+
+void KRootPixmap::setFadeEffect(double fade, const QColor &color)
+{
+ if (fade < 0)
+ m_Fade = 0;
+ else if (fade > 1)
+ m_Fade = 1;
+ else
+ m_Fade = fade;
+ m_FadeColor = color;
+
+ if ( m_bActive && m_bInit ) repaint(true);
+}
+
+
+bool KRootPixmap::eventFilter(QObject *, QEvent *event)
+{
+ // Initialise after the first show or paint event on the managed widget.
+ if (!m_bInit && ((event->type() == QEvent::Show) || (event->type() == QEvent::Paint)))
+ {
+ m_bInit = true;
+ m_Desk = currentDesktop();
+ }
+
+ if (!m_bActive)
+ return false;
+
+ switch (event->type())
+ {
+ case QEvent::Resize:
+ case QEvent::Move:
+ m_pTimer->start(100, true);
+ break;
+
+ case QEvent::Paint:
+ m_pTimer->start(0, true);
+ break;
+
+ case QEvent::Reparent:
+ d->toplevel->removeEventFilter(this);
+ d->toplevel = m_pWidget->topLevelWidget();
+ d->toplevel->installEventFilter(this);
+ break;
+
+ default:
+ break;
+ }
+
+ return false; // always continue processing
+}
+
+void KRootPixmap::desktopChanged(int desktop)
+{
+ if (wallpaperForDesktop(m_Desk) == wallpaperForDesktop(desktop) &&
+ !wallpaperForDesktop(m_Desk).isNull())
+ return;
+
+#ifdef Q_WS_X11
+ if (KWin::windowInfo(m_pWidget->topLevelWidget()->winId()).desktop() == NET::OnAllDesktops &&
+ pixmapName(m_Desk) != pixmapName(desktop))
+#endif
+ repaint(true);
+}
+
+void KRootPixmap::desktopChanged( WId window, unsigned int properties )
+{
+#ifdef Q_WS_X11
+ if( !(properties & NET::WMDesktop) ||
+ (window != m_pWidget->topLevelWidget()->winId()))
+ return;
+#endif
+
+ kdDebug() << k_funcinfo << endl;
+ repaint(true);
+}
+
+void KRootPixmap::repaint()
+{
+ repaint(false);
+}
+
+
+void KRootPixmap::repaint(bool force)
+{
+ QPoint p1 = m_pWidget->mapToGlobal(m_pWidget->rect().topLeft());
+ QPoint p2 = m_pWidget->mapToGlobal(m_pWidget->rect().bottomRight());
+ if (!force && (m_Rect == QRect(p1, p2)))
+ return;
+
+ // Due to northwest bit gravity, we don't need to do anything if the
+ // bottom right corner of the widget is moved inward.
+ // That said, konsole clears the background when it is resized, so
+ // we have to reset the background pixmap.
+ if ((p1 == m_Rect.topLeft()) && (m_pWidget->width() < m_Rect.width()) &&
+ (m_pWidget->height() < m_Rect.height())
+ )
+ {
+ m_Rect = QRect(p1, p2);
+ updateBackground( m_pPixmap );
+ return;
+ }
+ m_Rect = QRect(p1, p2);
+#ifdef Q_WS_X11
+ m_Desk = KWin::windowInfo(m_pWidget->topLevelWidget()->winId()).desktop();
+ if (m_Desk == NET::OnAllDesktops)
+ m_Desk = currentDesktop();
+
+ // KSharedPixmap will correctly generate a tile for us.
+ m_pPixmap->loadFromShared(pixmapName(m_Desk), m_Rect);
+#else
+ m_Desk = currentDesktop();
+ // !x11 note: tile is not generated!
+ // TODO: pixmapName() is a nonsense now!
+ m_pPixmap->load( pixmapName(m_Desk) );
+ if (!m_pPixmap->isNull()) {
+ m_pPixmap->resize( m_Rect.size() );
+ slotDone(true);
+ }
+#endif
+}
+
+bool KRootPixmap::isAvailable() const
+{
+#ifdef Q_WS_X11
+ return m_pPixmap->isAvailable(pixmapName(m_Desk));
+#else
+ return m_pPixmap->isNull();
+#endif
+}
+
+QString KRootPixmap::pixmapName(int desk) {
+ QString pattern = QString("DESKTOP%1");
+#ifdef Q_WS_X11
+ int screen_number = DefaultScreen(qt_xdisplay());
+ if (screen_number) {
+ pattern = QString("SCREEN%1-DESKTOP").arg(screen_number) + "%1";
+ }
+#endif
+ return pattern.arg( desk );
+}
+
+
+void KRootPixmap::enableExports()
+{
+#ifdef Q_WS_X11
+ kdDebug(270) << k_lineinfo << "activating background exports.\n";
+ DCOPClient *client = kapp->dcopClient();
+ if (!client->isAttached())
+ client->attach();
+ QByteArray data;
+ QDataStream args( data, IO_WriteOnly );
+ args << 1;
+
+ QCString appname( "kdesktop" );
+ int screen_number = DefaultScreen(qt_xdisplay());
+ if ( screen_number )
+ appname.sprintf("kdesktop-screen-%d", screen_number );
+
+ client->send( appname, "KBackgroundIface", "setExport(int)", data );
+#endif
+}
+
+
+void KRootPixmap::slotDone(bool success)
+{
+ if (!success)
+ {
+ kdWarning(270) << k_lineinfo << "loading of desktop background failed.\n";
+ return;
+ }
+
+ // We need to test active as the pixmap might become available
+ // after the widget has been destroyed.
+ if ( m_bActive )
+ updateBackground( m_pPixmap );
+}
+
+void KRootPixmap::updateBackground( KSharedPixmap *spm )
+{
+ QPixmap pm = *spm;
+
+ if (m_Fade > 1e-6)
+ {
+ KPixmapIO io;
+ QImage img = io.convertToImage(pm);
+ img = KImageEffect::fade(img, m_Fade, m_FadeColor);
+ pm = io.convertToPixmap(img);
+ }
+
+ if ( !m_bCustomPaint )
+ m_pWidget->setBackgroundPixmap( pm );
+ else {
+ emit backgroundUpdated( pm );
+ }
+}
+
+
+void KRootPixmap::slotBackgroundChanged(int desk)
+{
+ if (!m_bInit || !m_bActive)
+ return;
+
+ if (desk == m_Desk)
+ repaint(true);
+}
+
+#include "krootpixmap.moc"
diff --git a/kdeui/krootpixmap.h b/kdeui/krootpixmap.h
new file mode 100644
index 000000000..3eef65f51
--- /dev/null
+++ b/kdeui/krootpixmap.h
@@ -0,0 +1,216 @@
+/* vi: ts=8 sts=4 sw=4
+ *
+ * $Id$
+ * This file is part of the KDE project, module kdesktop.
+ * Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org>
+ *
+ * You can Freely distribute this program under the GNU Library General
+ * Public License. See the file "COPYING.LIB" for the exact licensing terms.
+ */
+
+#ifndef __KRootPixmap_h_Included__
+#define __KRootPixmap_h_Included__
+
+#include <qobject.h>
+#include <qcolor.h>
+#include <kdelibs_export.h>
+
+#ifndef Q_WS_QWS //FIXME
+
+class QRect;
+class QWidget;
+class QTimer;
+class KSharedPixmap;
+class KRootPixmapData;
+
+/**
+ * Creates pseudo-transparent widgets.
+ *
+ * A pseudo-transparent widget is a widget with its background pixmap set to
+ * that part of the desktop background that it is currently obscuring. This
+ * gives a transparency effect.
+ *
+ * To create a transparent widget, construct a KRootPixmap and pass it a
+ * pointer to your widget. That's it! Moving, resizing and background changes
+ * are handled automatically.
+ *
+ * Instead of using the default behavior, you can ask KRootPixmap
+ * to emit a backgroundUpdated(const QPixmap &) signal whenever
+ * the background needs updating by using setCustomPainting(bool).
+ * Alternatively by reimplementing updateBackground(KSharedPixmap*)
+ * you can take complete control of the behavior.
+ *
+ * @author Geert Jansen <jansen@kde.org>
+ * @version $Id$
+ */
+class KDEUI_EXPORT KRootPixmap: public QObject
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Constructs a KRootPixmap. The KRootPixmap will be created as a child
+ * of the target widget so it will be deleted automatically when the
+ * widget is destroyed.
+ *
+ * @param target A pointer to the widget that you want to make pseudo
+ * transparent.
+ * @param name The internal name of the pixmap
+ */
+ KRootPixmap( QWidget *target, const char *name=0 );
+
+ /**
+ * Constructs a KRootPixmap where the parent QObject and target QWidget are
+ * different.
+ */
+ KRootPixmap( QWidget *target, QObject *parent, const char *name=0 );
+
+ /**
+ * Destructs the object.
+ */
+ virtual ~KRootPixmap();
+
+ /**
+ * Checks if pseudo-transparency is available.
+ * @return @p true if transparency is available, @p false otherwise.
+ */
+ bool isAvailable() const;
+
+ /**
+ * Returns true if the KRootPixmap is active.
+ */
+ bool isActive() const { return m_bActive; }
+
+ /**
+ * Returns the number of the current desktop.
+ */
+ int currentDesktop() const;
+
+ /**
+ * Returns true if custom painting is enabled, false otherwise.
+ * @see setCustomPainting(bool)
+ */
+ bool customPainting() const { return m_bCustomPaint; }
+
+#ifndef KDE_NO_COMPAT
+ /**
+ * Deprecated, use isAvailable() instead.
+ * @deprecated
+ */
+ KDE_DEPRECATED bool checkAvailable(bool) { return isAvailable(); }
+#endif
+
+ /** @since 3.2
+ * @return the fade color.
+ */
+ const QColor &color() const { return m_FadeColor; }
+
+ /** @since 3.2
+ * @return the color opacity.
+ */
+ double opacity() const { return m_Fade; }
+
+public slots:
+ /**
+ * Starts background handling.
+ */
+ virtual void start();
+
+ /**
+ * Stops background handling.
+ */
+ virtual void stop();
+
+ /**
+ * Sets the fade effect.
+ *
+ * This effect will fade the background to the
+ * specified color.
+ * @param opacity A value between 0 and 1, indicating the opacity
+ * of the color. A value of 0 will not change the image, a value of 1
+ * will use the fade color unchanged.
+ * @param color The color to fade to.
+ */
+ void setFadeEffect(double opacity, const QColor &color);
+
+ /**
+ * Repaints the widget background. Normally, you shouldn't need this
+ * as it is handled automatically.
+ *
+ * @param force Force a repaint, even if the contents did not change.
+ */
+ void repaint( bool force );
+
+ /**
+ * Repaints the widget background. Normally, you shouldn't need this
+ * as it is handled automatically. This is equivalent to calling
+ * repaint( false ).
+ */
+ void repaint();
+
+ /**
+ * Enables custom handling of the background painting. If custom
+ * painting is enabled then KRootPixmap will emit a
+ * backgroundUpdated() signal when the background for the
+ * target widget changes, instead of applying the new background.
+ */
+ void setCustomPainting( bool enable ) { m_bCustomPaint = enable; }
+
+ /**
+ * Asks KDesktop to export the desktop background as a KSharedPixmap.
+ * This method uses DCOP to call KBackgroundIface/setExport(int).
+ */
+ void enableExports();
+
+ /**
+ * Returns the name of the shared pixmap (only needed for low level access)
+ */
+ static QString pixmapName(int desk);
+signals:
+ /**
+ * Emitted when the background needs updating and custom painting
+ * (see setCustomPainting(bool) ) is enabled.
+ *
+ * @param pm A pixmap containing the new background.
+ */
+ void backgroundUpdated( const QPixmap &pm );
+
+protected:
+ /**
+ * Reimplemented to filter the events from the target widget and
+ * track its movements.
+ */
+ virtual bool eventFilter(QObject *, QEvent *);
+
+ /**
+ * Called when the pixmap has been updated. The default implementation
+ * applies the fade effect, then sets the target's background, or emits
+ * backgroundUpdated(const QPixmap &) depending on the painting mode.
+ */
+ virtual void updateBackground( KSharedPixmap * );
+
+private slots:
+ void slotBackgroundChanged(int);
+ void slotDone(bool);
+ void desktopChanged(int desktop);
+ void desktopChanged( WId window, unsigned int properties );
+
+private:
+ bool m_bActive, m_bInit, m_bCustomPaint;
+ int m_Desk;
+
+ double m_Fade;
+ QColor m_FadeColor;
+
+ QRect m_Rect;
+ QWidget *m_pWidget;
+ QTimer *m_pTimer;
+ KSharedPixmap *m_pPixmap;
+ KRootPixmapData *d;
+
+ void init();
+};
+
+#endif // ! Q_WS_QWS
+#endif // __KRootPixmap_h_Included__
+
diff --git a/kdeui/kruler.cpp b/kdeui/kruler.cpp
new file mode 100644
index 000000000..08cea5515
--- /dev/null
+++ b/kdeui/kruler.cpp
@@ -0,0 +1,742 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1998 Jörg Habenicht (j.habenicht@europemail.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#include "kruler.h"
+
+#include <qpainter.h>
+#include <qfont.h>
+
+#define INIT_VALUE 0
+#define INIT_MIN_VALUE 0
+#define INIT_MAX_VALUE 100
+#define INIT_TINY_MARK_DISTANCE 1
+#define INIT_LITTLE_MARK_DISTANCE 5
+#define INIT_MIDDLE_MARK_DISTANCE (INIT_LITTLE_MARK_DISTANCE * 2)
+#define INIT_BIG_MARK_DISTANCE (INIT_LITTLE_MARK_DISTANCE * 10)
+#define INIT_SHOW_TINY_MARK false
+#define INIT_SHOW_LITTLE_MARK true
+#define INIT_SHOW_MEDIUM_MARK true
+#define INIT_SHOW_BIG_MARK true
+#define INIT_SHOW_END_MARK true
+#define INIT_SHOW_POINTER true
+#define INIT_SHOW_END_LABEL true
+
+#define INIT_PIXEL_PER_MARK (double)10.0 /* distance between 2 base marks in pixel */
+#define INIT_OFFSET (-20)
+#define INIT_LENGTH_FIX true
+#define INIT_END_OFFSET 0
+
+#define FIX_WIDTH 20 /* widget width in pixel */
+#define LINE_END (FIX_WIDTH - 3)
+#define END_MARK_LENGTH (FIX_WIDTH - 6)
+#define END_MARK_X2 LINE_END
+#define END_MARK_X1 (END_MARK_X2 - END_MARK_LENGTH)
+#define BIG_MARK_LENGTH (END_MARK_LENGTH*3/4)
+#define BIG_MARK_X2 LINE_END
+#define BIG_MARK_X1 (BIG_MARK_X2 - BIG_MARK_LENGTH)
+#define MIDDLE_MARK_LENGTH (END_MARK_LENGTH/2)
+#define MIDDLE_MARK_X2 LINE_END
+#define MIDDLE_MARK_X1 (MIDDLE_MARK_X2 - MIDDLE_MARK_LENGTH)
+#define LITTLE_MARK_LENGTH (MIDDLE_MARK_LENGTH/2)
+#define LITTLE_MARK_X2 LINE_END
+#define LITTLE_MARK_X1 (LITTLE_MARK_X2 - LITTLE_MARK_LENGTH)
+#define BASE_MARK_LENGTH (LITTLE_MARK_LENGTH/2)
+#define BASE_MARK_X2 LINE_END
+#define BASE_MARK_X1 (BASE_MARK_X2 - BASE_MARK_LENGTH)
+
+#define LABEL_SIZE 8
+#define END_LABEL_X 4
+#define END_LABEL_Y (END_LABEL_X + LABEL_SIZE - 2)
+
+#undef PROFILING
+
+#ifdef PROFILING
+# include <qdatetime.h>
+#endif
+
+class KRuler::KRulerPrivate
+{
+public:
+ bool showpointer;
+ bool showEndL;
+ bool lengthFix;
+ int endOffset_length; /* marks the offset at the end of the ruler
+ * i.e. right side at horizontal and down side
+ * at vertical rulers.
+ * the ruler end mark is moved endOffset_length
+ * ticks away from the widget end.
+ * positive offset moves end mark inside the ruler.
+ * if lengthFix is true, endOffset_length holds the
+ * length of the ruler.
+ */
+ int fontWidth; // ONLY valid for vertical rulers
+};
+
+
+
+KRuler::KRuler(QWidget *parent, const char *name)
+ : QFrame(parent, name),
+ range(INIT_MIN_VALUE, INIT_MAX_VALUE, 1, 10, INIT_VALUE),
+ dir(Horizontal)
+{
+ init();
+ setFixedHeight(FIX_WIDTH);
+}
+
+
+KRuler::KRuler(Orientation orient,
+ QWidget *parent, const char *name, WFlags f)
+ : QFrame(parent, name, f),
+ range(INIT_MIN_VALUE, INIT_MAX_VALUE, 1, 10, INIT_VALUE),
+ dir(orient)
+{
+ init();
+ if (orient == Horizontal)
+ setFixedHeight(FIX_WIDTH);
+ else
+ setFixedWidth(FIX_WIDTH);
+}
+
+
+KRuler::KRuler(Orientation orient, int widgetWidth,
+ QWidget *parent, const char *name, WFlags f)
+ : QFrame(parent, name, f),
+ range(INIT_MIN_VALUE, INIT_MAX_VALUE, 1, 10, INIT_VALUE),
+ dir(orient)
+{
+ init();
+
+ if (orient == Horizontal)
+ setFixedHeight(widgetWidth);
+ else
+ setFixedWidth(widgetWidth);
+}
+
+
+void KRuler::init()
+{
+ setFrameStyle(WinPanel | Raised);
+
+ tmDist = INIT_TINY_MARK_DISTANCE;
+ lmDist = INIT_LITTLE_MARK_DISTANCE;
+ mmDist = INIT_MIDDLE_MARK_DISTANCE;
+ bmDist = INIT_BIG_MARK_DISTANCE;
+ offset_= INIT_OFFSET;
+ showtm = INIT_SHOW_TINY_MARK;
+ showlm = INIT_SHOW_LITTLE_MARK;
+ showmm = INIT_SHOW_MEDIUM_MARK;
+ showbm = INIT_SHOW_BIG_MARK;
+ showem = INIT_SHOW_END_MARK;
+ ppm = INIT_PIXEL_PER_MARK;
+
+ d = new KRuler::KRulerPrivate;
+ d->showpointer = INIT_SHOW_POINTER;
+ d->showEndL = INIT_SHOW_END_LABEL;
+ d->lengthFix = INIT_LENGTH_FIX;
+ d->endOffset_length = INIT_END_OFFSET;
+}
+
+
+KRuler::~KRuler()
+{
+ delete d;
+}
+
+void
+KRuler::setMinValue(int value)
+{
+ if (range.minValue() != value) {
+ range.setRange( value, range.maxValue() );
+ update(contentsRect());
+ }
+}
+
+void
+KRuler::setMaxValue(int value)
+{
+ if (range.maxValue() != value) {
+ range.setRange( range.minValue(), value );
+ update(contentsRect());
+ }
+}
+
+void
+KRuler::setRange(int min, int max)
+{// debug("set range from %i to %i", min, max);
+ if ((range.minValue() != min) || (range.maxValue() != max)) {
+ range.setRange( min, max );
+ update(contentsRect());
+ }
+}
+
+void
+KRuler::setValue(int value)
+{
+ range.setValue(value);
+ update(contentsRect());
+}
+
+void
+KRuler::setTinyMarkDistance(int dist)
+{
+ if (dist != tmDist) {
+ tmDist = dist;
+ update(contentsRect());
+ }
+}
+
+void
+KRuler::setLittleMarkDistance(int dist)
+{
+ if (dist != lmDist) {
+ lmDist = dist;
+ update(contentsRect());
+ }
+}
+
+void
+KRuler::setMediumMarkDistance(int dist)
+{
+ if (dist != mmDist) {
+ mmDist = dist;
+ update(contentsRect());
+ }
+}
+
+void
+KRuler::setBigMarkDistance(int dist)
+{
+ if (dist != bmDist) {
+ bmDist = dist;
+ update(contentsRect());
+ }
+}
+
+void
+KRuler::setShowTinyMarks(bool show)
+{
+ if (show != showtm) {
+ showtm = show;
+ update(contentsRect());
+ }
+}
+
+bool
+KRuler::showTinyMarks() const
+{
+ return showtm;
+}
+
+void
+KRuler::setShowLittleMarks(bool show)
+{
+ if (show != showlm) {
+ showlm = show;
+ update(contentsRect());
+ }
+}
+
+bool
+KRuler::showLittleMarks() const
+{
+ return showlm;
+}
+
+void
+KRuler::setShowMediumMarks(bool show)
+{
+ if (show != showmm) {
+ showmm = show;
+ update(contentsRect());
+ }
+}
+
+bool
+KRuler::showMediumMarks() const
+{
+ return showmm;
+}
+
+void
+KRuler::setShowBigMarks(bool show)
+{
+ if (show != showbm) {
+ showbm = show;
+ update(contentsRect());
+ }
+}
+
+
+bool
+KRuler::showBigMarks() const
+{
+ return showbm;
+}
+
+void
+KRuler::setShowEndMarks(bool show)
+{
+ if (show != showem) {
+ showem = show;
+ update(contentsRect());
+ }
+}
+
+bool
+KRuler::showEndMarks() const
+{
+ return showem;
+}
+
+void
+KRuler::setShowPointer(bool show)
+{
+ if (show != d->showpointer) {
+ d->showpointer = show;
+ update(contentsRect());
+ }
+}
+
+
+bool
+KRuler::showPointer() const
+{
+ return d->showpointer;
+}
+
+void
+KRuler::setValuePerLittleMark(int)
+{
+ update(contentsRect());
+}
+
+void
+KRuler::setValuePerMediumMark(int)
+{
+ update(contentsRect());
+}
+
+void
+KRuler::setValuePerBigMark(int)
+{
+ update(contentsRect());
+}
+
+void
+KRuler::setShowEndLabel(bool show)
+{
+ if (d->showEndL != show) {
+ d->showEndL = show;
+ update(contentsRect());
+ }
+}
+
+
+bool
+KRuler::showEndLabel() const
+{
+ return d->showEndL;
+}
+
+
+void
+KRuler::setEndLabel(const QString& label)
+{
+ endlabel = label;
+
+ // premeasure the fontwidth and save it
+ if (dir == Vertical) {
+ QFont font = this->font();
+ font.setPointSize(LABEL_SIZE);
+ QFontMetrics fm(font);
+ d->fontWidth = fm.width(endlabel);
+ }
+ update(contentsRect());
+}
+
+QString KRuler::endLabel() const
+{
+ return endlabel;
+}
+
+void
+KRuler::setRulerMetricStyle(KRuler::MetricStyle style)
+{
+ switch (style) {
+ default: /* fall through */
+ case Custom:
+ return;
+ case Pixel:
+ setLittleMarkDistance(1);
+ setMediumMarkDistance(5);
+ setBigMarkDistance(10);
+
+ setShowTinyMarks(false);
+ setShowLittleMarks(true);
+ setShowMediumMarks(true);
+ setShowBigMarks(true);
+ setShowEndMarks(true);
+
+ update(contentsRect());
+ setPixelPerMark(10.0);
+
+ break;
+ case Inch:
+ setTinyMarkDistance(1);
+ setLittleMarkDistance(2);
+ setMediumMarkDistance(4);
+ setBigMarkDistance(8);
+
+ setShowTinyMarks(true);
+ setShowLittleMarks(true);
+ setShowMediumMarks(true);
+ setShowBigMarks(true);
+ setShowEndMarks(true);
+
+ update(contentsRect());
+ setPixelPerMark(9.0);
+
+ break;
+ case Millimetres: /* fall through */
+ case Centimetres: /* fall through */
+ case Metres:
+ setLittleMarkDistance(1);
+ setMediumMarkDistance(5);
+ setBigMarkDistance(10);
+
+ setShowTinyMarks(false);
+ setShowLittleMarks(true);
+ setShowMediumMarks(true);
+ setShowBigMarks(true);
+ setShowEndMarks(true);
+
+ update(contentsRect());
+ setPixelPerMark(3.0);
+ }
+ switch (style) {
+ case Pixel:
+ setEndLabel(QString::fromLatin1("pixel"));
+ break;
+ case Inch:
+ setEndLabel(QString::fromLatin1("inch"));
+ break;
+ case Millimetres:
+ setEndLabel(QString::fromLatin1("mm"));
+ break;
+ case Centimetres:
+ setEndLabel(QString::fromLatin1("cm"));
+ break;
+ case Metres:
+ setEndLabel(QString::fromLatin1("m"));
+ default: /* never reached, see above switch */
+ /* empty command */;
+ }
+ // if the style changes one of the values,
+ // update would have been called inside the methods
+ // -> no update() call needed here !
+}
+
+void
+KRuler::setPixelPerMark(double rate)
+{ // never compare floats against each other :)
+ ppm = rate;
+ update(contentsRect());
+}
+
+
+void
+KRuler::setLength(int length)
+{
+ int tmp;
+ if (d->lengthFix) {
+ tmp = length;
+ }
+ else {
+ tmp = this->width() - length;
+ }
+ if (tmp != d->endOffset_length) {
+ d->endOffset_length = tmp;
+ update(contentsRect());
+ }
+}
+
+int
+KRuler::length() const
+{
+ if (d->lengthFix) {
+ return d->endOffset_length;
+ }
+ return (this->width() - d->endOffset_length);
+}
+
+
+void
+KRuler::setLengthFixed(bool fix)
+{
+ d->lengthFix = fix;
+}
+
+bool
+KRuler::lengthFixed() const
+{
+ return d->lengthFix;
+}
+
+void
+KRuler::setOffset(int _offset)
+{// debug("set offset %i", _offset);
+ if (offset_ != _offset) {
+ offset_ = _offset;
+ update(contentsRect());
+ }
+}
+
+int
+KRuler::endOffset() const
+{
+ if (d->lengthFix) {
+ return (this->width() - d->endOffset_length);
+ }
+ return d->endOffset_length;
+}
+
+
+void
+KRuler::slideUp(int count)
+{
+ if (count) {
+ offset_ += count;
+ update(contentsRect());
+ }
+}
+
+void
+KRuler::slideDown(int count)
+{
+ if (count) {
+ offset_ -= count;
+ update(contentsRect());
+ }
+}
+
+
+void
+KRuler::slotNewValue(int _value)
+{
+ int oldvalue = range.value();
+ if (oldvalue == _value) {
+ return;
+ }
+ // setValue(_value);
+ range.setValue(_value);
+ if (range.value() == oldvalue) {
+ return;
+ }
+ // get the rectangular of the old and the new ruler pointer
+ // and repaint only him
+ if (dir == Horizontal) {
+ QRect oldrec(-5+oldvalue,10, 11,6);
+ QRect newrec(-5+_value,10, 11,6);
+ repaint( oldrec.unite(newrec) );
+ }
+ else {
+ QRect oldrec(10,-5+oldvalue, 6,11);
+ QRect newrec(10,-5+_value, 6,11);
+ repaint( oldrec.unite(newrec) );
+ }
+}
+
+void
+KRuler::slotNewOffset(int _offset)
+{
+ if (offset_ != _offset) {
+ //setOffset(_offset);
+ offset_ = _offset;
+ repaint(contentsRect());
+ }
+}
+
+
+void
+KRuler::slotEndOffset(int offset)
+{
+ int tmp;
+ if (d->lengthFix) {
+ tmp = this->width() - offset;
+ }
+ else {
+ tmp = offset;
+ }
+ if (d->endOffset_length != tmp) {
+ d->endOffset_length = tmp;
+ repaint(contentsRect());
+ }
+}
+
+void
+KRuler::drawContents(QPainter *p)
+{
+ // debug ("KRuler::drawContents, %s",(horizontal==dir)?"horizontal":"vertical");
+
+#ifdef PROFILING
+ QTime time;
+ time.start();
+ for (int profile=0; profile<10; profile++) {
+#endif
+
+ int value = range.value(),
+ minval = range.minValue(),
+ maxval;
+ if (dir == Horizontal) {
+ maxval = range.maxValue()
+ + offset_
+ - (d->lengthFix?(height()-d->endOffset_length):d->endOffset_length);
+ }
+ else
+ {
+ maxval = range.maxValue()
+ + offset_
+ - (d->lengthFix?(width()-d->endOffset_length):d->endOffset_length);
+ }
+ //ioffsetval = value-offset;
+ // pixelpm = (int)ppm;
+ // left = clip.left(),
+ // right = clip.right();
+ double f, fend,
+ offsetmin=(double)(minval-offset_),
+ offsetmax=(double)(maxval-offset_),
+ fontOffset = (((double)minval)>offsetmin)?(double)minval:offsetmin;
+
+ // draw labels
+ QFont font = p->font();
+ font.setPointSize(LABEL_SIZE);
+ p->setFont( font );
+ // draw littlemarklabel
+
+ // draw mediummarklabel
+
+ // draw bigmarklabel
+
+ // draw endlabel
+ if (d->showEndL) {
+ if (dir == Horizontal) {
+ p->translate( fontOffset, 0 );
+ p->drawText( END_LABEL_X, END_LABEL_Y, endlabel );
+ }
+ else { // rotate text +pi/2 and move down a bit
+ //QFontMetrics fm(font);
+#ifdef KRULER_ROTATE_TEST
+ p->rotate( -90.0 + rotate );
+ p->translate( -8.0 - fontOffset - d->fontWidth + xtrans,
+ ytrans );
+#else
+ p->rotate( -90.0 );
+ p->translate( -8.0 - fontOffset - d->fontWidth, 0.0 );
+#endif
+ p->drawText( END_LABEL_X, END_LABEL_Y, endlabel );
+ }
+ p->resetXForm();
+ }
+
+ // draw the tiny marks
+ if (showtm) {
+ fend = ppm*tmDist;
+ for ( f=offsetmin; f<offsetmax; f+=fend ) {
+ if (dir == Horizontal) {
+ p->drawLine((int)f, BASE_MARK_X1, (int)f, BASE_MARK_X2);
+ }
+ else {
+ p->drawLine(BASE_MARK_X1, (int)f, BASE_MARK_X2, (int)f);
+ }
+ }
+ }
+ if (showlm) {
+ // draw the little marks
+ fend = ppm*lmDist;
+ for ( f=offsetmin; f<offsetmax; f+=fend ) {
+ if (dir == Horizontal) {
+ p->drawLine((int)f, LITTLE_MARK_X1, (int)f, LITTLE_MARK_X2);
+ }
+ else {
+ p->drawLine(LITTLE_MARK_X1, (int)f, LITTLE_MARK_X2, (int)f);
+ }
+ }
+ }
+ if (showmm) {
+ // draw medium marks
+ fend = ppm*mmDist;
+ for ( f=offsetmin; f<offsetmax; f+=fend ) {
+ if (dir == Horizontal) {
+ p->drawLine((int)f, MIDDLE_MARK_X1, (int)f, MIDDLE_MARK_X2);
+ }
+ else {
+ p->drawLine(MIDDLE_MARK_X1, (int)f, MIDDLE_MARK_X2, (int)f);
+ }
+ }
+ }
+ if (showbm) {
+ // draw big marks
+ fend = ppm*bmDist;
+ for ( f=offsetmin; f<offsetmax; f+=fend ) {
+ if (dir == Horizontal) {
+ p->drawLine((int)f, BIG_MARK_X1, (int)f, BIG_MARK_X2);
+ }
+ else {
+ p->drawLine(BIG_MARK_X1, (int)f, BIG_MARK_X2, (int)f);
+ }
+ }
+ }
+ if (showem) {
+ // draw end marks
+ if (dir == Horizontal) {
+ p->drawLine(minval-offset_, END_MARK_X1, minval-offset_, END_MARK_X2);
+ p->drawLine(maxval-offset_, END_MARK_X1, maxval-offset_, END_MARK_X2);
+ }
+ else {
+ p->drawLine(END_MARK_X1, minval-offset_, END_MARK_X2, minval-offset_);
+ p->drawLine(END_MARK_X1, maxval-offset_, END_MARK_X2, maxval-offset_);
+ }
+ }
+
+ // draw pointer
+ if (d->showpointer) {
+ QPointArray pa(4);
+ if (dir == Horizontal) {
+ pa.setPoints(3, value-5, 10, value+5, 10, value/*+0*/,15);
+ }
+ else {
+ pa.setPoints(3, 10, value-5, 10, value+5, 15, value/*+0*/);
+ }
+ p->setBrush( p->backgroundColor() );
+ p->drawPolygon( pa );
+ }
+
+#ifdef PROFILING
+ }
+ int elapsed = time.elapsed();
+ debug("paint time %i",elapsed);
+#endif
+
+}
+
+void KRuler::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "kruler.moc"
diff --git a/kdeui/kruler.h b/kdeui/kruler.h
new file mode 100644
index 000000000..8d1ae3cc7
--- /dev/null
+++ b/kdeui/kruler.h
@@ -0,0 +1,521 @@
+/* -*- c++ -*- */
+/* This file is part of the KDE libraries
+ Copyright (C) 1998 Jörg Habenicht (j.habenicht@europemail.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KRULER_H
+#define KRULER_H
+
+#include <qframe.h>
+#include <qrangecontrol.h>
+#include <kdelibs_export.h>
+
+/**
+ * A ruler widget.
+ *
+ * The vertical ruler looks similar to this:
+ *
+ *\code
+ * meters inches
+ *
+ * ------ <--- end mark ---> ------
+ * -- -
+ * -- <---little mark---> --
+ * -- -
+ * -- ---
+ * --- <---medium mark -
+ * -- --
+ * -- tiny mark----> -
+ * -- ----
+ * -- -
+ * ---- <-----big mark --
+ * -- -
+ * |>-- <--ruler pointer--> |>--
+ *
+ * \endcode
+ *
+ * There are tiny marks, little marks, medium marks, and big marks along the
+ * ruler.
+ *
+ * To receive mouse clicks or mouse moves,
+ * the class has to be overloaded.
+ *
+ * For performance reasons, the public methods don't call QWidget::repaint().
+ * (Slots do, see documentation below.)
+ * All the changed settings will be painted once after leaving
+ * to the main event loop.
+ * For performance painting the slot methods should be used,
+ * they do a fast QWidget::repaint() call after changing the values.
+ * For setting multiple values like minValue(), maxValue(), offset() etc.
+ * using the public methods is recommended
+ * so the widget will be painted only once when entering the main event loop.
+ *
+ * @short A ruler widget.
+ * @author Jörg Habenicht
+ */
+class KDEUI_EXPORT KRuler : public QFrame
+{
+ Q_OBJECT
+ Q_PROPERTY( int minValue READ minValue WRITE setMinValue )
+ Q_PROPERTY( int maxValue READ maxValue WRITE setMaxValue )
+ Q_PROPERTY( int value READ value WRITE setValue )
+ Q_PROPERTY( bool showTinyMarks READ showTinyMarks WRITE setShowTinyMarks )
+ Q_PROPERTY( bool showLittleMarks READ showLittleMarks WRITE setShowLittleMarks )
+ Q_PROPERTY( bool showMediumMarks READ showMediumMarks WRITE setShowMediumMarks )
+ Q_PROPERTY( bool showBigMarks READ showBigMarks WRITE setShowBigMarks )
+ Q_PROPERTY( bool showPointer READ showPointer WRITE setShowPointer )
+ Q_PROPERTY( bool showEndLabel READ showEndLabel WRITE setShowEndLabel )
+ Q_PROPERTY( int tinyMarkDistance READ tinyMarkDistance WRITE setTinyMarkDistance )
+ Q_PROPERTY( int littleMarkDistance READ littleMarkDistance WRITE setLittleMarkDistance )
+ Q_PROPERTY( int mediumMarkDistance READ mediumMarkDistance WRITE setBigMarkDistance )
+ Q_PROPERTY( int bigMarkDistance READ bigMarkDistance WRITE setBigMarkDistance )
+ Q_PROPERTY( double pixelPerMark READ pixelPerMark WRITE setPixelPerMark )
+ Q_PROPERTY( bool lengthFixed READ lengthFixed WRITE setLengthFixed )
+
+public:
+
+/*
+#define KRULER_ROTATE_TEST KRULER_ROTATE_TEST
+#undef KRULER_ROTATE_TEST
+#ifdef KRULER_ROTATE_TEST
+ double xtrans, ytrans, rotate;
+# warning tmporaer variablen eingeschaltet
+#endif
+*/
+
+ /**
+ * The types of units used.
+ **/
+ enum MetricStyle { Custom=0, Pixel, Inch, Millimetres, Centimetres, Metres };
+
+ /**
+ * The style (or look) of the ruler.
+ **/
+ // enum PaintStyle { Flat, Raised, Sunken };
+
+ /**
+ * Constructs a horizontal ruler.
+ */
+ KRuler(QWidget *parent=0, const char *name=0);
+ /**
+ * Constructs a ruler with orientation @p orient.
+ *
+ * @p parent, @p name and @p f are passed to QFrame.
+ * The default look is a raised widget
+ * but may be changed with the inherited QFrame methods.
+ *
+ * @param orient Orientation of the ruler.
+ * @param parent Will be handed over to QFrame.
+ * @param name Will be handed over to QFrame.
+ * @param f Will be handed over to QFrame.
+ *
+ **/
+ KRuler(Orientation orient, QWidget *parent=0, const char *name=0,
+ WFlags f=0);
+
+ /**
+ * Constructs a ruler with orientation @p orient and initial width @p widgetWidth.
+ *
+ * The width sets the fixed width of the widget. This is useful if you
+ * want to draw the ruler bigger or smaller than the default size.
+ * Note: The size of the marks doesn't change.
+ * @p parent, @p name and @p f are passed to QFrame.
+ *
+ * @param orient Orientation of the ruler.
+ * @param widgetWidth Fixed width of the widget.
+ * @param parent Will be handed over to QFrame.
+ * @param name Will be handed over to QFrame.
+ * @param f Will be handed over to QFrame.
+ *
+ */
+ KRuler(Orientation orient, int widgetWidth, QWidget *parent=0,
+ const char *name=0, WFlags f=0);
+
+ /**
+ * Destructor.
+ */
+ ~KRuler();
+
+ /**
+ * Sets the minimal value of the ruler pointer (default is 0).
+ *
+ * This method calls update() so that the widget is painted after leaving
+ * to the main event loop.
+ *
+ **/
+ void setMinValue(int);
+
+ /**
+ * Returns the minimal value of the ruler pointer.
+ **/
+ inline int minValue() const;
+
+ /**
+ * Sets the maximum value of the ruler pointer (default is 100).
+ *
+ * This method calls update() so that the widget is painted after leaving
+ * to the main event loop.
+ */
+ void setMaxValue(int);
+
+ /**
+ * Returns the maximal value of the ruler pointer.
+ */
+ inline int maxValue() const;
+
+ /**
+ * Sets minimum and maximum values of the ruler pointer.
+ *
+ * This method calls update() so that the widget is painted after leaving
+ * to the main event loop.
+ */
+ void setRange(int min, int max);
+
+ /**
+ * Sets the value of the ruler pointer.
+ *
+ * The value is indicated by painting the ruler pointer at the
+ * corresponding position.
+ * This method calls update() so that the widget is painted after leaving
+ * to the main event loop.
+ */
+ void setValue(int);
+ inline int value() const;
+
+ /**
+ * Sets the distance between tiny marks.
+ *
+ * This is mostly used in the English system (inches) with distance of 1.
+ */
+ void setTinyMarkDistance(int);
+ /**
+ * Returns the distance between tiny marks.
+ **/
+ inline int tinyMarkDistance() const;
+
+ /**
+ * Sets the distance between little marks.
+ *
+ * The default value is 1 in the metric system and 2 in the English (inches) system.
+ */
+ void setLittleMarkDistance(int);
+
+ /**
+ * Returns the distance between little marks.
+ */
+ inline int littleMarkDistance() const;
+
+ /**
+ * Sets the distance between medium marks.
+ *
+ * For English (inches) styles it defaults to twice the little mark distance.
+ * For metric styles it defaults to five times the little mark distance.
+ **/
+ void setMediumMarkDistance(int);
+ inline int mediumMarkDistance() const;
+
+ /**
+ * Sets distance between big marks.
+ *
+ * For English (inches) or metric styles it is twice the medium mark distance.
+ **/
+ void setBigMarkDistance(int);
+ /**
+ * Returns the distance between big marks.
+ **/
+ inline int bigMarkDistance() const;
+
+ /**
+ * Shows/hides tiny marks.
+ **/
+ void setShowTinyMarks(bool);
+ bool showTinyMarks() const;
+ /**
+ * Shows/hides little marks.
+ **/
+ void setShowLittleMarks(bool);
+ bool showLittleMarks() const;
+ /**
+ * Shows/hides medium marks.
+ **/
+ void setShowMediumMarks(bool);
+ bool showMediumMarks() const;
+ /**
+ * Shows/hides big marks.
+ **/
+ void setShowBigMarks(bool);
+ bool showBigMarks() const;
+ /**
+ * Shows/hides end marks.
+ **/
+ void setShowEndMarks(bool);
+ bool showEndMarks() const;
+ /**
+ * Shows/hides the pointer.
+ */
+ void setShowPointer(bool);
+ bool showPointer() const;
+
+ //#### KDE4: The next 3 need to go.
+ /**
+ * @deprecated
+ * This method has no effect other than an update. Do not use.
+ **/
+ void setValuePerLittleMark(int) KDE_DEPRECATED;
+
+ /**
+ * @deprecated
+ * This method has no effect other than an update. Do not use.
+ **/
+ void setValuePerMediumMark(int) KDE_DEPRECATED;
+
+ /**
+ * @deprecated
+ * This method has no effect other than an update. Do not use.
+ */
+ void setValuePerBigMark(int) KDE_DEPRECATED;
+
+ /**
+ * Show/hide number values of the little marks.
+ *
+ * Default is @p false.
+ **/
+ // void setShowLittleMarkLabel(bool);
+
+ /**
+ * Show/hide number values of the medium marks.
+ *
+ * Default is @p false.
+ **/
+ // void setShowMediumMarkLabel(bool);
+
+ /**
+ * Show/hide number values of the big marks.
+ *
+ * Default is @p false.
+ **/
+ // void showBigMarkLabel(bool);
+
+ /**
+ * Show/hide number values of the end marks.
+ *
+ * Default is @p false.
+ **/
+ void setShowEndLabel(bool);
+ bool showEndLabel() const;
+
+ /**
+ * Sets the label this is drawn at the beginning of the visible part
+ * of the ruler to @p label
+ **/
+ void setEndLabel(const QString&);
+ QString endLabel() const;
+
+ /**
+ * Sets up the necessary tasks for the provided styles.
+ *
+ * A convenience method.
+ **/
+ void setRulerMetricStyle(KRuler::MetricStyle);
+
+ /**
+ * Sets the number of pixels between two base marks.
+ *
+ * Calling this method stretches or shrinks your ruler.
+ *
+ * For pixel display ( MetricStyle) the value is 10.0 marks
+ * per pixel ;-)
+ * For English (inches) it is 9.0, and for centimetres ~2.835 -> 3.0 .
+ * If you want to magnify your part of display, you have to
+ * adjust the mark distance @p here.
+ * Notice: The double type is only supported to give the possibility
+ * of having some double values.
+ * It should be used with care. Using values below 10.0
+ * shows visible jumps of markpositions (e.g. 2.345).
+ * Using whole numbers is highly recommended.
+ * To use @p int values use setPixelPerMark((int)your_int_value);
+ * default: 1 mark per 10 pixels
+ */
+ void setPixelPerMark(double rate);
+
+ /**
+ * Returns the number of pixels between two base marks.
+ **/
+ inline double pixelPerMark() const;
+
+ /**
+ * Sets the length of the ruler, i.e. the difference between
+ * the begin mark and the end mark of the ruler.
+ *
+ * Same as (width() - offset())
+ *
+ * when the length is not locked, it gets adjusted with the
+ * length of the widget.
+ */
+ void setLength(int);
+ int length() const;
+
+ /**
+ * Locks the length of the ruler, i.e. the difference between
+ * the two end marks doesn't change when the widget is resized.
+ *
+ * @param fix fixes the length, if true
+ */
+ void setLengthFixed(bool fix);
+ bool lengthFixed() const;
+
+ /**
+ * Sets the number of pixels by which the ruler may slide up or left.
+ * The number of pixels moved is realive to the previous position.
+ * The Method makes sense for updating a ruler, which is working with
+ * a scrollbar.
+ *
+ * This doesn't affect the position of the ruler pointer.
+ * Only the visible part of the ruler is moved.
+ *
+ * @param count Number of pixel moving up or left relative to the previous position
+ **/
+ void slideUp(int count = 1);
+
+ /**
+ * Sets the number of pixels by which the ruler may slide down or right.
+ * The number of pixels moved is realive to the previous position.
+ * The Method makes sense for updating a ruler, which is working with
+ * a scrollbar.
+ *
+ * This doesn't affect the position of the ruler pointer.
+ * Only the visible part of the ruler is moved.
+ *
+ * @param count Number of pixel moving up or left relative to the previous position
+ **/
+ void slideDown(int count = 1);
+
+ /**
+ * Sets the ruler slide offset.
+ *
+ * This is like slideup() or slidedown() with an absolute offset
+ * from the start of the ruler.
+ *
+ * @param offset Number of pixel to move the ruler up or left from the beginning
+ **/
+ void setOffset(int offset);
+
+ /**
+ * Returns the current ruler offset.
+ **/
+ inline int offset() const;
+
+ int endOffset() const;
+
+public slots:
+
+ /**
+ * Sets the pointer to a new position.
+ *
+ * The offset is NOT updated.
+ * QWidget::repaint() is called afterwards.
+ **/
+ void slotNewValue(int);
+
+ /**
+ * Sets the ruler marks to a new position.
+ *
+ * The pointer is NOT updated.
+ * QWidget::repaint() is called afterwards.
+ **/
+ void slotNewOffset(int);
+
+ void slotEndOffset(int);
+
+protected:
+ virtual void drawContents(QPainter *);
+
+private:
+ void init();
+
+ QRangeControl range;
+ Orientation dir;
+ int tmDist;
+ int lmDist;
+ int mmDist;
+ int bmDist;
+ int offset_;
+ bool showtm; /* show tiny, little, medium, big, endmarks */
+ bool showlm;
+ bool showmm;
+ bool showbm;
+ bool showem;
+
+ // #### KDE4 : All value* and show* below should be removed, unused
+
+ int valuelm; /* value per little, medium, big mark */
+ int valuemm;
+ int valuebm;
+ bool showValuelm;
+ bool showValuemm;
+ bool showValuebm;
+
+ double ppm; /* pixel per mark */
+
+ QString endlabel;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KRulerPrivate;
+ KRulerPrivate *d;
+};
+
+
+int
+KRuler::minValue() const
+{ return range.minValue(); }
+
+int
+KRuler::maxValue() const
+{ return range.maxValue(); }
+
+int
+KRuler::value() const
+{ return range.value(); }
+
+int
+KRuler::tinyMarkDistance() const
+{ return tmDist; }
+
+int
+KRuler::littleMarkDistance() const
+{ return lmDist; }
+
+int
+KRuler::mediumMarkDistance() const
+{ return mmDist; }
+
+int
+KRuler::bigMarkDistance() const
+{ return bmDist; }
+
+double
+KRuler::pixelPerMark() const
+{ return ppm; }
+
+int
+KRuler::offset() const
+{ return offset_; }
+
+#endif
diff --git a/kdeui/ksconfig.cpp b/kdeui/ksconfig.cpp
new file mode 100644
index 000000000..f17bd0dcc
--- /dev/null
+++ b/kdeui/ksconfig.cpp
@@ -0,0 +1,1028 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 David Sweet <dsweet@kde.org>
+ Copyright (C) 2000-2001 Wolfram Diestel <wolfram@steloj.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config.h>
+
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qtimer.h>
+
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kdialog.h>
+#include <kfiledialog.h>
+#include <kglobal.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <kpushbutton.h>
+#include <kstdguiitem.h>
+
+#include "ksconfig.h"
+
+class KSpellConfigPrivate
+{
+public:
+ QStringList replacelist;
+};
+
+
+KSpellConfig::KSpellConfig (const KSpellConfig &_ksc)
+ : QWidget(0, 0), nodialog(true)
+ , kc(0)
+ , cb1(0)
+ , cb2(0)
+ , dictlist(0)
+ , dictcombo(0)
+ , encodingcombo(0)
+ , clientcombo(0)
+{
+ d = new KSpellConfigPrivate;
+ setReplaceAllList( _ksc.replaceAllList() );
+ setNoRootAffix( _ksc.noRootAffix() );
+ setRunTogether( _ksc.runTogether() );
+ setDictionary( _ksc.dictionary() );
+ setDictFromList( _ksc.dictFromList() );
+ // setPersonalDict (_ksc.personalDict());
+ setIgnoreList( _ksc.ignoreList() );
+ setEncoding( _ksc.encoding() );
+ setClient( _ksc.client() );
+}
+
+
+KSpellConfig::KSpellConfig( QWidget *parent, const char *name,
+ KSpellConfig *_ksc, bool addHelpButton )
+ : QWidget (parent, name), nodialog(false)
+ , kc(0)
+ , cb1(0)
+ , cb2(0)
+ , dictlist(0)
+ , dictcombo(0)
+ , encodingcombo(0)
+ , clientcombo(0)
+{
+ d = new KSpellConfigPrivate;
+ kc = KGlobal::config();
+
+ if( !_ksc )
+ {
+ readGlobalSettings();
+ }
+ else
+ {
+ setNoRootAffix( _ksc->noRootAffix() );
+ setRunTogether( _ksc->runTogether() );
+ setDictionary( _ksc->dictionary() );
+ setDictFromList( _ksc->dictFromList() );
+ //setPersonalDict (_ksc->personalDict());
+ setIgnoreList( _ksc->ignoreList() );
+ setEncoding( _ksc->encoding() );
+ setClient( _ksc->client() );
+ }
+
+ QGridLayout *glay = new QGridLayout( this, 6, 3, 0, KDialog::spacingHint() );
+ cb1 = new QCheckBox( i18n("Create &root/affix combinations"
+ " not in dictionary"), this, "NoRootAffix" );
+ connect( cb1, SIGNAL(toggled(bool)), SLOT(sNoAff(bool)) );
+ glay->addMultiCellWidget( cb1, 0, 0, 0, 2 );
+
+ cb2 = new QCheckBox( i18n("Consider run-together &words"
+ " as spelling errors"), this, "RunTogether" );
+ connect( cb2, SIGNAL(toggled(bool)), SLOT(sRunTogether(bool)) );
+ glay->addMultiCellWidget( cb2, 1, 1, 0, 2 );
+
+ dictcombo = new QComboBox( this, "DictFromList" );
+ dictcombo->setInsertionPolicy( QComboBox::NoInsertion );
+ connect( dictcombo, SIGNAL (activated(int)),
+ this, SLOT (sSetDictionary(int)) );
+ glay->addMultiCellWidget( dictcombo, 2, 2, 1, 2 );
+
+ dictlist = new QLabel( dictcombo, i18n("&Dictionary:"), this );
+ glay->addWidget( dictlist, 2 ,0 );
+
+ encodingcombo = new QComboBox( this, "Encoding" );
+ encodingcombo->insertItem( "US-ASCII" );
+ encodingcombo->insertItem( "ISO 8859-1" );
+ encodingcombo->insertItem( "ISO 8859-2" );
+ encodingcombo->insertItem( "ISO 8859-3" );
+ encodingcombo->insertItem( "ISO 8859-4" );
+ encodingcombo->insertItem( "ISO 8859-5" );
+ encodingcombo->insertItem( "ISO 8859-7" );
+ encodingcombo->insertItem( "ISO 8859-8" );
+ encodingcombo->insertItem( "ISO 8859-9" );
+ encodingcombo->insertItem( "ISO 8859-13" );
+ encodingcombo->insertItem( "ISO 8859-15" );
+ encodingcombo->insertItem( "UTF-8" );
+ encodingcombo->insertItem( "KOI8-R" );
+ encodingcombo->insertItem( "KOI8-U" );
+ encodingcombo->insertItem( "CP1251" );
+ encodingcombo->insertItem( "CP1255" );
+
+ connect( encodingcombo, SIGNAL(activated(int)), this,
+ SLOT(sChangeEncoding(int)) );
+ glay->addMultiCellWidget( encodingcombo, 3, 3, 1, 2 );
+
+ QLabel *tmpQLabel = new QLabel( encodingcombo, i18n("&Encoding:"), this);
+ glay->addWidget( tmpQLabel, 3, 0 );
+
+
+ clientcombo = new QComboBox( this, "Client" );
+ clientcombo->insertItem( i18n("International Ispell") );
+ clientcombo->insertItem( i18n("Aspell") );
+ clientcombo->insertItem( i18n("Hspell") );
+ clientcombo->insertItem( i18n("Zemberek") );
+ connect( clientcombo, SIGNAL (activated(int)), this,
+ SLOT (sChangeClient(int)) );
+ glay->addMultiCellWidget( clientcombo, 4, 4, 1, 2 );
+
+ tmpQLabel = new QLabel( clientcombo, i18n("&Client:"), this );
+ glay->addWidget( tmpQLabel, 4, 0 );
+
+ if( addHelpButton )
+ {
+ QPushButton *pushButton = new KPushButton( KStdGuiItem::help(), this );
+ connect( pushButton, SIGNAL(clicked()), this, SLOT(sHelp()) );
+ glay->addWidget(pushButton, 5, 2);
+ }
+
+ fillInDialog();
+}
+
+KSpellConfig::~KSpellConfig()
+{
+ delete d;
+}
+
+
+bool
+KSpellConfig::dictFromList() const
+{
+ return dictfromlist;
+}
+
+bool
+KSpellConfig::readGlobalSettings()
+{
+ KConfigGroupSaver cs( kc,"KSpell" );
+
+ setNoRootAffix ( kc->readNumEntry("KSpell_NoRootAffix", 0) );
+ setRunTogether ( kc->readNumEntry("KSpell_RunTogether", 0) );
+ setDictionary ( kc->readEntry("KSpell_Dictionary") );
+ setDictFromList ( kc->readNumEntry("KSpell_DictFromList", false) );
+ setEncoding ( kc->readNumEntry ("KSpell_Encoding", KS_E_ASCII) );
+ setClient ( kc->readNumEntry ("KSpell_Client", KS_CLIENT_ISPELL) );
+
+ return true;
+}
+
+bool
+KSpellConfig::writeGlobalSettings ()
+{
+ KConfigGroupSaver cs( kc,"KSpell" );
+
+ kc->writeEntry ("KSpell_NoRootAffix",(int) noRootAffix(), true, true);
+ kc->writeEntry ("KSpell_RunTogether", (int) runTogether(), true, true);
+ kc->writeEntry ("KSpell_Dictionary", dictionary(), true, true);
+ kc->writeEntry ("KSpell_DictFromList",(int) dictFromList(), true, true);
+ kc->writeEntry ("KSpell_Encoding", (int) encoding(),
+ true, true);
+ kc->writeEntry ("KSpell_Client", client(),
+ true, true);
+ kc->sync();
+
+ return true;
+}
+
+void
+KSpellConfig::sChangeEncoding( int i )
+{
+ kdDebug(750) << "KSpellConfig::sChangeEncoding(" << i << ")" << endl;
+ setEncoding( i );
+ emit configChanged();
+}
+
+void
+KSpellConfig::sChangeClient( int i )
+{
+ setClient( i );
+
+ // read in new dict list
+ if ( dictcombo ) {
+ if ( iclient == KS_CLIENT_ISPELL )
+ getAvailDictsIspell();
+ else if ( iclient == KS_CLIENT_HSPELL )
+ {
+ langfnames.clear();
+ dictcombo->clear();
+ dictcombo->insertItem( i18n("Hebrew") );
+ sChangeEncoding( KS_E_CP1255 );
+ } else if ( iclient == KS_CLIENT_ZEMBEREK ) {
+ langfnames.clear();
+ dictcombo->clear();
+ dictcombo->insertItem( i18n("Turkish") );
+ sChangeEncoding( KS_E_UTF8 );
+ }
+ else
+ getAvailDictsAspell();
+ }
+ emit configChanged();
+}
+
+// KDE 4: Make it const QString & fname (only fname)
+bool
+KSpellConfig::interpret( QString &fname, QString &lname,
+ QString &hname )
+
+{
+
+ kdDebug(750) << "KSpellConfig::interpret [" << fname << "]" << endl;
+
+ QString dname( fname );
+
+ if( dname.endsWith( "+" ) )
+ dname.remove( dname.length()-1, 1 );
+
+ if( dname.endsWith("sml") || dname.endsWith("med") || dname.endsWith("lrg") ||
+ dname.endsWith("xlg"))
+ dname.remove(dname.length()-3,3);
+
+ QString extension;
+
+ int i = dname.find('-');
+ if ( i != -1 )
+ {
+ extension = dname.mid(i+1);
+ dname.truncate(i);
+ }
+
+ // Aspell uses 2 alpha language codes or 2 alpha language + 2 alpha country,
+ // but since aspell 0.6 also 3-character ISO-codes can be used
+ if ( (dname.length() == 2) || (dname.length() == 3) ) {
+ lname = dname;
+ hname = KGlobal::locale()->twoAlphaToLanguageName( lname );
+ }
+ else if ( (dname.length() == 5) && (dname[2] == '_') ) {
+ lname = dname.left(2);
+ hname = KGlobal::locale()->twoAlphaToLanguageName(lname);
+ QString country = KGlobal::locale()->twoAlphaToCountryName( dname.right(2) );
+ if ( extension.isEmpty() )
+ extension = country;
+ else
+ extension = country + " - " + extension;
+ }
+ //These are mostly the ispell-langpack defaults
+ else if ( dname=="english" || dname=="american" ||
+ dname=="british" || dname=="canadian" ) {
+ lname="en"; hname=i18n("English");
+ }
+ else if ( dname == "espa~nol" || dname == "espanol" ) {
+ lname="es"; hname=i18n("Spanish");
+ }
+ else if (dname=="dansk") {
+ lname="da"; hname=i18n("Danish");
+ }
+ else if (dname=="deutsch") {
+ lname="de"; hname=i18n("German");
+ }
+ else if (dname=="german") {
+ lname="de"; hname=i18n("German (new spelling)");
+ }
+ else if (dname=="portuguesb" || dname=="br") {
+ lname="br"; hname=i18n("Brazilian Portuguese");
+ }
+ else if (dname=="portugues") {
+ lname="pt"; hname=i18n("Portuguese");
+ }
+ else if (dname=="esperanto") {
+ lname="eo"; hname=i18n("Esperanto");
+ }
+ else if (dname=="norsk") {
+ lname="no"; hname=i18n("Norwegian");
+ }
+ else if (dname=="polish") {
+ lname="pl"; hname=i18n("Polish"); sChangeEncoding(KS_E_LATIN2);
+ }
+ else if (dname=="russian") {
+ lname="ru"; hname=i18n("Russian");
+ }
+ else if (dname=="slovensko") {
+ lname="si"; hname=i18n("Slovenian"); sChangeEncoding(KS_E_LATIN2);
+ }
+ else if (dname=="slovak"){
+ lname="sk"; hname=i18n("Slovak"); sChangeEncoding(KS_E_LATIN2);
+ }
+ else if (dname=="czech") {
+ lname="cs"; hname=i18n("Czech"); sChangeEncoding(KS_E_LATIN2);
+ }
+ else if (dname=="svenska") {
+ lname="sv"; hname=i18n("Swedish");
+ }
+ else if (dname=="swiss") {
+ lname="de"; hname=i18n("Swiss German");
+ }
+ else if (dname=="ukrainian") {
+ lname="uk"; hname=i18n("Ukrainian");
+ }
+ else if (dname=="lietuviu" || dname=="lithuanian") {
+ lname="lt"; hname=i18n("Lithuanian");
+ }
+ else if (dname=="francais" || dname=="french") {
+ lname="fr"; hname=i18n("French");
+ }
+ else if (dname=="belarusian") { // waiting for post 2.2 to not dissapoint translators
+ lname="be"; hname=i18n("Belarusian");
+ }
+ else if( dname == "magyar" ) {
+ lname="hu"; hname=i18n("Hungarian");
+ sChangeEncoding(KS_E_LATIN2);
+ }
+ else {
+ lname=""; hname=i18n("Unknown ispell dictionary", "Unknown");
+ }
+ if (!extension.isEmpty())
+ {
+ hname = hname + " (" + extension + ")";
+ }
+
+ //We have explicitly chosen English as the default here.
+ if ( ( KGlobal::locale()->language() == QString::fromLatin1("C") &&
+ lname==QString::fromLatin1("en") ) ||
+ KGlobal::locale()->language() == lname )
+ return true;
+
+ return false;
+}
+
+void
+KSpellConfig::fillInDialog ()
+{
+ if ( nodialog )
+ return;
+
+ kdDebug(750) << "KSpellConfig::fillinDialog" << endl;
+
+ cb1->setChecked( noRootAffix() );
+ cb2->setChecked( runTogether() );
+ encodingcombo->setCurrentItem( encoding() );
+ clientcombo->setCurrentItem( client() );
+
+ // get list of available dictionaries
+ if ( iclient == KS_CLIENT_ISPELL )
+ getAvailDictsIspell();
+ else if ( iclient == KS_CLIENT_HSPELL )
+ {
+ langfnames.clear();
+ dictcombo->clear();
+ langfnames.append(""); // Default
+ dictcombo->insertItem( i18n("Hebrew") );
+ } else if ( iclient == KS_CLIENT_ZEMBEREK ) {
+ langfnames.clear();
+ dictcombo->clear();
+ langfnames.append("");
+ dictcombo->insertItem( i18n("Turkish") );
+ }
+ else
+ getAvailDictsAspell();
+
+ // select the used dictionary in the list
+ int whichelement=-1;
+
+ if ( dictFromList() )
+ whichelement = langfnames.findIndex(dictionary());
+
+ dictcombo->setMinimumWidth (dictcombo->sizeHint().width());
+
+ if (dictionary().isEmpty() || whichelement!=-1)
+ {
+ setDictFromList (true);
+ if (whichelement!=-1)
+ dictcombo->setCurrentItem(whichelement);
+ }
+ else
+ // Current dictionary vanished, present the user with a default if possible.
+ if ( !langfnames.empty() )
+ {
+ setDictFromList( true );
+ dictcombo->setCurrentItem(0);
+ }
+ else
+ setDictFromList( false );
+
+ sDictionary( dictFromList() );
+ sPathDictionary( !dictFromList() );
+
+}
+
+
+void KSpellConfig::getAvailDictsIspell () {
+
+ langfnames.clear();
+ dictcombo->clear();
+ langfnames.append(""); // Default
+ dictcombo->insertItem( i18n("ISpell Default") );
+
+ // dictionary path
+ QFileInfo dir ("/usr/lib" KDELIBSUFF "/ispell");
+ if (!dir.exists() || !dir.isDir())
+ dir.setFile ("/usr/local/lib" KDELIBSUFF "/ispell");
+ if (!dir.exists() || !dir.isDir())
+ dir.setFile ("/usr/local/share/ispell");
+ if (!dir.exists() || !dir.isDir())
+ dir.setFile ("/usr/share/ispell");
+ if (!dir.exists() || !dir.isDir())
+ dir.setFile ("/usr/pkg/lib");
+ /* TODO get them all instead of just one of them.
+ * If /usr/local/lib exists, it skips the rest
+ if (!dir.exists() || !dir.isDir())
+ dir.setFile ("/usr/local/lib");
+ */
+ if (!dir.exists() || !dir.isDir()) return;
+
+ kdDebug(750) << "KSpellConfig::getAvailDictsIspell "
+ << dir.filePath() << " " << dir.dirPath() << endl;
+
+ const QDir thedir (dir.filePath(),"*.hash");
+ const QStringList entryList = thedir.entryList();
+
+ kdDebug(750) << "KSpellConfig" << thedir.path() << "\n" << endl;
+ kdDebug(750) << "entryList().count()="
+ << entryList.count() << endl;
+
+ QStringList::const_iterator entryListItr = entryList.constBegin();
+ const QStringList::const_iterator entryListEnd = entryList.constEnd();
+
+ for ( ; entryListItr != entryListEnd; ++entryListItr)
+ {
+ QString fname, lname, hname;
+ fname = *entryListItr;
+
+ // remove .hash
+ if (fname.endsWith(".hash")) fname.remove (fname.length()-5,5);
+
+ if (interpret (fname, lname, hname) && langfnames.first().isEmpty())
+ { // This one is the KDE default language
+ // so place it first in the lists (overwrite "Default")
+
+ langfnames.remove ( langfnames.begin() );
+ langfnames.prepend ( fname );
+
+ hname=i18n("default spelling dictionary"
+ ,"Default - %1 [%2]").arg(hname).arg(fname);
+
+ dictcombo->changeItem (hname,0);
+ }
+ else
+ {
+ langfnames.append (fname);
+ hname=hname+" ["+fname+"]";
+
+ dictcombo->insertItem (hname);
+ }
+ }
+}
+
+void KSpellConfig::getAvailDictsAspell () {
+
+ langfnames.clear();
+ dictcombo->clear();
+
+ langfnames.append(""); // Default
+ dictcombo->insertItem (i18n("ASpell Default"));
+
+ // Aspell now have /usr/lib/aspell as
+ // ASPELL_DATADIR default.
+ QFileInfo dir ( ASPELL_DATADIR );
+ if (!dir.exists() || !dir.isDir())
+ dir.setFile ("/usr/lib" KDELIBSUFF "/aspell-0.60");
+ if (!dir.exists() || !dir.isDir())
+ dir.setFile ("/usr/local/lib" KDELIBSUFF "/aspell");
+ if (!dir.exists() || !dir.isDir())
+ dir.setFile ("/usr/share/aspell");
+ if (!dir.exists() || !dir.isDir())
+ dir.setFile ("/usr/local/share/aspell");
+ if (!dir.exists() || !dir.isDir())
+ dir.setFile ("/usr/pkg/lib/aspell");
+ if (!dir.exists() || !dir.isDir()) return;
+
+ kdDebug(750) << "KSpellConfig::getAvailDictsAspell "
+ << dir.filePath() << " " << dir.dirPath() << endl;
+
+ const QDir thedir (dir.filePath(),"*");
+ const QStringList entryList = thedir.entryList();
+
+ kdDebug(750) << "KSpellConfig" << thedir.path() << "\n" << endl;
+ kdDebug(750) << "entryList().count()="
+ << entryList.count() << endl;
+
+ QStringList::const_iterator entryListItr = entryList.constBegin();
+ const QStringList::const_iterator entryListEnd = entryList.constEnd();
+
+ for ( ; entryListItr != entryListEnd; ++entryListItr)
+ {
+ QString fname, lname, hname;
+ fname = *entryListItr;
+
+ // consider only simple dicts without '-' in the name
+ // FIXME: may be this is wrong an the list should contain
+ // all *.multi files too, to allow using special dictionaries
+
+ // Well, KSpell2 has a better way to do this, but this code has to be
+ // cleaned up somehow: since aspell 0.6 we have quite a lot of files in the
+ // aspell dictionary that are not dictionaries. These must not be presented as "languages"
+ // We only keep
+ // *.rws: dictionary
+ // *.multi: definition file to load several subdictionaries
+ if ( !( fname.endsWith(".rws") || fname.endsWith(".multi") ) ) {
+ // remove noise from the language list
+ continue;
+ }
+ if (fname[0] != '.')
+ {
+
+ // remove .multi
+ if (fname.endsWith(".multi")) fname.remove (fname.length()-6,6);
+ // remove .rws
+ if (fname.endsWith(".rws")) fname.remove (fname.length()-4,4);
+
+ if (interpret (fname, lname, hname) && langfnames.first().isEmpty())
+ { // This one is the KDE default language
+ // so place it first in the lists (overwrite "Default")
+
+ langfnames.remove ( langfnames.begin() );
+ langfnames.prepend ( fname );
+
+ hname=i18n("default spelling dictionary"
+ ,"Default - %1").arg(hname);
+
+ dictcombo->changeItem (hname,0);
+ }
+ else
+ {
+ langfnames.append (fname);
+ dictcombo->insertItem (hname);
+ }
+ }
+ }
+}
+
+void
+KSpellConfig::fillDicts( QComboBox* box, QStringList* dictionaries )
+{
+ langfnames.clear();
+ if ( box ) {
+ if ( iclient == KS_CLIENT_ISPELL ) {
+ box->clear();
+ langfnames.append(""); // Default
+ box->insertItem( i18n("ISpell Default") );
+
+ // dictionary path
+ QFileInfo dir ("/usr/lib/ispell");
+ if (!dir.exists() || !dir.isDir())
+ dir.setFile ("/usr/local/lib/ispell");
+ if (!dir.exists() || !dir.isDir())
+ dir.setFile ("/usr/local/share/ispell");
+ if (!dir.exists() || !dir.isDir())
+ dir.setFile ("/usr/share/ispell");
+ if (!dir.exists() || !dir.isDir())
+ dir.setFile ("/usr/pkg/lib");
+ /* TODO get them all instead of just one of them.
+ * If /usr/local/lib exists, it skips the rest
+ if (!dir.exists() || !dir.isDir())
+ dir.setFile ("/usr/local/lib");
+ */
+ if (!dir.exists() || !dir.isDir()) return;
+
+ kdDebug(750) << "KSpellConfig::getAvailDictsIspell "
+ << dir.filePath() << " " << dir.dirPath() << endl;
+
+ const QDir thedir (dir.filePath(),"*.hash");
+ const QStringList entryList = thedir.entryList();
+
+ kdDebug(750) << "KSpellConfig" << thedir.path() << "\n" << endl;
+ kdDebug(750) << "entryList().count()="
+ << entryList.count() << endl;
+
+ QStringList::const_iterator entryListItr = entryList.constBegin();
+ const QStringList::const_iterator entryListEnd = entryList.constEnd();
+
+ for ( ; entryListItr != entryListEnd; ++entryListItr)
+ {
+ QString fname, lname, hname;
+ fname = *entryListItr;
+
+ // remove .hash
+ if (fname.endsWith(".hash")) fname.remove (fname.length()-5,5);
+
+ if (interpret (fname, lname, hname) && langfnames.first().isEmpty())
+ { // This one is the KDE default language
+ // so place it first in the lists (overwrite "Default")
+
+ langfnames.remove ( langfnames.begin() );
+ langfnames.prepend ( fname );
+
+ hname=i18n("default spelling dictionary"
+ ,"Default - %1 [%2]").arg(hname).arg(fname);
+
+ box->changeItem (hname,0);
+ }
+ else
+ {
+ langfnames.append (fname);
+ hname=hname+" ["+fname+"]";
+
+ box->insertItem (hname);
+ }
+ }
+ } else if ( iclient == KS_CLIENT_HSPELL ) {
+ box->clear();
+ box->insertItem( i18n("Hebrew") );
+ langfnames.append(""); // Default
+ sChangeEncoding( KS_E_CP1255 );
+ } else if ( iclient == KS_CLIENT_ZEMBEREK ) {
+ box->clear();
+ box->insertItem( i18n("Turkish") );
+ langfnames.append("");
+ sChangeEncoding( KS_E_UTF8 );
+ }
+ else {
+ box->clear();
+ langfnames.append(""); // Default
+ box->insertItem (i18n("ASpell Default"));
+
+ // dictionary path
+ // FIXME: use "aspell dump config" to find out the dict-dir
+ QFileInfo dir ("/usr/lib" KDELIBSUFF "/aspell");
+ if (!dir.exists() || !dir.isDir())
+ dir.setFile ("/usr/lib" KDELIBSUFF "/aspell-0.60");
+ if (!dir.exists() || !dir.isDir())
+ dir.setFile ("/usr/local/lib" KDELIBSUFF "/aspell");
+ if (!dir.exists() || !dir.isDir())
+ dir.setFile ("/usr/share/aspell");
+ if (!dir.exists() || !dir.isDir())
+ dir.setFile ("/usr/local/share/aspell");
+ if (!dir.exists() || !dir.isDir())
+ dir.setFile ("/usr/pkg/lib/aspell");
+ if (!dir.exists() || !dir.isDir()) return;
+
+ kdDebug(750) << "KSpellConfig::getAvailDictsAspell "
+ << dir.filePath() << " " << dir.dirPath() << endl;
+
+ const QDir thedir (dir.filePath(),"*");
+ const QStringList entryList = thedir.entryList();
+
+ kdDebug(750) << "KSpellConfig" << thedir.path() << "\n" << endl;
+ kdDebug(750) << "entryList().count()="
+ << entryList.count() << endl;
+
+ QStringList::const_iterator entryListItr = entryList.constBegin();
+ const QStringList::const_iterator entryListEnd = entryList.constEnd();
+
+ for ( ; entryListItr != entryListEnd; ++entryListItr)
+ {
+ QString fname, lname, hname;
+ fname = *entryListItr;
+
+ // consider only simple dicts without '-' in the name
+ // FIXME: may be this is wrong an the list should contain
+ // all *.multi files too, to allow using special dictionaries
+
+ // Well, KSpell2 has a better way to do this, but this code has to be
+ // cleaned up somehow: since aspell 0.6 we have quite a lot of files in the
+ // aspell dictionary that are not dictionaries. These must not be presented as "languages"
+ // We only keep
+ // *.rws: dictionary
+ // *.multi: definition file to load several subdictionaries
+ if ( !( fname.endsWith(".rws") || fname.endsWith(".multi") ) ) {
+ // remove noise from the language list
+ continue;
+ }
+ if (fname[0] != '.')
+ {
+
+ // remove .multi
+ if (fname.endsWith(".multi")) fname.remove (fname.length()-6,6);
+ // remove .rws
+ if (fname.endsWith(".rws")) fname.remove (fname.length()-4,4);
+
+ if (interpret (fname, lname, hname) && langfnames.first().isEmpty())
+ { // This one is the KDE default language
+ // so place it first in the lists (overwrite "Default")
+
+ langfnames.remove ( langfnames.begin() );
+ langfnames.prepend ( fname );
+
+ hname=i18n("default spelling dictionary"
+ ,"Default - %1").arg(hname);
+
+ box->changeItem (hname,0);
+ }
+ else
+ {
+ langfnames.append (fname);
+ box->insertItem (hname);
+ }
+ }
+ }
+ }
+ int whichelement = langfnames.findIndex(qsdict);
+ if ( whichelement >= 0 ) {
+ box->setCurrentItem( whichelement );
+ }
+ if ( dictionaries )
+ *dictionaries = langfnames;
+ }
+}
+
+/*
+ * Options setting routines.
+ */
+
+void
+KSpellConfig::setClient (int c)
+{
+ iclient = c;
+
+ if (clientcombo)
+ clientcombo->setCurrentItem(c);
+}
+
+void
+KSpellConfig::setNoRootAffix (bool b)
+{
+ bnorootaffix=b;
+
+ if(cb1)
+ cb1->setChecked(b);
+}
+
+void
+KSpellConfig::setRunTogether(bool b)
+{
+ bruntogether=b;
+
+ if(cb2)
+ cb2->setChecked(b);
+}
+
+void
+KSpellConfig::setDictionary (const QString s)
+{
+ qsdict=s; //.copy();
+
+ if (qsdict.length()>5)
+ if ((signed)qsdict.find(".hash")==(signed)qsdict.length()-5)
+ qsdict.remove (qsdict.length()-5,5);
+
+
+ if(dictcombo)
+ {
+ int whichelement=-1;
+ if (dictFromList())
+ {
+ whichelement = langfnames.findIndex(s);
+
+ if(whichelement >= 0)
+ {
+ dictcombo->setCurrentItem(whichelement);
+ }
+ }
+ }
+
+
+}
+
+void
+KSpellConfig::setDictFromList (bool dfl)
+{
+ // kdebug (KDEBUG_INFO, 750, "sdfl = %d", dfl);
+ dictfromlist=dfl;
+}
+
+/*
+void KSpellConfig::setPersonalDict (const char *s)
+{
+ qspdict=s;
+}
+*/
+
+void
+KSpellConfig::setEncoding (int enctype)
+{
+ enc=enctype;
+
+ if(encodingcombo)
+ encodingcombo->setCurrentItem(enctype);
+}
+
+/*
+ Options reading routines.
+ */
+int
+KSpellConfig::client () const
+{
+ return iclient;
+}
+
+
+bool
+KSpellConfig::noRootAffix () const
+{
+ return bnorootaffix;
+}
+
+bool
+KSpellConfig::runTogether() const
+{
+ return bruntogether;
+}
+
+const
+QString KSpellConfig::dictionary () const
+{
+ return qsdict;
+}
+
+/*
+const QString KSpellConfig::personalDict () const
+{
+ return qspdict;
+}
+*/
+
+int
+KSpellConfig::encoding () const
+{
+ return enc;
+}
+
+void
+KSpellConfig::sRunTogether(bool)
+{
+ setRunTogether (cb2->isChecked());
+ emit configChanged();
+}
+
+void
+KSpellConfig::sNoAff(bool)
+{
+ setNoRootAffix (cb1->isChecked());
+ emit configChanged();
+}
+
+/*
+void
+KSpellConfig::sBrowseDict()
+{
+ return;
+
+ QString qs( KFileDialog::getOpenFileName ("/usr/local/lib","*.hash") );
+ if ( !qs.isNull() )
+ kle1->setText (qs);
+
+}
+*/
+
+/*
+void KSpellConfig::sBrowsePDict()
+{
+ //how do I find home directory path??
+ QString qs( KFileDialog::getOpenFileName ("",".ispell_*") );
+ if ( !qs.isNull() )
+ kle2->setText (qs);
+
+
+}
+*/
+
+void
+KSpellConfig::sSetDictionary (int i)
+{
+ setDictionary (langfnames[i]);
+ setDictFromList (true);
+ QTimer::singleShot( 0, this, SIGNAL( configChanged() ) );
+}
+
+void
+KSpellConfig::sDictionary(bool on)
+{
+ if (on)
+ {
+ dictcombo->setEnabled (true);
+ setDictionary (langfnames[dictcombo->currentItem()] );
+ setDictFromList (true);
+ }
+ else
+ {
+ dictcombo->setEnabled (false);
+ }
+ emit configChanged();
+}
+
+void
+KSpellConfig::sPathDictionary(bool on)
+{
+ return; //enough for now
+
+
+ if (on)
+ {
+ //kle1->setEnabled (true);
+ // browsebutton1->setEnabled (true);
+ //setDictionary (kle1->text());
+ setDictFromList (false);
+ }
+ else
+ {
+ //kle1->setEnabled (false);
+ //browsebutton1->setEnabled (false);
+ }
+ emit configChanged();
+}
+
+
+void KSpellConfig::activateHelp( void )
+{
+ sHelp();
+}
+
+void KSpellConfig::sHelp( void )
+{
+ kapp->invokeHelp("configuration", "kspell");
+}
+
+/*
+void KSpellConfig::textChanged1 (const char *s)
+{
+ setDictionary (s);
+}
+
+void KSpellConfig::textChanged2 (const char *)
+{
+ // setPersonalDict (s);
+}
+*/
+
+void
+KSpellConfig::operator= (const KSpellConfig &ksc)
+{
+ //We want to copy the data members, but not the
+ //pointers to the child widgets
+ setNoRootAffix (ksc.noRootAffix());
+ setRunTogether (ksc.runTogether());
+ setDictionary (ksc.dictionary());
+ setDictFromList (ksc.dictFromList());
+ // setPersonalDict (ksc.personalDict());
+ setEncoding (ksc.encoding());
+ setClient (ksc.client());
+
+ fillInDialog();
+}
+
+// KDE 4: Make it const QStringList &
+void
+KSpellConfig::setIgnoreList (QStringList _ignorelist)
+{
+ ignorelist=_ignorelist;
+}
+
+QStringList
+KSpellConfig::ignoreList () const
+{
+ return ignorelist;
+}
+
+// KDE 4: Make it const QStringList &
+void
+KSpellConfig::setReplaceAllList (QStringList _replacelist)
+{
+ d->replacelist=_replacelist;
+}
+
+QStringList
+KSpellConfig::replaceAllList() const
+{
+ return d->replacelist;
+}
+
+#include "ksconfig.moc"
+
+
+
diff --git a/kdeui/ksconfig.h b/kdeui/ksconfig.h
new file mode 100644
index 000000000..548fbfc84
--- /dev/null
+++ b/kdeui/ksconfig.h
@@ -0,0 +1,293 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 David Sweet <dsweet@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef KDELIBS_KSCONFIG_H
+#define KDELIBS_KSCONFIG_H
+
+#include <qwidget.h>
+#include <qstring.h>
+#include <qstringlist.h>
+
+#include <kdelibs_export.h>
+
+class QCheckBox;
+class QComboBox;
+class QLabel;
+
+class KConfig;
+class KSpellConfigPrivate;
+
+/**
+ * @brief Encoding for the spell checker
+ * @note In the identifier names LATIN means ISO-8859, not ECMA Latin
+ * @todo Should be replaced by the charset strings
+ * because the config file would be more stable
+ * when inserting entries in the list
+ */
+enum Encoding {
+ KS_E_ASCII=0,
+ KS_E_LATIN1=1,
+ KS_E_LATIN2=2,
+ KS_E_LATIN3=3,
+ KS_E_LATIN4=4,
+ KS_E_LATIN5=5, ///< ISO-8859-5 (Cyrillic)
+ KS_E_LATIN7=6, ///< ISO-8859-6 (Arabic)
+ KS_E_LATIN8=7, ///< ISO-8859-7 (Greek)
+ KS_E_LATIN9=8, ///< ISO-8859-8 (Hebrew)
+ KS_E_LATIN13=9, ///< ISO-8859-13 (Latin 7)
+ KS_E_LATIN15=10, ///< ISO-8859-15 (Latin 9)
+ KS_E_UTF8=11,
+ KS_E_KOI8R=12,
+ KS_E_KOI8U=13,
+ KS_E_CP1251=14,
+ KS_E_CP1255=15
+};
+
+enum KSpellClients {
+ KS_CLIENT_ISPELL=0,
+ KS_CLIENT_ASPELL=1,
+ KS_CLIENT_HSPELL=2,
+ KS_CLIENT_ZEMBEREK=3
+};
+
+/**
+ * A configuration class/dialog for KSpell.
+ *
+ * It contains all of the options settings.The options are set to default
+ * values by the constructor and can be reset either by using the
+ * public interface or by using KSpellConfig as a widget in a dialog
+ * (or, preferably a tabbed dialog using KDialogBase) and letting
+ * the user change the settings. This way an application that uses
+ * KSpell can either rely on the default settings (in the simplest
+ * case), offer a dialog to configure KSpell, or offer a dialog to
+ * configure KSpell <em>for this app only</em> (in which case, the application
+ * should save the settings for use next time it is run).
+ * This last option might be useful in an email program, for example, where
+ * people may be writing in a language different from that used for
+ * writing papers in their word processor.
+ *
+ * @author David Sweet <dsweet@kde.org>
+ * @see KSpell
+ */
+
+class KDEUI_EXPORT KSpellConfig : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Constructs a KSpellConfig with default or custom settings.
+ *
+ * @param parent Parent of the widget.
+ * @param name Widget name.
+ * @param spellConfig Predefined configuration. If this parameter
+ * is 0, a default configuration will be used.
+ * @param addHelpButton Enabled or hides a help button. See
+ * activateHelp for more information.
+ *
+ */
+ KSpellConfig( QWidget *parent=0, const char *name=0,
+ KSpellConfig *spellConfig=0, bool addHelpButton = true );
+
+ KSpellConfig( const KSpellConfig & );
+
+ /**
+ * Deconstructor.
+ * Deletes private class.
+ */
+ virtual ~KSpellConfig();
+
+ void operator=( const KSpellConfig &ksc );
+
+ /**
+ *
+ * @short Get the translated dictionary names and, optionally, the
+ * corresponding internal dictionary names.
+ *
+ * Fills @p box with the human readable, translated dictionary names and
+ * selects the currently used dictionary (this will be the global
+ * dictionary if you call @ref fillDicts directly after the constructor).
+ * If @p dictionaries isn't 0 then @p dictionaries will be filled with the
+ * corresponding internal dictionary names that are necessary to set the
+ * dictionary with @ref setDictionary.
+ *
+ * @param box Will be filled with the translated dictionary names.
+ * @param dictionaries Will be filled with the internal dictionary names.
+ *
+ * @since 3.2
+ *
+ */
+ void fillDicts( QComboBox* box, QStringList* dictionaries = 0 );
+
+ /**
+ * @sect Options setting routines.
+ **/
+
+ /**
+ *
+ * The @p _ignorelist contains words you'd like KSpell
+ * to ignore when it is spellchecking. When you get a KSpellConfig
+ * object back from KSpell (using KSpell::kcConfig()),
+ * the @p _ignorelist contains whatever was put in by you plus
+ * any words the user has chosen to ignore via the dialog box.
+ * It may be useful to save this list with the document being
+ * edited to facilitate quicker future spellchecking.
+ */
+ void setIgnoreList( QStringList _ignorelist );
+
+ /**
+ * The @p _replaceAllList contains word you like that replace
+ * word. Be careful that this list contains word which is replaced
+ * and new word.
+ */
+ void setReplaceAllList( QStringList _replaceAllList );
+
+ /**
+ * Set an ISpell option.
+ *
+ * If @p true, don't create root-affix combinations.
+ */
+ void setNoRootAffix( bool );
+
+ /**
+ * Set an ISpell option.
+ *
+ * If @p true, treat run-together words a valid.
+ */
+ void setRunTogether( bool );
+
+ /**
+ * Set the name of the dictionary to use.
+ */
+ void setDictionary( const QString qs );
+ void setDictFromList( bool dfl );
+ //void setPersonalDict (const char *s);
+
+ /**
+ *
+ */
+ void setEncoding( int enctype );
+ void setClient( int client );
+
+ /**
+ * Options reading routines.
+ */
+ bool noRootAffix() const;
+ bool runTogether() const;
+ const QString dictionary() const;
+ bool dictFromList() const;
+ //QString personalDict () const;
+ int encoding() const;
+ QStringList ignoreList() const;
+ QStringList replaceAllList() const;
+
+ int client() const; ///< Spell checker client, see KSpellClients
+
+ /**
+ * Call this method before this class is deleted if you want
+ * the settings you have (or the user has) chosen to become the
+ * global, default settings.
+ */
+ bool writeGlobalSettings();
+
+ bool readGlobalSettings();
+ protected:
+ void fillInDialog();
+
+ /**
+ * This takes a dictionary file name and provides both a language
+ * abbreviation appropriate for the $LANG variable, and a
+ * human-readable name.
+ *
+ * It also truncates ".aff" at the end of fname.
+ *
+ * @param fname the dictionary name file (input)
+ * @param lname the language abbreviation, such as de for German (output)
+ * @param hname the human-readable name, such as Deutsch (output)
+ *
+ * @return true if <pre>lname.data()==$LANG</pre>
+ */
+ bool interpret( QString &fname, QString &lname, QString &hname );
+
+
+ public slots:
+ /**
+ * Use this function to activate the help information for this
+ * widget. The function is particulary useful if the help button is
+ * not displayed as specified by the constructor. Normally you want
+ * to hide the help button if this widget is embedded into a larger
+ * dialog box that has its own help button. See kedit
+ * (optiondialog.cpp) for an example
+ */
+ void activateHelp( void );
+
+
+ protected slots:
+ /**
+ * Invokes the help documentation for kspell
+ */
+ void sHelp();
+ //void sBrowseDict();
+ //void sBrowsePDict();
+ void sNoAff( bool );
+ void sRunTogether( bool );
+ void sDictionary( bool );
+ void sPathDictionary( bool );
+ void sSetDictionary( int );
+ void sChangeEncoding( int );
+ void sChangeClient( int );
+ //void textChanged1 (const char *);
+ //void textChanged2 (const char *);
+
+ protected:
+ // The options
+ int enc; // 1 ==> -Tlatin1
+ bool bnorootaffix; // -m
+ bool bruntogether; // -B
+ bool dictfromlist;
+ bool nodialog;
+ QString qsdict; // -d [dict]
+ QString qspdict; // -p [dict]
+ QStringList ignorelist;
+ enum {rdictlist=3, rencoding=4, rhelp=6};
+ KConfig *kc;
+ int iclient; // defaults to ispell, may be aspell, too
+
+ QCheckBox *cb1, *cb2;
+ //KLineEdit *kle1, *kle2;
+ //QButtonGroup *dictgroup;
+ //QRadioButton *dictlistbutton, *dicteditbutton;
+ QLabel *dictlist;
+ QComboBox *dictcombo, *encodingcombo, *clientcombo;
+ //QPushButton *browsebutton1;
+ QStringList langfnames;
+
+signals:
+ void configChanged();
+
+private:
+ KSpellConfigPrivate *d;
+ void getAvailDictsIspell();
+ void getAvailDictsAspell();
+};
+
+#endif // KDELIBS_KSCONFIG_H
+
+
+
+
+
diff --git a/kdeui/kscrollview.cpp b/kdeui/kscrollview.cpp
new file mode 100644
index 000000000..779f6a62b
--- /dev/null
+++ b/kdeui/kscrollview.cpp
@@ -0,0 +1,189 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2005 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+
+#include <qtimer.h>
+#include <qevent.h>
+#include <qapplication.h>
+
+#include "kscrollview.h"
+#include <kdebug.h>
+#include <kconfig.h>
+#include <kglobal.h>
+
+struct KScrollView::KScrollViewPrivate {
+ KScrollViewPrivate() : dx(0), dy(0), ddx(0), ddy(0), rdx(0), rdy(0), scrolling(false) {}
+ QTimer timer;
+ int dx;
+ int dy;
+ // Step size * 16 and residual to avoid huge difference between 1px/step and 2px/step
+ int ddx;
+ int ddy;
+ int rdx;
+ int rdy;
+ bool scrolling;
+};
+
+KScrollView::KScrollView( QWidget *parent, const char *name, Qt::WFlags f )
+ : QScrollView( parent, name, f )
+{
+ d = new KScrollViewPrivate;
+ connect(&d->timer, SIGNAL(timeout()), this, SLOT(scrollTick()));
+}
+
+KScrollView::~KScrollView()
+{
+ delete d;
+}
+
+void KScrollView::scrollBy(int dx, int dy)
+{
+ KConfigGroup cfg( KGlobal::config(), "KDE" );
+ if( !cfg.readBoolEntry( "SmoothScrolling", true )) {
+ QScrollView::scrollBy( dx, dy );
+ return;
+ }
+ // scrolling destination
+ int full_dx = d->dx + dx;
+ int full_dy = d->dy + dy;
+
+ // scrolling speed
+ int ddx = 0;
+ int ddy = 0;
+
+ int steps = SCROLL_TIME/SCROLL_TICK;
+
+ ddx = (full_dx*16)/steps;
+ ddy = (full_dy*16)/steps;
+
+ // don't go under 1px/step
+ if (ddx > 0 && ddx < 16) ddx = 16;
+ if (ddy > 0 && ddy < 16) ddy = 16;
+ if (ddx < 0 && ddx > -16) ddx = -16;
+ if (ddy < 0 && ddy > -16) ddy = -16;
+
+ d->dx = full_dx;
+ d->dy = full_dy;
+ d->ddx = ddx;
+ d->ddy = ddy;
+
+ if (!d->scrolling) {
+ scrollTick();
+ startScrolling();
+ }
+}
+/*
+void KScrollView::scrollBy(int dx, int dy)
+{
+ if (d->scrolling)
+ setContentsPos( d->x+dx, d->y+dy );
+ else
+ setContentsPos( contentsX() + dx, contentsY() + dy);
+}
+
+void KScrollView::setContentsPos(int x, int y)
+{
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+
+ int dx = x - contentsX();
+ int dy = y - contentsY();
+
+ // to large to smooth out
+// if (dx > 1000 || dy > 1000) return QScrollView::setContentsPos(x,y);
+
+ // scrolling speed
+ int ddx = 0;
+ int ddy = 0;
+
+ int steps = SCROLL_TIME/SCROLL_TICK;
+
+ ddx = (dx*16)/steps;
+ ddy = (dy*16)/steps;
+
+ d->x = x;
+ d->y = y;
+ d->dx = dx;
+ d->dy = dy;
+ d->ddx = ddx;
+ d->ddy = ddy;
+
+ if (!d->scrolling) {
+ scrollTick();
+ startScrolling();
+ }
+} */
+
+void KScrollView::scrollTick() {
+ if (d->dx == 0 && d->dy == 0) {
+ stopScrolling();
+ return;
+ }
+
+ int tddx = d->ddx + d->rdx;
+ int tddy = d->ddy + d->rdy;
+
+ int ddx = tddx / 16;
+ int ddy = tddy / 16;
+ d->rdx = tddx % 16;
+ d->rdy = tddy % 16;
+
+ if (d->dx > 0 && ddx > d->dx) ddx = d->dx;
+ else
+ if (d->dx < 0 && ddx < d->dx) ddx = d->dx;
+
+ if (d->dy > 0 && ddy > d->dy) ddy = d->dy;
+ else
+ if (d->dy < 0 && ddy < d->dy) ddy = d->dy;
+
+ d->dx -= ddx;
+ d->dy -= ddy;
+
+// QScrollView::setContentsPos( contentsX() + ddx, contentsY() + ddy);
+ QScrollView::scrollBy(ddx, ddy);
+}
+
+void KScrollView::startScrolling()
+{
+ d->scrolling = true;
+ d->timer.start(SCROLL_TICK, false);
+}
+
+void KScrollView::stopScrolling()
+{
+ d->timer.stop();
+ d->dx = d->dy = 0;
+ d->scrolling = false;
+}
+
+// Overloaded from QScrollView and QScrollBar
+void KScrollView::wheelEvent( QWheelEvent *e )
+{
+ int pageStep = verticalScrollBar()->pageStep();
+ int lineStep = verticalScrollBar()->lineStep();
+ int step = QMIN( QApplication::wheelScrollLines()*lineStep, pageStep );
+ if ( ( e->state() & ControlButton ) || ( e->state() & ShiftButton ) )
+ step = pageStep;
+
+ int dy = (e->delta()*step)/120;
+ scrollBy(0,-dy);
+ e->accept();
+}
+
+#include "kscrollview.moc"
diff --git a/kdeui/kscrollview.h b/kdeui/kscrollview.h
new file mode 100644
index 000000000..9326876af
--- /dev/null
+++ b/kdeui/kscrollview.h
@@ -0,0 +1,62 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2005 Allan Sandfeld Jensen <kde@carewolf.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef KSCROLLVIEW_H
+#define KSCROLLVIEW_H
+
+#include <qscrollview.h>
+
+#include <kdelibs_export.h>
+
+/**
+ * @short A variant of QScrollView that supports smooth scrolling.
+ *
+ *
+ **/
+class KDEUI_EXPORT KScrollView : public QScrollView
+{
+ Q_OBJECT
+
+public:
+ KScrollView( QWidget *parent = 0, const char *name = 0, Qt::WFlags f = 0 );
+
+ ~KScrollView();
+
+public slots:
+ void scrollBy(int dx, int dy);
+// virtual void setContentsPos(int x, int y);
+
+protected:
+ virtual void wheelEvent( QWheelEvent *e );
+
+ void startScrolling();
+ void stopScrolling();
+
+protected slots:
+ void scrollTick();
+
+private:
+ // All scrolls must be completed within 240ms of last keypress
+ static const int SCROLL_TIME = 240;
+ // Each step is 20 ms == 50 frames/second
+ static const int SCROLL_TICK = 20;
+
+ struct KScrollViewPrivate;
+ KScrollViewPrivate *d;
+};
+
+#endif
diff --git a/kdeui/kselect.cpp b/kdeui/kselect.cpp
new file mode 100644
index 000000000..3795056e6
--- /dev/null
+++ b/kdeui/kselect.cpp
@@ -0,0 +1,534 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Martin Jones (mjones@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qimage.h>
+#include <qpainter.h>
+#include <qdrawutil.h>
+#include <qstyle.h>
+#include <kimageeffect.h>
+#include "kselect.h"
+
+#define STORE_W 8
+#define STORE_W2 STORE_W * 2
+
+//-----------------------------------------------------------------------------
+/*
+ * 2D value selector.
+ * The contents of the selector are drawn by derived class.
+ */
+
+KXYSelector::KXYSelector( QWidget *parent, const char *name )
+ : QWidget( parent, name )
+{
+ xPos = 0;
+ yPos = 0;
+ minX = 0;
+ minY = 0;
+ maxX = 100;
+ maxY = 100;
+ store.setOptimization( QPixmap::BestOptim );
+ store.resize( STORE_W2, STORE_W2 );
+}
+
+
+KXYSelector::~KXYSelector()
+{}
+
+
+void KXYSelector::setRange( int _minX, int _minY, int _maxX, int _maxY )
+{
+ int w = style().pixelMetric(QStyle::PM_DefaultFrameWidth);
+ px = w;
+ py = w;
+ minX = _minX;
+ minY = _minY;
+ maxX = _maxX;
+ maxY = _maxY;
+}
+
+void KXYSelector::setXValue( int _xPos )
+{
+ setValues(_xPos, yPos);
+}
+
+void KXYSelector::setYValue( int _yPos )
+{
+ setValues(xPos, _yPos);
+}
+
+void KXYSelector::setValues( int _xPos, int _yPos )
+{
+ int w = style().pixelMetric(QStyle::PM_DefaultFrameWidth);
+ if (w < 5) w = 5;
+
+ xPos = _xPos;
+ yPos = _yPos;
+
+ if ( xPos > maxX )
+ xPos = maxX;
+ else if ( xPos < minX )
+ xPos = minX;
+
+ if ( yPos > maxY )
+ yPos = maxY;
+ else if ( yPos < minY )
+ yPos = minY;
+
+ int xp = w + (width() - 2 * w) * xPos / (maxX - minX);
+ int yp = height() - w - (height() - 2 * w) * yPos / (maxY - minY);
+
+ setPosition( xp, yp );
+}
+
+QRect KXYSelector::contentsRect() const
+{
+ int w = style().pixelMetric(QStyle::PM_DefaultFrameWidth);
+ if (w < 5) {
+ w = 5;
+ }
+ QRect contents(rect());
+ contents.addCoords(w, w, -w, -w);
+ return contents;
+}
+
+void KXYSelector::paintEvent( QPaintEvent *ev )
+{
+ QRect cursorRect( px - STORE_W, py - STORE_W, STORE_W2, STORE_W2);
+ QRect paintRect = ev->rect();
+ QRect borderRect = rect();
+
+ int w = style().pixelMetric(QStyle::PM_DefaultFrameWidth);
+ if (w < 5) {
+ w = 5 - w;
+ }
+ borderRect.addCoords(w, w, -w, -w);
+
+ QPainter painter;
+ painter.begin( this );
+
+ style().drawPrimitive(QStyle::PE_Panel, &painter,
+ borderRect, colorGroup(),
+ QStyle::Style_Sunken);
+
+ drawContents( &painter );
+ if (paintRect.contains(cursorRect))
+ {
+ bitBlt( &store, 0, 0, this, px - STORE_W, py - STORE_W,
+ STORE_W2, STORE_W2, CopyROP );
+ drawCursor( &painter, px, py );
+ }
+ else if (paintRect.intersects(cursorRect))
+ {
+ repaint( cursorRect, false);
+ }
+
+ painter.end();
+}
+
+void KXYSelector::mousePressEvent( QMouseEvent *e )
+{
+ mouseMoveEvent(e);
+}
+
+void KXYSelector::mouseMoveEvent( QMouseEvent *e )
+{
+ int xVal, yVal;
+
+ int w = style().pixelMetric(QStyle::PM_DefaultFrameWidth);
+ valuesFromPosition( e->pos().x() - w, e->pos().y() - w, xVal, yVal );
+
+ setValues( xVal, yVal );
+
+ emit valueChanged( xPos, yPos );
+}
+
+void KXYSelector::wheelEvent( QWheelEvent *e )
+{
+ if ( e->orientation() == Qt::Horizontal )
+ setValues( xValue() + e->delta()/120, yValue() );
+ else
+ setValues( xValue(), yValue() + e->delta()/120 );
+
+ emit valueChanged( xPos, yPos );
+}
+
+void KXYSelector::valuesFromPosition( int x, int y, int &xVal, int &yVal ) const
+{
+ int w = style().pixelMetric(QStyle::PM_DefaultFrameWidth);
+ if (w < 5) w = 5;
+ xVal = ( (maxX-minX) * (x-w) ) / ( width()-2*w );
+ yVal = maxY - ( ( (maxY-minY) * (y-w) ) / ( height()-2*w ) );
+
+ if ( xVal > maxX )
+ xVal = maxX;
+ else if ( xVal < minX )
+ xVal = minX;
+
+ if ( yVal > maxY )
+ yVal = maxY;
+ else if ( yVal < minY )
+ yVal = minY;
+}
+
+void KXYSelector::setPosition( int xp, int yp )
+{
+ int w = style().pixelMetric(QStyle::PM_DefaultFrameWidth);
+ if (w < 5) w = 5;
+ if ( xp < w )
+ xp = w;
+ else if ( xp > width() - w )
+ xp = width() - w;
+
+ if ( yp < w )
+ yp = w;
+ else if ( yp > height() - w )
+ yp = height() - w;
+
+ QPainter painter;
+ painter.begin( this );
+
+ bitBlt( this, px - STORE_W, py - STORE_W, &store, 0, 0,
+ STORE_W2, STORE_W2, CopyROP );
+ bitBlt( &store, 0, 0, this, xp - STORE_W, yp - STORE_W,
+ STORE_W2, STORE_W2, CopyROP );
+ drawCursor( &painter, xp, yp );
+ px = xp;
+ py = yp;
+
+ painter.end();
+}
+
+void KXYSelector::drawContents( QPainter * )
+{}
+
+
+void KXYSelector::drawCursor( QPainter *p, int xp, int yp )
+{
+ p->setPen( QPen( white ) );
+
+ p->drawLine( xp - 6, yp - 6, xp - 2, yp - 2 );
+ p->drawLine( xp - 6, yp + 6, xp - 2, yp + 2 );
+ p->drawLine( xp + 6, yp - 6, xp + 2, yp - 2 );
+ p->drawLine( xp + 6, yp + 6, xp + 2, yp + 2 );
+}
+
+//-----------------------------------------------------------------------------
+/*
+ * 1D value selector with contents drawn by derived class.
+ * See KColorDialog for example.
+ */
+
+
+KSelector::KSelector( QWidget *parent, const char *name )
+ : QWidget( parent, name ), QRangeControl()
+{
+ _orientation = Horizontal;
+ _indent = true;
+}
+
+KSelector::KSelector( Orientation o, QWidget *parent, const char *name )
+ : QWidget( parent, name ), QRangeControl()
+{
+ _orientation = o;
+ _indent = true;
+}
+
+
+KSelector::~KSelector()
+{}
+
+
+QRect KSelector::contentsRect() const
+{
+ int w = style().pixelMetric(QStyle::PM_DefaultFrameWidth);
+ int iw = (w < 5) ? 5 : w;
+ if ( orientation() == Vertical )
+ return QRect( w, iw, width() - w * 2 - 5, height() - 2 * iw );
+ else
+ return QRect( iw, w, width() - 2 * iw, height() - w * 2 - 5 );
+}
+
+void KSelector::paintEvent( QPaintEvent * )
+{
+ QPainter painter;
+ int w = style().pixelMetric(QStyle::PM_DefaultFrameWidth);
+ int iw = (w < 5) ? 5 : w;
+
+ painter.begin( this );
+
+ drawContents( &painter );
+
+ if ( indent() )
+ {
+ QRect r = rect();
+ if ( orientation() == Vertical )
+ r.addCoords(0, iw - w, -iw, w - iw);
+ else
+ r.addCoords(iw - w, 0, w - iw, -iw);
+ style().drawPrimitive(QStyle::PE_Panel, &painter,
+ r, colorGroup(),
+ QStyle::Style_Sunken);
+ }
+
+ QPoint pos = calcArrowPos( value() );
+ drawArrow( &painter, true, pos );
+
+ painter.end();
+}
+
+void KSelector::mousePressEvent( QMouseEvent *e )
+{
+ moveArrow( e->pos() );
+}
+
+void KSelector::mouseMoveEvent( QMouseEvent *e )
+{
+ moveArrow( e->pos() );
+}
+
+void KSelector::wheelEvent( QWheelEvent *e )
+{
+ int val = value() + e->delta()/120;
+ setValue( val );
+}
+
+void KSelector::valueChange()
+{
+ QPainter painter;
+ QPoint pos;
+
+ painter.begin( this );
+
+ pos = calcArrowPos( prevValue() );
+ drawArrow( &painter, false, pos );
+
+ pos = calcArrowPos( value() );
+ drawArrow( &painter, true, pos );
+
+ painter.end();
+
+ emit valueChanged( value() );
+}
+
+void KSelector::moveArrow( const QPoint &pos )
+{
+ int val;
+ int w = style().pixelMetric(QStyle::PM_DefaultFrameWidth);
+ int iw = (w < 5) ? 5 : w;
+
+ if ( orientation() == Vertical )
+ val = ( maxValue() - minValue() ) * (height()-pos.y()-5+w)
+ / (height()-iw*2) + minValue();
+ else
+ val = ( maxValue() - minValue() ) * (width()-pos.x()-5+w)
+ / (width()-iw*2) + minValue();
+
+ setValue( val );
+}
+
+QPoint KSelector::calcArrowPos( int val )
+{
+ QPoint p;
+
+ int w = style().pixelMetric(QStyle::PM_DefaultFrameWidth);
+ int iw = (w < 5) ? 5 : w;
+ if ( orientation() == Vertical )
+ {
+ p.setY( height() - ( (height()-2*iw) * val
+ / ( maxValue() - minValue() ) + 5 ) );
+ p.setX( width() - 5 );
+ }
+ else
+ {
+ p.setX( width() - ( (width()-2*iw) * val
+ / ( maxValue() - minValue() ) + 5 ) );
+ p.setY( height() - 5 );
+ }
+
+ return p;
+}
+
+void KSelector::drawContents( QPainter * )
+{}
+
+void KSelector::drawArrow( QPainter *painter, bool show, const QPoint &pos )
+{
+ if ( show )
+ {
+ QPointArray array(3);
+
+ painter->setPen( QPen() );
+ painter->setBrush( QBrush( colorGroup().buttonText() ) );
+ array.setPoint( 0, pos.x()+0, pos.y()+0 );
+ array.setPoint( 1, pos.x()+5, pos.y()+5 );
+ if ( orientation() == Vertical )
+ {
+ array.setPoint( 2, pos.x()+5, pos.y()-5 );
+ }
+ else
+ {
+ array.setPoint( 2, pos.x()-5, pos.y()+5 );
+ }
+
+ painter->drawPolygon( array );
+ }
+ else
+ {
+ if ( orientation() == Vertical )
+ {
+ repaint(pos.x(), pos.y()-5, 6, 11, true);
+ }
+ else
+ {
+ repaint(pos.x()-5, pos.y(), 11, 6, true);
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+
+KGradientSelector::KGradientSelector( QWidget *parent, const char *name )
+ : KSelector( parent, name )
+{
+ init();
+}
+
+
+KGradientSelector::KGradientSelector( Orientation o, QWidget *parent,
+ const char *name )
+ : KSelector( o, parent, name )
+{
+ init();
+}
+
+
+KGradientSelector::~KGradientSelector()
+{}
+
+
+void KGradientSelector::init()
+{
+ color1.setRgb( 0, 0, 0 );
+ color2.setRgb( 255, 255, 255 );
+
+ text1 = text2 = "";
+}
+
+
+void KGradientSelector::drawContents( QPainter *painter )
+{
+ QImage image( contentsRect().width(), contentsRect().height(), 32 );
+
+ QColor col;
+ float scale;
+
+ int redDiff = color2.red() - color1.red();
+ int greenDiff = color2.green() - color1.green();
+ int blueDiff = color2.blue() - color1.blue();
+
+ if ( orientation() == Vertical )
+ {
+ for ( int y = 0; y < image.height(); y++ )
+ {
+ scale = 1.0 * y / image.height();
+ col.setRgb( color1.red() + int(redDiff*scale),
+ color1.green() + int(greenDiff*scale),
+ color1.blue() + int(blueDiff*scale) );
+
+ unsigned int *p = (uint *) image.scanLine( y );
+ for ( int x = 0; x < image.width(); x++ )
+ *p++ = col.rgb();
+ }
+ }
+ else
+ {
+ unsigned int *p = (uint *) image.scanLine( 0 );
+
+ for ( int x = 0; x < image.width(); x++ )
+ {
+ scale = 1.0 * x / image.width();
+ col.setRgb( color1.red() + int(redDiff*scale),
+ color1.green() + int(greenDiff*scale),
+ color1.blue() + int(blueDiff*scale) );
+ *p++ = col.rgb();
+ }
+
+ for ( int y = 1; y < image.height(); y++ )
+ memcpy( image.scanLine( y ), image.scanLine( y - 1),
+ sizeof( unsigned int ) * image.width() );
+ }
+
+ QColor ditherPalette[8];
+
+ for ( int s = 0; s < 8; s++ )
+ ditherPalette[s].setRgb( color1.red() + redDiff * s / 8,
+ color1.green() + greenDiff * s / 8,
+ color1.blue() + blueDiff * s / 8 );
+
+ KImageEffect::dither( image, ditherPalette, 8 );
+
+ QPixmap p;
+ p.convertFromImage( image );
+
+ painter->drawPixmap( contentsRect().x(), contentsRect().y(), p );
+
+ if ( orientation() == Vertical )
+ {
+ int yPos = contentsRect().top() + painter->fontMetrics().ascent() + 2;
+ int xPos = contentsRect().left() + (contentsRect().width() -
+ painter->fontMetrics().width( text2 )) / 2;
+ QPen pen( color2 );
+ painter->setPen( pen );
+ painter->drawText( xPos, yPos, text2 );
+
+ yPos = contentsRect().bottom() - painter->fontMetrics().descent() - 2;
+ xPos = contentsRect().left() + (contentsRect().width() -
+ painter->fontMetrics().width( text1 )) / 2;
+ pen.setColor( color1 );
+ painter->setPen( pen );
+ painter->drawText( xPos, yPos, text1 );
+ }
+ else
+ {
+ int yPos = contentsRect().bottom()-painter->fontMetrics().descent()-2;
+
+ QPen pen( color2 );
+ painter->setPen( pen );
+ painter->drawText( contentsRect().left() + 2, yPos, text1 );
+
+ pen.setColor( color1 );
+ painter->setPen( pen );
+ painter->drawText( contentsRect().right() -
+ painter->fontMetrics().width( text2 ) - 2, yPos, text2 );
+ }
+}
+
+//-----------------------------------------------------------------------------
+
+void KXYSelector::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void KSelector::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void KGradientSelector::virtual_hook( int id, void* data )
+{ KSelector::virtual_hook( id, data ); }
+
+#include "kselect.moc"
+
diff --git a/kdeui/kselect.h b/kdeui/kselect.h
new file mode 100644
index 000000000..bc281341d
--- /dev/null
+++ b/kdeui/kselect.h
@@ -0,0 +1,373 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Martin Jones (mjones@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+//-----------------------------------------------------------------------------
+// Selector widgets for KDE Color Selector, but probably useful for other
+// stuff also.
+
+#ifndef __KSELECT_H__
+#define __KSELECT_H__
+
+#include <qwidget.h>
+#include <qrangecontrol.h>
+#include <qpixmap.h>
+
+#include <kdelibs_export.h>
+
+/**
+ * KXYSelector is the base class for other widgets which
+ * provides the ability to choose from a two-dimensional
+ * range of values. The currently chosen value is indicated
+ * by a cross. An example is the KHSSelector which
+ * allows to choose from a range of colors, and which is
+ * used in KColorDialog.
+ *
+ * A custom drawing routine for the widget surface has
+ * to be provided by the subclass.
+ */
+class KDEUI_EXPORT KXYSelector : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY( int xValue READ xValue WRITE setXValue )
+ Q_PROPERTY( int yValue READ yValue WRITE setYValue )
+
+public:
+ /**
+ * Constructs a two-dimensional selector widget which
+ * has a value range of [0..100] in both directions.
+ */
+ KXYSelector( QWidget *parent=0, const char *name=0 );
+ /**
+ * Destructs the widget.
+ */
+ ~KXYSelector();
+
+ /**
+ * Sets the current values in horizontal and
+ * vertical direction.
+ * @param xPos the horizontal value
+ * @param yPos the veritcal value
+ */
+ void setValues( int xPos, int yPos );
+
+ /**
+ * Sets the current horizontal value
+ * @param xPos the horizontal value
+ */
+ void setXValue( int xPos );
+
+ /**
+ * Sets the current vertical value
+ * @param yPos the veritcal value
+ */
+ void setYValue( int yPos );
+
+ /**
+ * Sets the range of possible values.
+ */
+ void setRange( int minX, int minY, int maxX, int maxY );
+
+ /**
+ * @return the current value in horizontal direction.
+ */
+ int xValue() const { return xPos; }
+ /**
+ * @return the current value in vertical direction.
+ */
+ int yValue() const { return yPos; }
+
+ /**
+ * @return the rectangle on which subclasses should draw.
+ */
+ QRect contentsRect() const;
+
+signals:
+ /**
+ * This signal is emitted whenever the user chooses a value,
+ * e.g. by clicking with the mouse on the widget.
+ */
+ void valueChanged( int x, int y );
+
+protected:
+ /**
+ * Override this function to draw the contents of the widget.
+ * The default implementation does nothing.
+ *
+ * Draw within contentsRect() only.
+ */
+ virtual void drawContents( QPainter * );
+ /**
+ * Override this function to draw the cursor which
+ * indicates the currently selected value pair.
+ */
+ virtual void drawCursor( QPainter *p, int xp, int yp );
+
+ virtual void paintEvent( QPaintEvent *e );
+ virtual void mousePressEvent( QMouseEvent *e );
+ virtual void mouseMoveEvent( QMouseEvent *e );
+ virtual void wheelEvent( QWheelEvent * );
+
+ /**
+ * Converts a pixel position to its corresponding values.
+ */
+ void valuesFromPosition( int x, int y, int& xVal, int& yVal ) const;
+
+private:
+ void setPosition( int xp, int yp );
+ int px;
+ int py;
+ int xPos;
+ int yPos;
+ int minX;
+ int maxX;
+ int minY;
+ int maxY;
+ QPixmap store;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KXYSelectorPrivate;
+ KXYSelectorPrivate *d;
+};
+
+
+/**
+ * KSelector is the base class for other widgets which
+ * provides the ability to choose from a one-dimensional
+ * range of values. An example is the KGradientSelector
+ * which allows to choose from a range of colors.
+ *
+ * A custom drawing routine for the widget surface has
+ * to be provided by the subclass.
+ */
+class KDEUI_EXPORT KSelector : public QWidget, public QRangeControl
+{
+ Q_OBJECT
+ Q_PROPERTY( int value READ value WRITE setValue )
+ Q_PROPERTY( int minValue READ minValue WRITE setMinValue )
+ Q_PROPERTY( int maxValue READ maxValue WRITE setMaxValue )
+public:
+
+ /**
+ * Constructs a horizontal one-dimensional selection widget.
+ */
+ KSelector( QWidget *parent=0, const char *name=0 );
+ /**
+ * Constructs a one-dimensional selection widget with
+ * a given orientation.
+ */
+ KSelector( Orientation o, QWidget *parent = 0L, const char *name = 0L );
+ /*
+ * Destructs the widget.
+ */
+ ~KSelector();
+
+ /**
+ * @return the orientation of the widget.
+ */
+ Orientation orientation() const
+ { return _orientation; }
+
+ /**
+ * @return the rectangle on which subclasses should draw.
+ */
+ QRect contentsRect() const;
+
+ /**
+ * Sets the indent option of the widget to i.
+ * This determines whether a shaded frame is drawn.
+ */
+ void setIndent( bool i )
+ { _indent = i; }
+ /**
+ * @return whether the indent option is set.
+ */
+ bool indent() const
+ { return _indent; }
+
+ /**
+ * Sets the value.
+ */
+ void setValue(int value)
+ { QRangeControl::setValue(value); }
+
+ /**
+ * @returns the value.
+ */
+ int value() const
+ { return QRangeControl::value(); }
+
+ /**
+ * Sets the min value.
+ */
+ void setMinValue(int value)
+ { QRangeControl::setMinValue(value); }
+
+ /**
+ * @return the min value.
+ */
+ int minValue() const
+ { return QRangeControl::minValue(); }
+
+ /**
+ * Sets the max value.
+ */
+ void setMaxValue(int value)
+ { QRangeControl::setMaxValue(value); }
+
+ /**
+ * @return the max value.
+ */
+ int maxValue() const
+ { return QRangeControl::maxValue(); }
+
+signals:
+ /**
+ * This signal is emitted whenever the user chooses a value,
+ * e.g. by clicking with the mouse on the widget.
+ */
+ void valueChanged( int value );
+
+protected:
+ /**
+ * Override this function to draw the contents of the control.
+ * The default implementation does nothing.
+ *
+ * Draw only within contentsRect().
+ */
+ virtual void drawContents( QPainter * );
+ /**
+ * Override this function to draw the cursor which
+ * indicates the current value. This function is
+ * always called twice, once with argument show=false
+ * to clear the old cursor, once with argument show=true
+ * to draw the new one.
+ */
+ virtual void drawArrow( QPainter *painter, bool show, const QPoint &pos );
+
+ virtual void valueChange();
+ virtual void paintEvent( QPaintEvent * );
+ virtual void mousePressEvent( QMouseEvent *e );
+ virtual void mouseMoveEvent( QMouseEvent *e );
+ virtual void wheelEvent( QWheelEvent * );
+
+private:
+ QPoint calcArrowPos( int val );
+ void moveArrow( const QPoint &pos );
+
+ Orientation _orientation;
+ bool _indent;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KSelectorPrivate;
+ KSelectorPrivate *d;
+};
+
+
+/**
+ * The KGradientSelector widget allows the user to choose
+ * from a one-dimensional range of colors which is given as a
+ * gradient between two colors provided by the programmer.
+ *
+ * \image html kgradientselector.png "KDE Gradient Selector Widget"
+ *
+ **/
+class KDEUI_EXPORT KGradientSelector : public KSelector
+{
+ Q_OBJECT
+
+ Q_PROPERTY( QColor firstColor READ firstColor WRITE setFirstColor )
+ Q_PROPERTY( QColor secondColor READ secondColor WRITE setSecondColor )
+ Q_PROPERTY( QString firstText READ firstText WRITE setFirstText )
+ Q_PROPERTY( QString secondText READ secondText WRITE setSecondText )
+
+public:
+ /**
+ * Constructs a horizontal color selector which
+ * contains a gradient between white and black.
+ */
+ KGradientSelector( QWidget *parent=0, const char *name=0 );
+ /**
+ * Constructs a colors selector with orientation o which
+ * contains a gradient between white and black.
+ */
+ KGradientSelector( Orientation o, QWidget *parent=0, const char *name=0 );
+ /**
+ * Destructs the widget.
+ */
+ ~KGradientSelector();
+ /**
+ * Sets the two colors which span the gradient.
+ */
+ void setColors( const QColor &col1, const QColor &col2 )
+ { color1 = col1; color2 = col2; update();}
+ void setText( const QString &t1, const QString &t2 )
+ { text1 = t1; text2 = t2; update(); }
+
+ /**
+ * Set each color on its own.
+ */
+ void setFirstColor( const QColor &col )
+ { color1 = col; update(); }
+ void setSecondColor( const QColor &col )
+ { color2 = col; update(); }
+
+ /**
+ * Set each description on its own
+ */
+ void setFirstText( const QString &t )
+ { text1 = t; update(); }
+ void setSecondText( const QString &t )
+ { text2 = t; update(); }
+
+ const QColor firstColor() const
+ { return color1; }
+ const QColor secondColor() const
+ { return color2; }
+
+ const QString firstText() const
+ { return text1; }
+ const QString secondText() const
+ { return text2; }
+
+protected:
+
+ virtual void drawContents( QPainter * );
+ virtual QSize minimumSize() const
+ { return sizeHint(); }
+
+private:
+ void init();
+ QColor color1;
+ QColor color2;
+ QString text1;
+ QString text2;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KGradientSelectorPrivate;
+ KGradientSelectorPrivate *d;
+};
+
+
+#endif // __KSELECT_H__
+
diff --git a/kdeui/kseparator.cpp b/kdeui/kseparator.cpp
new file mode 100644
index 000000000..a0c636f4c
--- /dev/null
+++ b/kdeui/kseparator.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 1997 Michael Roth <mroth@wirlweb.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <qstyle.h>
+
+#include <kdebug.h>
+#include <kapplication.h>
+
+#include "kseparator.moc"
+
+
+KSeparator::KSeparator(QWidget* parent, const char* name, WFlags f)
+ : QFrame(parent, name, f)
+{
+ setLineWidth(1);
+ setMidLineWidth(0);
+ setOrientation( HLine );
+}
+
+
+
+KSeparator::KSeparator(int orientation, QWidget* parent, const char* name, WFlags f)
+ : QFrame(parent, name, f)
+{
+ setLineWidth(1);
+ setMidLineWidth(0);
+ setOrientation( orientation );
+}
+
+
+
+void KSeparator::setOrientation(int orientation)
+{
+ switch(orientation)
+ {
+ case Vertical:
+ case VLine:
+ setFrameStyle( QFrame::VLine | QFrame::Sunken );
+ setMinimumSize(2, 0);
+ break;
+
+ default:
+ kdWarning() << "KSeparator::setOrientation(): invalid orientation, using default orientation HLine" << endl;
+
+ case Horizontal:
+ case HLine:
+ setFrameStyle( QFrame::HLine | QFrame::Sunken );
+ setMinimumSize(0, 2);
+ break;
+ }
+}
+
+
+
+int KSeparator::orientation() const
+{
+ if ( frameStyle() & VLine )
+ return VLine;
+
+ if ( frameStyle() & HLine )
+ return HLine;
+
+ return 0;
+}
+
+void KSeparator::drawFrame(QPainter *p)
+{
+ QPoint p1, p2;
+ QRect r = frameRect();
+ const QColorGroup & g = colorGroup();
+
+ if ( frameStyle() & HLine ) {
+ p1 = QPoint( r.x(), r.height()/2 );
+ p2 = QPoint( r.x()+r.width(), p1.y() );
+ }
+ else {
+ p1 = QPoint( r.x()+r.width()/2, 0 );
+ p2 = QPoint( p1.x(), r.height() );
+ }
+
+ QStyleOption opt( lineWidth(), midLineWidth() );
+ style().drawPrimitive( QStyle::PE_Separator, p, QRect( p1, p2 ), g,
+ QStyle::Style_Sunken, opt );
+}
+
+
+QSize KSeparator::sizeHint() const
+{
+ if ( frameStyle() & VLine )
+ return QSize(2, 0);
+
+ if ( frameStyle() & HLine )
+ return QSize(0, 2);
+
+ return QSize(-1, -1);
+}
+
+void KSeparator::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
diff --git a/kdeui/kseparator.h b/kdeui/kseparator.h
new file mode 100644
index 000000000..56def3eda
--- /dev/null
+++ b/kdeui/kseparator.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 1997 Michael Roth <mroth@wirlweb.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef __KSEPARATOR_H__
+#define __KSEPARATOR_H__
+
+#include <qframe.h>
+
+#include <kdelibs_export.h>
+
+/**
+ * Standard horizontal or vertical separator.
+ *
+ * @author Michael Roth <mroth@wirlweb.de>
+ * @version $Id$
+*/
+class KDEUI_EXPORT KSeparator : public QFrame
+{
+ Q_OBJECT
+ Q_PROPERTY( int orientation READ orientation WRITE setOrientation )
+ public:
+ /**
+ * Constructor.
+ * @param parent parent object.
+ * @param name name of the new object.
+ * @param f extra QWidget flags.
+ **/
+ KSeparator(QWidget* parent=0, const char* name=0, WFlags f=0);
+
+ /**
+ * Constructor.
+ * @param orientation Set the orientation of the separator.
+ * Possible values are HLine or Horizontal and VLine or Vertical.
+ * @param parent parent object.
+ * @param name name of the new object.
+ * @param f extra QWidget flags.
+ **/
+ KSeparator(int orientation, QWidget* parent=0, const char* name=0,
+ WFlags f=0);
+
+ /**
+ * Returns the orientation of the separator.
+ * @return int Possible values are VLine and HLine.
+ **/
+ int orientation() const;
+
+ /**
+ * Set the orientation of the separator to @p orient
+ *
+ * @param orient Possible values are VLine and HLine.
+ */
+ void setOrientation(int orient);
+
+ /**
+ * The recommended height (width) for a horizontal (vertical) separator.
+ **/
+ virtual QSize sizeHint() const;
+
+protected:
+ /**
+ * @param p pointer to painter
+ */
+ virtual void drawFrame( QPainter *p );
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KSeparatorPrivate* d;
+};
+
+
+#endif // __KSEPARATOR_H__
diff --git a/kdeui/ksharedpixmap.cpp b/kdeui/ksharedpixmap.cpp
new file mode 100644
index 000000000..8af8d7277
--- /dev/null
+++ b/kdeui/ksharedpixmap.cpp
@@ -0,0 +1,228 @@
+/* vi: ts=8 sts=4 sw=4
+ *
+ *
+ * This file is part of the KDE libraries.
+ * Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * Shared pixmap client for KDE.
+ */
+#include "config.h"
+
+#include <qrect.h>
+#include <qsize.h>
+#include <qstring.h>
+#include <qpixmap.h>
+#include <qwindowdefs.h>
+#include <qwidget.h>
+
+#ifdef Q_WS_X11
+
+#include <kapplication.h>
+#include <krootprop.h>
+#include <ksharedpixmap.h>
+#include <kdebug.h>
+#include <stdlib.h> // for abs
+
+#include <X11/Xlib.h>
+
+// Make sure to include all this X-based shit before we clean up the mess.
+// Needed for --enable-final. Not needed by this file itself!
+#include <X11/Xutil.h>
+#ifdef HAVE_MITSHM
+#include <X11/extensions/XShm.h>
+#endif
+
+#include <netwm.h>
+
+// Clean up the mess
+
+#undef Bool
+#undef Above
+#undef Below
+#undef KeyPress
+#undef KeyRelease
+#undef FocusOut
+
+/**
+ * KSharedPixmap
+ */
+
+class KSharedPixmapPrivate
+{
+public:
+ Atom pixmap;
+ Atom target;
+ Atom selection;
+ QRect rect;
+};
+
+KSharedPixmap::KSharedPixmap()
+ : QWidget(0L, "shpixmap comm window")
+{
+ d = new KSharedPixmapPrivate;
+ init();
+}
+
+
+KSharedPixmap::~KSharedPixmap()
+{
+ delete d;
+}
+
+
+void KSharedPixmap::init()
+{
+ d->pixmap = XInternAtom(qt_xdisplay(), "PIXMAP", false);
+ QCString atom;
+ atom.sprintf("target prop for window %lx", static_cast<unsigned long int>(winId()));
+ d->target = XInternAtom(qt_xdisplay(), atom.data(), false);
+ d->selection = None;
+}
+
+
+bool KSharedPixmap::isAvailable(const QString & name) const
+{
+ QString str = QString("KDESHPIXMAP:%1").arg(name);
+ Atom sel = XInternAtom(qt_xdisplay(), str.latin1(), true);
+ if (sel == None)
+ return false;
+ return XGetSelectionOwner(qt_xdisplay(), sel) != None;
+}
+
+
+bool KSharedPixmap::loadFromShared(const QString & name, const QRect & rect)
+{
+ d->rect = rect;
+ if (d->selection != None)
+ // already active
+ return false;
+
+ QPixmap::resize(0, 0); // invalidate
+
+ QString str = QString("KDESHPIXMAP:%1").arg(name);
+ d->selection = XInternAtom(qt_xdisplay(), str.latin1(), true);
+ if (d->selection == None)
+ return false;
+ if (XGetSelectionOwner(qt_xdisplay(), d->selection) == None)
+ {
+ d->selection = None;
+ return false;
+ }
+
+ XConvertSelection(qt_xdisplay(), d->selection, d->pixmap, d->target,
+ winId(), CurrentTime);
+ return true;
+}
+
+
+bool KSharedPixmap::x11Event(XEvent *event)
+{
+ if (event->type != SelectionNotify)
+ return false;
+
+ XSelectionEvent *ev = &event->xselection;
+ if (ev->selection != d->selection)
+ return false;
+
+ if ((ev->target != d->pixmap) || (ev->property == None))
+ {
+ kdWarning(270) << k_funcinfo << "illegal selection notify event.\n";
+ d->selection = None;
+ emit done(false);
+ return true;
+ }
+
+ // Read pixmap handle from ev->property
+
+ int dummy, format;
+ unsigned long nitems, ldummy;
+ unsigned char *pixmap_id = 0;
+ Atom type;
+
+ XGetWindowProperty(qt_xdisplay(), winId(), ev->property, 0, 1, false,
+ d->pixmap, &type, &format, &nitems, &ldummy,
+ &pixmap_id);
+
+ if (nitems != 1 || !pixmap_id)
+ {
+ kdWarning(270) << k_funcinfo << "could not read property, nitems = " << nitems << "\n";
+ emit done(false);
+ return true;
+ }
+
+ Window root;
+ unsigned int width, height, udummy;
+ void *drawable_id = (void *) pixmap_id;
+ Drawable pixmap = *(Drawable*) drawable_id;
+
+ Status status = XGetGeometry(qt_xdisplay(), pixmap, &root, &dummy, &dummy, &width, &height, &udummy, &udummy);
+
+ if (status == BadDrawable)
+ return false;
+
+ if (d->rect.isEmpty())
+ {
+ QPixmap::resize(width, height);
+ XCopyArea(qt_xdisplay(), pixmap, ((KPixmap*)this)->handle(), qt_xget_temp_gc(qt_xscreen(), false),
+ 0, 0, width, height, 0, 0);
+
+ XFree(pixmap_id);
+ XDeleteProperty(qt_xdisplay(), winId(), ev->property);
+ d->selection = None;
+ emit done(true);
+ return true;
+ }
+
+ // Do some more processing here: Generate a tile that can be used as a
+ // background tile for the rectangle "rect".
+
+ //Check for origin off screen
+ QPoint origin(0, 0);
+ if( d->rect.topLeft().x() < 0 || d->rect.topLeft().y() < 0 ) {
+ //Save the offset and relocate the rect corners
+ QPoint tl = d->rect.topLeft();
+ QPoint br = d->rect.bottomRight();
+ if( tl.x() < 0 ) {
+ origin.setX( abs( tl.x() ) );
+ tl.setX( 0 );
+ }
+ if( tl.y() < 0 ) {
+ origin.setY( abs( tl.y() ) );
+ tl.setY( 0 );
+ }
+ QRect adjustedRect( tl, br );
+ d->rect = adjustedRect;
+ }
+
+ unsigned w = d->rect.width(), h = d->rect.height();
+ unsigned tw = QMIN(width, w), th = QMIN(height, h);
+ unsigned xa = d->rect.x() % width, ya = d->rect.y() % height;
+ unsigned t1w = QMIN(width-xa,tw), t1h = QMIN(height-ya,th);
+
+ QPixmap::resize( tw+origin.x(), th+origin.y() );
+
+ XCopyArea(qt_xdisplay(), pixmap, ((KPixmap*)this)->handle(), qt_xget_temp_gc(qt_xscreen(), false),
+ xa, ya, t1w+origin.x(), t1h+origin.y(), origin.x(), origin.y() );
+ XCopyArea(qt_xdisplay(), pixmap, ((KPixmap*)this)->handle(), qt_xget_temp_gc(qt_xscreen(), false),
+ 0, ya, tw-t1w, t1h, t1w, 0);
+ XCopyArea(qt_xdisplay(), pixmap, ((KPixmap*)this)->handle(), qt_xget_temp_gc(qt_xscreen(), false),
+ xa, 0, t1w, th-t1h, 0, t1h);
+ XCopyArea(qt_xdisplay(), pixmap, ((KPixmap*)this)->handle(), qt_xget_temp_gc(qt_xscreen(), false),
+ 0, 0, tw-t1w, th-t1h, t1w, t1h);
+
+ XFree(pixmap_id);
+
+ d->selection = None;
+ XDeleteProperty(qt_xdisplay(), winId(), ev->property);
+ emit done(true);
+ return true;
+}
+
+
+#include "ksharedpixmap.moc"
+#endif
diff --git a/kdeui/ksharedpixmap.h b/kdeui/ksharedpixmap.h
new file mode 100644
index 000000000..49e5da667
--- /dev/null
+++ b/kdeui/ksharedpixmap.h
@@ -0,0 +1,115 @@
+/* vi: ts=8 sts=4 sw=4
+ *
+ * $Id$
+ *
+ * This file is part of the KDE libraries.
+ * Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef __KSharedPixmap_h_Included__
+#define __KSharedPixmap_h_Included__
+
+#include <kpixmap.h>
+
+#ifdef Q_WS_X11
+
+#include <qstring.h>
+#include <qpixmap.h>
+#include <qwidget.h>
+
+class KSharedPixmapPrivate;
+
+/**
+ * Shared pixmap client.
+ *
+ * A shared pixmap is a pixmap that resides on the X server, is referenced
+ * by a global id string, and can be accessed by all X clients.
+ *
+ * This class is a client class to shared pixmaps in KDE. You can use it
+ * to copy (a part of) a shared pixmap into. KSharedPixmap inherits KPixmap
+ * for that purpose.
+ *
+ * The server part of shared pixmaps is not implemented here.
+ * That part is provided by KPixmapServer, in the source file:
+ * kdebase/kdesktop/pixmapserver.cc.
+ *
+ * An example: copy from a shared pixmap:
+ * \code
+ * KSharedPixmap *pm = new KSharedPixmap;
+ * connect(pm, SIGNAL(done(bool)), SLOT(slotDone(bool)));
+ * pm->loadFromShared("My Pixmap");
+ * \endcode
+ *
+ * @author Geert Jansen <jansen@kde.org>
+ * @version $Id$
+ *
+ */
+class KDEUI_EXPORT KSharedPixmap:
+ public QWidget,
+ public KPixmap
+{
+ Q_OBJECT
+
+public:
+
+ /**
+ * Construct an empty pixmap.
+ */
+ KSharedPixmap();
+
+ /**
+ * Destroys the pixmap.
+ */
+ ~KSharedPixmap();
+
+ /**
+ * Load from a shared pixmap reference. The signal done() is emitted
+ * when the operation has finished.
+ *
+ * @param name The shared pixmap name.
+ * @param rect If you pass a nonzero rectangle, a tile is generated which
+ * is able to fill up the specified rectangle completely. This is solely
+ * for optimization: in some cases the tile will be much smaller than the
+ * original pixmap. It reflects KSharedPixmap's original use: sharing
+ * of the desktop background to achieve pseudo transparency.
+ * @return True if the shared pixmap exists and loading has started
+ * successfully, false otherwise.
+ */
+ bool loadFromShared(const QString & name, const QRect & rect=QRect());
+
+ /**
+ * Check whether a shared pixmap is available.
+ *
+ * @param name The shared pixmap name.
+ * @return True if the shared pixmap is available, false otherwise.
+ */
+ bool isAvailable(const QString & name) const;
+
+signals:
+ /**
+ * This signal is raised when a pixmap load operation has finished.
+ *
+ * @param success True if successful, false otherwise.
+ */
+ void done(bool success);
+
+protected:
+ bool x11Event(XEvent *);
+
+private:
+ bool copy(const QString & id, const QRect & rect);
+ void init();
+
+ KSharedPixmapPrivate *d;
+};
+#else // WIN32, Qt Embedded
+// Let's simply assume KPixmap will do for now. Yes, I know that's broken.
+#define KSharedPixmap KPixmap
+#endif
+
+#endif
diff --git a/kdeui/kshortcutdialog.cpp b/kdeui/kshortcutdialog.cpp
new file mode 100644
index 000000000..05a6c705f
--- /dev/null
+++ b/kdeui/kshortcutdialog.cpp
@@ -0,0 +1,529 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2002,2003 Ellis Whitehead <ellis@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kshortcutdialog.h"
+
+#include <qvariant.h>
+
+#ifdef Q_WS_X11
+ #define XK_XKB_KEYS
+ #define XK_MISCELLANY
+ #include <X11/Xlib.h> // For x11Event()
+ #include <X11/keysymdef.h> // For XK_...
+
+ #ifdef KeyPress
+ const int XKeyPress = KeyPress;
+ const int XKeyRelease = KeyRelease;
+ const int XFocusOut = FocusOut;
+ const int XFocusIn = FocusIn;
+ #undef KeyRelease
+ #undef KeyPress
+ #undef FocusOut
+ #undef FocusIn
+ #endif
+#elif defined(Q_WS_WIN)
+# include <kkeyserver.h>
+#endif
+
+#include <kshortcutdialog_simple.h>
+#include <kshortcutdialog_advanced.h>
+
+#include <qbuttongroup.h>
+#include <qcheckbox.h>
+#include <qframe.h>
+#include <qlayout.h>
+#include <qradiobutton.h>
+#include <qtimer.h>
+#include <qvbox.h>
+
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kiconloader.h>
+#include <kkeynative.h>
+#include <klocale.h>
+#include <kstdguiitem.h>
+#include <kpushbutton.h>
+
+bool KShortcutDialog::s_showMore = false;
+
+KShortcutDialog::KShortcutDialog( const KShortcut& shortcut, bool bQtShortcut, QWidget* parent, const char* name )
+: KDialogBase( parent, name, true, i18n("Configure Shortcut"),
+ KDialogBase::Details|KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Cancel, true )
+{
+ setButtonText(Details, i18n("Advanced"));
+ m_stack = new QVBox(this);
+ m_stack->setMinimumWidth(360);
+ m_stack->setSpacing(0);
+ m_stack->setMargin(0);
+ setMainWidget(m_stack);
+
+ m_simple = new KShortcutDialogSimple(m_stack);
+
+ m_adv = new KShortcutDialogAdvanced(m_stack);
+ m_adv->hide();
+
+ m_bQtShortcut = bQtShortcut;
+
+ m_bGrab = false;
+ m_iSeq = 0;
+ m_iKey = 0;
+ m_ptxtCurrent = 0;
+ m_bRecording = false;
+ m_mod = 0;
+
+ m_simple->m_btnClearShortcut->setPixmap( SmallIcon( "locationbar_erase" ) );
+ m_adv->m_btnClearPrimary->setPixmap( SmallIcon( "locationbar_erase" ) );
+ m_adv->m_btnClearAlternate->setPixmap( SmallIcon( "locationbar_erase" ) );
+ connect(m_simple->m_btnClearShortcut, SIGNAL(clicked()),
+ this, SLOT(slotClearShortcut()));
+ connect(m_adv->m_btnClearPrimary, SIGNAL(clicked()),
+ this, SLOT(slotClearPrimary()));
+ connect(m_adv->m_btnClearAlternate, SIGNAL(clicked()),
+ this, SLOT(slotClearAlternate()));
+
+ connect(m_adv->m_txtPrimary, SIGNAL(clicked()),
+ m_adv->m_btnPrimary, SLOT(animateClick()));
+ connect(m_adv->m_txtAlternate, SIGNAL(clicked()),
+ m_adv->m_btnAlternate, SLOT(animateClick()));
+ connect(m_adv->m_btnPrimary, SIGNAL(clicked()),
+ this, SLOT(slotSelectPrimary()));
+ connect(m_adv->m_btnAlternate, SIGNAL(clicked()),
+ this, SLOT(slotSelectAlternate()));
+
+ KGuiItem ok = KStdGuiItem::ok();
+ ok.setText( i18n( "OK" ) );
+ setButtonOK( ok );
+
+ KGuiItem cancel = KStdGuiItem::cancel();
+ cancel.setText( i18n( "Cancel" ) );
+ setButtonCancel( cancel );
+
+ setShortcut( shortcut );
+ resize( 0, 0 );
+
+ s_showMore = KConfigGroup(KGlobal::config(), "General").readBoolEntry("ShowAlternativeShortcutConfig", s_showMore);
+ updateDetails();
+
+ #ifdef Q_WS_X11
+ kapp->installX11EventFilter( this ); // Allow button to capture X Key Events.
+ #endif
+}
+
+KShortcutDialog::~KShortcutDialog()
+{
+ KConfigGroup group(KGlobal::config(), "General");
+ group.writeEntry("ShowAlternativeShortcutConfig", s_showMore);
+}
+
+void KShortcutDialog::setShortcut( const KShortcut & shortcut )
+{
+ m_shortcut = shortcut;
+ updateShortcutDisplay();
+}
+
+void KShortcutDialog::updateShortcutDisplay()
+{
+ QString s[2] = { m_shortcut.seq(0).toString(), m_shortcut.seq(1).toString() };
+
+ if( m_bRecording ) {
+ m_ptxtCurrent->setDefault( true );
+ m_ptxtCurrent->setFocus();
+
+ // Display modifiers for the first key in the KKeySequence
+ if( m_iKey == 0 ) {
+ if( m_mod ) {
+ QString keyModStr;
+ if( m_mod & KKey::WIN ) keyModStr += KKey::modFlagLabel(KKey::WIN) + "+";
+ if( m_mod & KKey::ALT ) keyModStr += KKey::modFlagLabel(KKey::ALT) + "+";
+ if( m_mod & KKey::CTRL ) keyModStr += KKey::modFlagLabel(KKey::CTRL) + "+";
+ if( m_mod & KKey::SHIFT ) keyModStr += KKey::modFlagLabel(KKey::SHIFT) + "+";
+ s[m_iSeq] = keyModStr;
+ }
+ }
+ // When in the middle of entering multi-key shortcuts,
+ // add a "," to the end of the displayed shortcut.
+ else
+ s[m_iSeq] += ",";
+ }
+ else {
+ m_adv->m_txtPrimary->setDefault( false );
+ m_adv->m_txtAlternate->setDefault( false );
+ this->setFocus();
+ }
+
+ s[0].replace('&', QString::fromLatin1("&&"));
+ s[1].replace('&', QString::fromLatin1("&&"));
+
+ m_simple->m_txtShortcut->setText( s[0] );
+ m_adv->m_txtPrimary->setText( s[0] );
+ m_adv->m_txtAlternate->setText( s[1] );
+
+ // Determine the enable state of the 'Less' button
+ bool bLessOk;
+ // If there is no shortcut defined,
+ if( m_shortcut.count() == 0 )
+ bLessOk = true;
+ // If there is a single shortcut defined, and it is not a multi-key shortcut,
+ else if( m_shortcut.count() == 1 && m_shortcut.seq(0).count() <= 1 )
+ bLessOk = true;
+ // Otherwise, we have an alternate shortcut or multi-key shortcut(s).
+ else
+ bLessOk = false;
+ enableButton(Details, bLessOk);
+}
+
+void KShortcutDialog::slotDetails()
+{
+ s_showMore = (m_adv->isHidden());
+ updateDetails();
+}
+
+void KShortcutDialog::updateDetails()
+{
+ bool showAdvanced = s_showMore || (m_shortcut.count() > 1);
+ setDetails(showAdvanced);
+ m_bRecording = false;
+ m_iSeq = 0;
+ m_iKey = 0;
+
+ if (showAdvanced)
+ {
+ m_simple->hide();
+ m_adv->show();
+ m_adv->m_btnPrimary->setChecked( true );
+ slotSelectPrimary();
+ }
+ else
+ {
+ m_ptxtCurrent = m_simple->m_txtShortcut;
+ m_adv->hide();
+ m_simple->show();
+ m_simple->m_txtShortcut->setDefault( true );
+ m_simple->m_txtShortcut->setFocus();
+ m_adv->m_btnMultiKey->setChecked( false );
+ }
+ kapp->processEvents();
+ adjustSize();
+}
+
+void KShortcutDialog::slotSelectPrimary()
+{
+ m_bRecording = false;
+ m_iSeq = 0;
+ m_iKey = 0;
+ m_ptxtCurrent = m_adv->m_txtPrimary;
+ m_ptxtCurrent->setDefault(true);
+ m_ptxtCurrent->setFocus();
+ updateShortcutDisplay();
+}
+
+void KShortcutDialog::slotSelectAlternate()
+{
+ m_bRecording = false;
+ m_iSeq = 1;
+ m_iKey = 0;
+ m_ptxtCurrent = m_adv->m_txtAlternate;
+ m_ptxtCurrent->setDefault(true);
+ m_ptxtCurrent->setFocus();
+ updateShortcutDisplay();
+}
+
+void KShortcutDialog::slotClearShortcut()
+{
+ m_shortcut.setSeq( 0, KKeySequence() );
+ updateShortcutDisplay();
+}
+
+void KShortcutDialog::slotClearPrimary()
+{
+ m_shortcut.setSeq( 0, KKeySequence() );
+ m_adv->m_btnPrimary->setChecked( true );
+ slotSelectPrimary();
+}
+
+void KShortcutDialog::slotClearAlternate()
+{
+ if( m_shortcut.count() == 2 )
+ m_shortcut.init( m_shortcut.seq(0) );
+ m_adv->m_btnAlternate->setChecked( true );
+ slotSelectAlternate();
+}
+
+void KShortcutDialog::slotMultiKeyMode( bool bOn )
+{
+ // If turning off multi-key mode during a recording,
+ if( !bOn && m_bRecording ) {
+ m_bRecording = false;
+ m_iKey = 0;
+ updateShortcutDisplay();
+ }
+}
+
+#ifdef Q_WS_X11
+/* we don't use the generic Qt code on X11 because it allows us
+ to grab the keyboard so that all keypresses are seen
+ */
+bool KShortcutDialog::x11Event( XEvent *pEvent )
+{
+ switch( pEvent->type ) {
+ case XKeyPress:
+ x11KeyPressEvent( pEvent );
+ return true;
+ case XKeyRelease:
+ x11KeyReleaseEvent( pEvent );
+ return true;
+ case XFocusIn:
+ if (!m_bGrab) {
+ //kdDebug(125) << "FocusIn and Grab!" << endl;
+ grabKeyboard();
+ m_bGrab = true;
+ }
+ //else
+ // kdDebug(125) << "FocusIn" << endl;
+ break;
+ case XFocusOut:
+ if (m_bGrab) {
+ //kdDebug(125) << "FocusOut and Ungrab!" << endl;
+ releaseKeyboard();
+ m_bGrab = false;
+ }
+ //else
+ // kdDebug(125) << "FocusOut" << endl;
+ break;
+ default:
+ //kdDebug(125) << "x11Event->type = " << pEvent->type << endl;
+ break;
+ }
+ return KDialogBase::x11Event( pEvent );
+}
+
+static uint getModsFromModX( uint keyModX )
+{
+ uint mod = 0;
+ if( keyModX & KKeyNative::modX(KKey::SHIFT) ) mod += KKey::SHIFT;
+ if( keyModX & KKeyNative::modX(KKey::CTRL) ) mod += KKey::CTRL;
+ if( keyModX & KKeyNative::modX(KKey::ALT) ) mod += KKey::ALT;
+ if( keyModX & KKeyNative::modX(KKey::WIN) ) mod += KKey::WIN;
+ return mod;
+}
+
+static bool convertSymXToMod( uint keySymX, uint* pmod )
+{
+ switch( keySymX ) {
+ // Don't allow setting a modifier key as an accelerator.
+ // Also, don't release the focus yet. We'll wait until
+ // we get a 'normal' key.
+ case XK_Shift_L: case XK_Shift_R: *pmod = KKey::SHIFT; break;
+ case XK_Control_L: case XK_Control_R: *pmod = KKey::CTRL; break;
+ case XK_Alt_L: case XK_Alt_R: *pmod = KKey::ALT; break;
+ // FIXME: check whether the Meta or Super key are for the Win modifier
+ case XK_Meta_L: case XK_Meta_R:
+ case XK_Super_L: case XK_Super_R: *pmod = KKey::WIN; break;
+ case XK_Hyper_L: case XK_Hyper_R:
+ case XK_Mode_switch:
+ case XK_Num_Lock:
+ case XK_Caps_Lock:
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+void KShortcutDialog::x11KeyPressEvent( XEvent* pEvent )
+{
+ KKeyNative keyNative( pEvent );
+ uint keyModX = keyNative.mod();
+ uint keySymX = keyNative.sym();
+
+ m_mod = getModsFromModX( keyModX );
+
+ if( keySymX ) {
+ m_bRecording = true;
+
+ uint mod = 0;
+ if( convertSymXToMod( keySymX, &mod ) ) {
+ if( mod )
+ m_mod |= mod;
+ }
+ else
+ keyPressed( KKey(keyNative) );
+ }
+ updateShortcutDisplay();
+}
+
+void KShortcutDialog::x11KeyReleaseEvent( XEvent* pEvent )
+{
+ // We're only interested in the release of modifier keys,
+ // and then only when it's for the first key in a sequence.
+ if( m_bRecording && m_iKey == 0 ) {
+ KKeyNative keyNative( pEvent );
+ uint keyModX = keyNative.mod();
+ uint keySymX = keyNative.sym();
+
+ m_mod = getModsFromModX( keyModX );
+
+ uint mod = 0;
+ if( convertSymXToMod( keySymX, &mod ) && mod ) {
+ m_mod &= ~mod;
+ if( !m_mod )
+ m_bRecording = false;
+ }
+ updateShortcutDisplay();
+ }
+}
+#elif defined(Q_WS_WIN)
+void KShortcutDialog::keyPressEvent( QKeyEvent * e )
+{
+ kdDebug() << e->text() << " " << (int)e->text()[0].latin1()<< " " << (int)e->ascii() << endl;
+ //if key is a letter, it must be stored as lowercase
+ int keyQt = QChar( e->key() & 0xff ).isLetter() ?
+ (QChar( e->key() & 0xff ).lower().latin1() | (e->key() & 0xffff00) )
+ : e->key();
+ int modQt = KKeyServer::qtButtonStateToMod( e->state() );
+ KKeyNative keyNative( KKey(keyQt, modQt) );
+ m_mod = keyNative.mod();
+ uint keySym = keyNative.sym();
+
+ switch( keySym ) {
+ case Key_Shift:
+ m_mod |= KKey::SHIFT;
+ m_bRecording = true;
+ break;
+ case Key_Control:
+ m_mod |= KKey::CTRL;
+ m_bRecording = true;
+ break;
+ case Key_Alt:
+ m_mod |= KKey::ALT;
+ m_bRecording = true;
+ break;
+ case Key_Menu:
+ case Key_Meta: //unused
+ break;
+ default:
+ if( keyNative.sym() == Key_Return && m_iKey > 0 ) {
+ accept();
+ return;
+ }
+ //accept
+ if (keyNative.sym()) {
+ KKey key = keyNative;
+ key.simplify();
+ KKeySequence seq;
+ if( m_iKey == 0 )
+ seq = key;
+ else {
+ seq = m_shortcut.seq( m_iSeq );
+ seq.setKey( m_iKey, key );
+ }
+ m_shortcut.setSeq( m_iSeq, seq );
+
+ if(m_adv->m_btnMultiKey->isChecked())
+ m_iKey++;
+
+ m_bRecording = true;
+
+ updateShortcutDisplay();
+
+ if( !m_adv->m_btnMultiKey->isChecked() )
+ QTimer::singleShot(500, this, SLOT(accept()));
+ }
+ return;
+ }
+
+ // If we are editing the first key in the sequence,
+ // display modifier keys which are held down
+ if( m_iKey == 0 ) {
+ updateShortcutDisplay();
+ }
+}
+
+bool KShortcutDialog::event ( QEvent * e )
+{
+ if (e->type()==QEvent::KeyRelease) {
+ int modQt = KKeyServer::qtButtonStateToMod( static_cast<QKeyEvent*>(e)->state() );
+ KKeyNative keyNative( KKey(static_cast<QKeyEvent*>(e)->key(), modQt) );
+ uint keySym = keyNative.sym();
+
+ bool change = true;
+ switch( keySym ) {
+ case Key_Shift:
+ if (m_mod & KKey::SHIFT)
+ m_mod ^= KKey::SHIFT;
+ break;
+ case Key_Control:
+ if (m_mod & KKey::CTRL)
+ m_mod ^= KKey::CTRL;
+ break;
+ case Key_Alt:
+ if (m_mod & KKey::ALT)
+ m_mod ^= KKey::ALT;
+ break;
+ default:
+ change = false;
+ }
+ if (change)
+ updateShortcutDisplay();
+ }
+ return KDialogBase::event(e);
+}
+#endif
+
+void KShortcutDialog::keyPressed( KKey key )
+{
+ kdDebug(125) << "keyPressed: " << key.toString() << endl;
+
+ key.simplify();
+ if( m_bQtShortcut ) {
+ key = key.keyCodeQt();
+ if( key.isNull() ) {
+ // TODO: message box about key not able to be used as application shortcut
+ }
+ }
+
+ KKeySequence seq;
+ if( m_iKey == 0 )
+ seq = key;
+ else {
+ // Remove modifiers
+ key.init( key.sym(), 0 );
+ seq = m_shortcut.seq( m_iSeq );
+ seq.setKey( m_iKey, key );
+ }
+
+ m_shortcut.setSeq( m_iSeq, seq );
+
+ m_mod = 0;
+ if( m_adv->m_btnMultiKey->isChecked() && m_iKey < KKeySequence::MAX_KEYS - 1 )
+ m_iKey++;
+ else {
+ m_iKey = 0;
+ m_bRecording = false;
+ }
+
+ updateShortcutDisplay();
+
+ if( !m_adv->m_btnMultiKey->isChecked() )
+ QTimer::singleShot(500, this, SLOT(accept()));
+}
+
+#include "kshortcutdialog.moc"
diff --git a/kdeui/kshortcutdialog.h b/kdeui/kshortcutdialog.h
new file mode 100644
index 000000000..e054e356b
--- /dev/null
+++ b/kdeui/kshortcutdialog.h
@@ -0,0 +1,96 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2002,2003 Ellis Whitehead <ellis@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _KSHORTCUTDIALOG_H_
+#define _KSHORTCUTDIALOG_H_
+
+#include "kdialogbase.h"
+#include "kshortcut.h"
+
+class QVBox;
+class KPushButton;
+class KShortcutDialogSimple;
+class KShortcutDialogAdvanced;
+
+/**
+ * @short Dialog for configuring a shortcut.
+ *
+ * This dialog allows configuring a single KShortcut. KKeyDialog
+ * should be usually used instead.
+ *
+ * @internal
+ * @see KKeyDialog
+ * @since 3.4
+ */
+class KDEUI_EXPORT KShortcutDialog : public KDialogBase
+{
+ Q_OBJECT
+public:
+ KShortcutDialog( const KShortcut& shortcut, bool bQtShortcut, QWidget* parent = 0, const char* name = 0 );
+ ~KShortcutDialog();
+
+ void setShortcut( const KShortcut & shortcut );
+ const KShortcut& shortcut() const { return m_shortcut; }
+
+private:
+ // true if qt shortcut, false if native shortcut
+ bool m_bQtShortcut;
+
+ KShortcut m_shortcut;
+ bool m_bGrab;
+ KPushButton* m_ptxtCurrent;
+ uint m_iSeq;
+ uint m_iKey;
+ bool m_bRecording;
+ uint m_mod;
+ KShortcutDialogSimple *m_simple;
+ KShortcutDialogAdvanced *m_adv;
+ QVBox *m_stack;
+
+ void updateShortcutDisplay();
+ //void displayMods();
+ void keyPressed( KKey key );
+ void updateDetails();
+
+ #ifdef Q_WS_X11
+ virtual bool x11Event( XEvent *pEvent );
+ //void x11EventKeyPress( XEvent *pEvent );
+ void x11KeyPressEvent( XEvent* pEvent );
+ void x11KeyReleaseEvent( XEvent* pEvent );
+ #endif
+ #ifdef Q_WS_WIN
+ virtual void keyPressEvent( QKeyEvent * e );
+ virtual bool event(QEvent * e);
+ #endif
+
+protected slots:
+ void slotDetails();
+ void slotSelectPrimary();
+ void slotSelectAlternate();
+ void slotClearShortcut();
+ void slotClearPrimary();
+ void slotClearAlternate();
+ void slotMultiKeyMode( bool bOn );
+
+private:
+ class KShortcutDialogPrivate* d;
+ static bool s_showMore;
+};
+
+#endif // _KSHORTCUTDIALOG_H_
diff --git a/kdeui/kshortcutdialog_advanced.ui b/kdeui/kshortcutdialog_advanced.ui
new file mode 100644
index 000000000..9c371523f
--- /dev/null
+++ b/kdeui/kshortcutdialog_advanced.ui
@@ -0,0 +1,254 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>KShortcutDialogAdvanced</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>KShortcutDialogAdvanced</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>359</width>
+ <height>157</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>m_frameMore</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Plain</enum>
+ </property>
+ <property name="title">
+ <string></string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QRadioButton" row="1" column="0">
+ <property name="name">
+ <cstring>m_btnAlternate</cstring>
+ </property>
+ <property name="focusPolicy">
+ <enum>NoFocus</enum>
+ </property>
+ <property name="text">
+ <string>Alternate shortcut:</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="0" column="0">
+ <property name="name">
+ <cstring>m_btnPrimary</cstring>
+ </property>
+ <property name="focusPolicy">
+ <enum>NoFocus</enum>
+ </property>
+ <property name="text">
+ <string>Primary shortcut:</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="2">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>m_txtAlternate</cstring>
+ </property>
+ <property name="paletteBackgroundColor">
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </property>
+ <property name="focusPolicy">
+ <enum>ClickFocus</enum>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ <property name="default">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="2">
+ <property name="name">
+ <cstring>layout7</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>m_txtPrimary</cstring>
+ </property>
+ <property name="paletteBackgroundColor">
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </property>
+ <property name="cursor">
+ <cursor>4</cursor>
+ </property>
+ <property name="focusPolicy">
+ <enum>ClickFocus</enum>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>The currently set shortcut or the shortcut you are entering will show up here.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer5</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="QPushButton" row="0" column="1">
+ <property name="name">
+ <cstring>m_btnClearPrimary</cstring>
+ </property>
+ <property name="text">
+ <string>x</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Clear shortcut</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="1" column="1">
+ <property name="name">
+ <cstring>m_btnClearAlternate</cstring>
+ </property>
+ <property name="text">
+ <string>x</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Clear shortcut</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="0">
+ <property name="name">
+ <cstring>m_btnMultiKey</cstring>
+ </property>
+ <property name="focusPolicy">
+ <enum>NoFocus</enum>
+ </property>
+ <property name="text">
+ <string>Multi-key mode</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Enable the entry of multi-key shortcuts</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select this checkbox to enable the entry of multi-key shortcuts. A multi-key shortcut consists of a sequence of up to 4 keys. For example, you could assign "Ctrl+F,B" to Font-Bold and "Ctrl+F,U" to Font-Underline.</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>m_txtPrimary</sender>
+ <signal>clicked()</signal>
+ <receiver>m_btnPrimary</receiver>
+ <slot>animateClick()</slot>
+ </connection>
+ <connection>
+ <sender>m_txtAlternate</sender>
+ <signal>clicked()</signal>
+ <receiver>m_btnAlternate</receiver>
+ <slot>animateClick()</slot>
+ </connection>
+</connections>
+<includes>
+ <include location="global" impldecl="in declaration">kshortcut.h</include>
+ <include location="global" impldecl="in declaration">kdialog.h</include>
+ <include location="global" impldecl="in implementation">kpushbutton.h</include>
+</includes>
+<forwards>
+ <forward>class KShortcut</forward>
+</forwards>
+<layoutdefaults spacing="6" margin="11"/>
+<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
+<includehints>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kdeui/kshortcutdialog_simple.ui b/kdeui/kshortcutdialog_simple.ui
new file mode 100644
index 000000000..a7fb651ff
--- /dev/null
+++ b/kdeui/kshortcutdialog_simple.ui
@@ -0,0 +1,120 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>KShortcutDialogSimple</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>KShortcutDialogSimple</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>177</width>
+ <height>36</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Shortcut:</string>
+ </property>
+ </widget>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KPushButton" row="0" column="3">
+ <property name="name">
+ <cstring>m_txtShortcut</cstring>
+ </property>
+ <property name="paletteBackgroundColor">
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </property>
+ <property name="cursor">
+ <cursor>4</cursor>
+ </property>
+ <property name="focusPolicy">
+ <enum>ClickFocus</enum>
+ </property>
+ <property name="text">
+ <string>Alt+Tab</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ <property name="default">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="0" column="2">
+ <property name="name">
+ <cstring>m_btnClearShortcut</cstring>
+ </property>
+ <property name="text">
+ <string>x</string>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Clear shortcut</string>
+ </property>
+ </widget>
+ <spacer row="0" column="4">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<includes>
+ <include location="global" impldecl="in declaration">kshortcut.h</include>
+ <include location="global" impldecl="in declaration">kdialog.h</include>
+ <include location="global" impldecl="in implementation">kpushbutton.h</include>
+</includes>
+<forwards>
+ <forward>class KShortcut</forward>
+</forwards>
+<layoutdefaults spacing="6" margin="11"/>
+<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
+<includehints>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kdeui/kspell.cpp b/kdeui/kspell.cpp
new file mode 100644
index 000000000..e34b819e8
--- /dev/null
+++ b/kdeui/kspell.cpp
@@ -0,0 +1,1577 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 David Sweet <dsweet@kde.org>
+ Copyright (C) 2000-2001 Wolfram Diestel <wolfram@steloj.de>
+ Copyright (C) 2003 Zack Rusin <zack@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdlib.h> // atoi
+
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+
+#include <qregexp.h>
+#include <qtextcodec.h>
+#include <qtimer.h>
+
+#include <kapplication.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include "kspell.h"
+#include "kspelldlg.h"
+#include <kwin.h>
+#include <kprocio.h>
+
+#define MAXLINELENGTH 10000
+#undef IGNORE //fix possible conflict
+
+enum {
+ GOOD= 0,
+ IGNORE= 1,
+ REPLACE= 2,
+ MISTAKE= 3
+};
+
+enum checkMethod { Method1 = 0, Method2 };
+
+struct BufferedWord
+{
+ checkMethod method;
+ QString word;
+ bool useDialog;
+ bool suggest;
+};
+
+class KSpell::KSpellPrivate
+{
+public:
+ bool endOfResponse;
+ bool m_bIgnoreUpperWords;
+ bool m_bIgnoreTitleCase;
+ bool m_bNoMisspellingsEncountered;
+ SpellerType type;
+ KSpell* suggestSpell;
+ bool checking;
+ QValueList<BufferedWord> unchecked;
+ QTimer *checkNextTimer;
+ bool aspellV6;
+};
+
+//TODO
+//Parse stderr output
+//e.g. -- invalid dictionary name
+
+/*
+ Things to put in KSpellConfigDlg:
+ make root/affix combinations that aren't in the dictionary (-m)
+ don't generate any affix/root combinations (-P)
+ Report run-together words with missing blanks as spelling errors. (-B)
+ default dictionary (-d [dictionary])
+ personal dictionary (-p [dictionary])
+ path to ispell -- NO: ispell should be in $PATH
+ */
+
+
+// Connects a slot to KProcIO's output signal
+#define OUTPUT(x) (connect (proc, SIGNAL (readReady(KProcIO *)), this, SLOT (x(KProcIO *))))
+
+// Disconnect a slot from...
+#define NOOUTPUT(x) (disconnect (proc, SIGNAL (readReady(KProcIO *)), this, SLOT (x(KProcIO *))))
+
+
+
+KSpell::KSpell( QWidget *_parent, const QString &_caption,
+ QObject *obj, const char *slot, KSpellConfig *_ksc,
+ bool _progressbar, bool _modal )
+{
+ initialize( _parent, _caption, obj, slot, _ksc,
+ _progressbar, _modal, Text );
+}
+
+KSpell::KSpell( QWidget *_parent, const QString &_caption,
+ QObject *obj, const char *slot, KSpellConfig *_ksc,
+ bool _progressbar, bool _modal, SpellerType type )
+{
+ initialize( _parent, _caption, obj, slot, _ksc,
+ _progressbar, _modal, type );
+}
+
+void KSpell::hide() { ksdlg->hide(); }
+
+int KSpell::heightDlg() const { return ksdlg->height(); }
+int KSpell::widthDlg() const { return ksdlg->width(); }
+
+// Check if aspell is at least version 0.6
+static bool determineASpellV6()
+{
+ QString result;
+ FILE *fs = popen("aspell -v", "r");
+ if (fs)
+ {
+ // Close textstream before we close fs
+ {
+ QTextStream ts(fs, IO_ReadOnly);
+ result = ts.read().stripWhiteSpace();
+ }
+ pclose(fs);
+ }
+
+ QRegExp rx("Aspell (\\d.\\d)");
+ if (rx.search(result) != -1)
+ {
+ float version = rx.cap(1).toFloat();
+ return (version >= 0.6);
+ }
+ return false;
+}
+
+
+void
+KSpell::startIspell()
+ //trystart = {0,1,2}
+{
+ if ((trystart == 0) && (ksconfig->client() == KS_CLIENT_ASPELL))
+ d->aspellV6 = determineASpellV6();
+
+ kdDebug(750) << "Try #" << trystart << endl;
+
+ if ( trystart > 0 ) {
+ proc->resetAll();
+ }
+
+ switch ( ksconfig->client() )
+ {
+ case KS_CLIENT_ISPELL:
+ *proc << "ispell";
+ kdDebug(750) << "Using ispell" << endl;
+ break;
+ case KS_CLIENT_ASPELL:
+ *proc << "aspell";
+ kdDebug(750) << "Using aspell" << endl;
+ break;
+ case KS_CLIENT_HSPELL:
+ *proc << "hspell";
+ kdDebug(750) << "Using hspell" << endl;
+ break;
+ case KS_CLIENT_ZEMBEREK:
+ *proc << "zpspell";
+ kdDebug(750) << "Using zemberek(zpspell)" << endl;
+ break;
+ }
+
+ if ( ksconfig->client() == KS_CLIENT_ISPELL || ksconfig->client() == KS_CLIENT_ASPELL )
+ {
+ *proc << "-a" << "-S";
+
+ switch ( d->type )
+ {
+ case HTML:
+ //Debian uses an ispell version that has the -h option instead.
+ //Not sure what they did, but the preferred spell checker
+ //on that platform is aspell anyway, so use -H untill I'll come
+ //up with something better.
+ *proc << "-H";
+ break;
+ case TeX:
+ //same for aspell and ispell
+ *proc << "-t";
+ break;
+ case Nroff:
+ //only ispell supports
+ if ( ksconfig->client() == KS_CLIENT_ISPELL )
+ *proc << "-n";
+ break;
+ case Text:
+ default:
+ //nothing
+ break;
+ }
+ if (ksconfig->noRootAffix())
+ {
+ *proc<<"-m";
+ }
+ if (ksconfig->runTogether())
+ {
+ *proc << "-B";
+ }
+ else
+ {
+ *proc << "-C";
+ }
+
+
+ if (trystart<2)
+ {
+ if (! ksconfig->dictionary().isEmpty())
+ {
+ kdDebug(750) << "using dictionary [" << ksconfig->dictionary() << "]" << endl;
+ *proc << "-d";
+ *proc << ksconfig->dictionary();
+ }
+ }
+
+ //Note to potential debuggers: -Tlatin2 _is_ being added on the
+ // _first_ try. But, some versions of ispell will fail with this
+ // option, so kspell tries again without it. That's why as 'ps -ax'
+ // shows "ispell -a -S ..." withou the "-Tlatin2" option.
+
+ if ( trystart<1 ) {
+ switch ( ksconfig->encoding() )
+ {
+ case KS_E_LATIN1:
+ *proc << "-Tlatin1";
+ break;
+ case KS_E_LATIN2:
+ *proc << "-Tlatin2";
+ break;
+ case KS_E_LATIN3:
+ *proc << "-Tlatin3";
+ break;
+
+ // add the other charsets here
+ case KS_E_LATIN4:
+ case KS_E_LATIN5:
+ case KS_E_LATIN7:
+ case KS_E_LATIN8:
+ case KS_E_LATIN9:
+ case KS_E_LATIN13:
+ // will work, if this is the default charset in the dictionary
+ kdError(750) << "charsets ISO-8859-4, -5, -7, -8, -9 and -13 not supported yet" << endl;
+ break;
+ case KS_E_LATIN15: // ISO-8859-15 (Latin 9)
+ if (ksconfig->client() == KS_CLIENT_ISPELL)
+ {
+ /*
+ * As far as I know, there are no ispell dictionary using ISO-8859-15
+ * but users have the tendency to select this encoding instead of ISO-8859-1
+ * So put ispell in ISO-8859-1 (Latin 1) mode.
+ */
+ *proc << "-Tlatin1";
+ }
+ else
+ kdError(750) << "ISO-8859-15 not supported for aspell yet." << endl;
+ break;
+ case KS_E_UTF8:
+ *proc << "-Tutf8";
+ if (ksconfig->client() == KS_CLIENT_ASPELL)
+ *proc << "--encoding=utf-8";
+ break;
+ case KS_E_KOI8U:
+ *proc << "-w'"; // add ' as a word char
+ break;
+ default:
+ break;
+ }
+ }
+
+ // -a : pipe mode
+ // -S : sort suggestions by probable correctness
+ }
+ else // hspell and Zemberek(zpspell) doesn't need all the rest of the options
+ *proc << "-a";
+
+ if (trystart == 0) //don't connect these multiple times
+ {
+ connect( proc, SIGNAL(receivedStderr(KProcess *, char *, int)),
+ this, SLOT(ispellErrors(KProcess *, char *, int)) );
+
+ connect( proc, SIGNAL(processExited(KProcess *)),
+ this, SLOT(ispellExit (KProcess *)) );
+
+ OUTPUT(KSpell2);
+ }
+
+ if ( !proc->start() )
+ {
+ m_status = Error;
+ QTimer::singleShot( 0, this, SLOT(emitDeath()));
+ }
+}
+
+void
+KSpell::ispellErrors( KProcess *, char *buffer, int buflen )
+{
+ buffer[buflen-1] = '\0';
+ // kdDebug(750) << "ispellErrors [" << buffer << "]\n" << endl;
+}
+
+void KSpell::KSpell2( KProcIO * )
+
+{
+ QString line;
+
+ kdDebug(750) << "KSpell::KSpell2" << endl;
+
+ trystart = maxtrystart; //We've officially started ispell and don't want
+ //to try again if it dies.
+
+ if ( proc->readln( line, true ) == -1 )
+ {
+ QTimer::singleShot( 0, this, SLOT(emitDeath()) );
+ return;
+ }
+
+
+ if ( line[0] != '@' ) //@ indicates that ispell is working fine
+ {
+ QTimer::singleShot( 0, this, SLOT(emitDeath()) );
+ return;
+ }
+
+ //We want to recognize KDE in any text!
+ if ( !ignore("kde") )
+ {
+ kdDebug(750) << "@KDE was false" << endl;
+ QTimer::singleShot( 0, this, SLOT(emitDeath()) );
+ return;
+ }
+
+ //We want to recognize linux in any text!
+ if ( !ignore("linux") )
+ {
+ kdDebug(750) << "@Linux was false" << endl;
+ QTimer::singleShot( 0, this, SLOT(emitDeath()) );
+ return;
+ }
+
+ NOOUTPUT( KSpell2 );
+
+ m_status = Running;
+ emit ready( this );
+}
+
+void
+KSpell::setUpDialog( bool reallyuseprogressbar )
+{
+ if ( dialogsetup )
+ return;
+
+ //Set up the dialog box
+ ksdlg = new KSpellDlg( parent, "dialog",
+ progressbar && reallyuseprogressbar, modaldlg );
+ ksdlg->setCaption( caption );
+
+ connect( ksdlg, SIGNAL(command(int)),
+ this, SLOT(slotStopCancel(int)) );
+ connect( this, SIGNAL(progress(unsigned int)),
+ ksdlg, SLOT(slotProgress(unsigned int)) );
+
+#ifdef Q_WS_X11 // FIXME(E): Implement for Qt/Embedded
+ KWin::setIcons( ksdlg->winId(), kapp->icon(), kapp->miniIcon() );
+#endif
+ if ( modaldlg )
+ ksdlg->setFocus();
+ dialogsetup = true;
+}
+
+bool KSpell::addPersonal( const QString & word )
+{
+ QString qs = word.simplifyWhiteSpace();
+
+ //we'll let ispell do the work here b/c we can
+ if ( qs.find(' ') != -1 || qs.isEmpty() ) // make sure it's a _word_
+ return false;
+
+ qs.prepend( "*" );
+ personaldict = true;
+
+ return proc->writeStdin( qs );
+}
+
+bool KSpell::writePersonalDictionary()
+{
+ return proc->writeStdin("#");
+}
+
+bool KSpell::ignore( const QString & word )
+{
+ QString qs = word.simplifyWhiteSpace();
+
+ //we'll let ispell do the work here b/c we can
+ if ( qs.find (' ') != -1 || qs.isEmpty() ) // make sure it's a _word_
+ return false;
+
+ qs.prepend( "@" );
+
+ return proc->writeStdin( qs );
+}
+
+bool
+KSpell::cleanFputsWord( const QString & s, bool appendCR )
+{
+ QString qs(s);
+ bool empty = true;
+
+ for( unsigned int i = 0; i < qs.length(); i++ )
+ {
+ //we need some punctuation for ornaments
+ if ( qs[i] != '\'' && qs[i] != '\"' && qs[i] != '-'
+ && qs[i].isPunct() || qs[i].isSpace() )
+ {
+ qs.remove(i,1);
+ i--;
+ } else {
+ if ( qs[i].isLetter() )
+ empty=false;
+ }
+ }
+
+ // don't check empty words, otherwise synchronization will lost
+ if (empty)
+ return false;
+
+ return proc->writeStdin( "^"+qs, appendCR );
+}
+
+bool
+KSpell::cleanFputs( const QString & s, bool appendCR )
+{
+ QString qs(s);
+ unsigned l = qs.length();
+
+ // some uses of '$' (e.g. "$0") cause ispell to skip all following text
+ for( unsigned int i = 0; i < l; ++i )
+ {
+ if( qs[i] == '$' )
+ qs[i] = ' ';
+ }
+
+ if ( l<MAXLINELENGTH )
+ {
+ if ( qs.isEmpty() )
+ qs="";
+ return proc->writeStdin( "^"+qs, appendCR );
+ }
+ else
+ return proc->writeStdin( QString::fromAscii( "^\n" ),appendCR );
+}
+
+bool KSpell::checkWord( const QString & buffer, bool _usedialog )
+{
+ if (d->checking) { // don't check multiple words simultaneously
+ BufferedWord bufferedWord;
+ bufferedWord.method = Method1;
+ bufferedWord.word = buffer;
+ bufferedWord.useDialog = _usedialog;
+ d->unchecked.append( bufferedWord );
+ return true;
+ }
+ d->checking = true;
+ QString qs = buffer.simplifyWhiteSpace();
+
+ if ( qs.find (' ') != -1 || qs.isEmpty() ) { // make sure it's a _word_
+ d->checkNextTimer->start( 0, true );
+ return false;
+ }
+ ///set the dialog signal handler
+ dialog3slot = SLOT(checkWord3());
+
+ usedialog = _usedialog;
+ setUpDialog( false );
+ if ( _usedialog )
+ {
+ emitProgress();
+ }
+ else
+ ksdlg->hide();
+
+ QString blank_line;
+ while (proc->readln( blank_line, true ) != -1); // eat spurious blanks
+
+ OUTPUT(checkWord2);
+ // connect (this, SIGNAL (dialog3()), this, SLOT (checkWord3()));
+
+ proc->writeStdin( "%" ); // turn off terse mode
+ proc->writeStdin( buffer ); // send the word to ispell
+
+ return true;
+}
+
+bool KSpell::checkWord( const QString & buffer, bool _usedialog, bool suggest )
+{
+ if (d->checking) { // don't check multiple words simultaneously
+ BufferedWord bufferedWord;
+ bufferedWord.method = Method2;
+ bufferedWord.word = buffer;
+ bufferedWord.useDialog = _usedialog;
+ bufferedWord.suggest = suggest;
+ d->unchecked.append( bufferedWord );
+ return true;
+ }
+ d->checking = true;
+ QString qs = buffer.simplifyWhiteSpace();
+
+ if ( qs.find (' ') != -1 || qs.isEmpty() ) { // make sure it's a _word_
+ d->checkNextTimer->start( 0, true );
+ return false;
+ }
+
+ ///set the dialog signal handler
+ if ( !suggest ) {
+ dialog3slot = SLOT(checkWord3());
+ usedialog = _usedialog;
+ setUpDialog( false );
+ if ( _usedialog )
+ {
+ emitProgress();
+ }
+ else
+ ksdlg->hide();
+ }
+
+ QString blank_line;
+ while (proc->readln( blank_line, true ) != -1); // eat spurious blanks
+
+ OUTPUT(checkWord2);
+ // connect (this, SIGNAL (dialog3()), this, SLOT (checkWord3()));
+
+ proc->writeStdin( "%" ); // turn off terse mode
+ proc->writeStdin( buffer ); // send the word to ispell
+
+ return true;
+}
+
+void KSpell::checkWord2( KProcIO* )
+{
+ QString word;
+ QString line;
+ proc->readln( line, true ); //get ispell's response
+
+/* ispell man page: "Each sentence of text input is terminated with an
+ additional blank line, indicating that ispell has completed processing
+ the input line."
+ <sanders>
+ But there can be multiple lines returned in the case of an error,
+ in this case we should consume all the output given otherwise spell checking
+ can get out of sync.
+ </sanders>
+*/
+ QString blank_line;
+ while (proc->readln( blank_line, true ) != -1); // eat the blank line
+ NOOUTPUT(checkWord2);
+
+ bool mistake = ( parseOneResponse(line, word, sugg) == MISTAKE );
+ if ( mistake && usedialog )
+ {
+ cwword = word;
+ dialog( word, sugg, SLOT(checkWord3()) );
+ d->checkNextTimer->start( 0, true );
+ return;
+ }
+ else if( mistake )
+ {
+ emit misspelling( word, sugg, lastpos );
+ }
+
+ //emits a "corrected" signal _even_ if no change was made
+ //so that the calling program knows when the check is complete
+ emit corrected( word, word, 0L );
+ d->checkNextTimer->start( 0, true );
+}
+
+void KSpell::checkNext()
+{
+// Queue words to prevent kspell from turning into a fork bomb
+ d->checking = false;
+ if (!d->unchecked.empty()) {
+ BufferedWord buf = d->unchecked.front();
+ d->unchecked.pop_front();
+
+ if (buf.method == Method1)
+ checkWord( buf.word, buf.useDialog );
+ else
+ checkWord( buf.word, buf.useDialog, buf.suggest );
+ }
+}
+
+void KSpell::suggestWord( KProcIO * )
+{
+ QString word;
+ QString line;
+ proc->readln( line, true ); //get ispell's response
+
+/* ispell man page: "Each sentence of text input is terminated with an
+ additional blank line, indicating that ispell has completed processing
+ the input line." */
+ QString blank_line;
+ proc->readln( blank_line, true ); // eat the blank line
+
+ NOOUTPUT(checkWord2);
+
+ bool mistake = ( parseOneResponse(line, word, sugg) == MISTAKE );
+ if ( mistake && usedialog )
+ {
+ cwword=word;
+ dialog( word, sugg, SLOT(checkWord3()) );
+ return;
+ }
+}
+
+void KSpell::checkWord3()
+{
+ disconnect( this, SIGNAL(dialog3()), this, SLOT(checkWord3()) );
+
+ emit corrected( cwword, replacement(), 0L );
+}
+
+QString KSpell::funnyWord( const QString & word )
+ // composes a guess from ispell to a readable word
+ // e.g. "re+fry-y+ies" -> "refries"
+{
+ QString qs;
+ unsigned int i=0;
+
+ for( i=0; word [i]!='\0';i++ )
+ {
+ if (word [i]=='+')
+ continue;
+ if (word [i]=='-')
+ {
+ QString shorty;
+ unsigned int j;
+ int k;
+
+ for( j = i+1; word[j] != '\0' && word[j] != '+' && word[j] != '-'; j++ )
+ shorty += word[j];
+
+ i = j-1;
+
+ if ( !( k = qs.findRev(shorty) ) || k != -1 )
+ qs.remove( k, shorty.length() );
+ else
+ {
+ qs += '-';
+ qs += shorty; //it was a hyphen, not a '-' from ispell
+ }
+ }
+ else
+ qs += word[i];
+ }
+
+ return qs;
+}
+
+
+int KSpell::parseOneResponse( const QString &buffer, QString &word, QStringList & sugg )
+ // buffer is checked, word and sugg are filled in
+ // returns
+ // GOOD if word is fine
+ // IGNORE if word is in ignorelist
+ // REPLACE if word is in replacelist
+ // MISTAKE if word is misspelled
+{
+ word = "";
+ posinline=0;
+
+ sugg.clear();
+
+ if ( buffer[0] == '*' || buffer[0] == '+' || buffer[0] == '-' )
+ {
+ return GOOD;
+ }
+
+ if ( buffer[0] == '&' || buffer[0] == '?' || buffer[0] == '#' )
+ {
+ int i,j;
+
+
+ word = buffer.mid( 2, buffer.find( ' ', 3 ) -2 );
+ //check() needs this
+ orig=word;
+
+ if( d->m_bIgnoreTitleCase && word == word.upper() )
+ return IGNORE;
+
+ if( d->m_bIgnoreUpperWords && word[0] == word[0].upper() )
+ {
+ QString text = word[0] + word.right( word.length()-1 ).lower();
+ if( text == word )
+ return IGNORE;
+ }
+
+ /////// Ignore-list stuff //////////
+ //We don't take advantage of ispell's ignore function because
+ //we can't interrupt ispell's output (when checking a large
+ //buffer) to add a word to _it's_ ignore-list.
+ if ( ignorelist.findIndex( word.lower() ) != -1 )
+ return IGNORE;
+
+ //// Position in line ///
+ QString qs2;
+
+ if ( buffer.find( ':' ) != -1 )
+ qs2 = buffer.left( buffer.find(':') );
+ else
+ qs2 = buffer;
+
+ posinline = qs2.right( qs2.length()-qs2.findRev(' ') ).toInt()-1;
+
+ ///// Replace-list stuff ////
+ QStringList::Iterator it = replacelist.begin();
+ for( ;it != replacelist.end(); ++it, ++it ) // Skip two entries at a time.
+ {
+ if ( word == *it ) // Word matches
+ {
+ ++it;
+ word = *it; // Replace it with the next entry
+ return REPLACE;
+ }
+ }
+
+ /////// Suggestions //////
+ if ( buffer[0] != '#' )
+ {
+ QString qs = buffer.mid( buffer.find(':')+2, buffer.length() );
+ qs += ',';
+ sugg.clear();
+ i = j = 0;
+
+ while( (unsigned int)i < qs.length() )
+ {
+ QString temp = qs.mid( i, (j=qs.find (',',i)) - i );
+ sugg.append( funnyWord(temp) );
+
+ i=j+2;
+ }
+ }
+
+ if ( (sugg.count()==1) && (sugg.first() == word) )
+ return GOOD;
+
+ return MISTAKE;
+ }
+
+ if ( buffer.isEmpty() ) {
+ kdDebug(750) << "Got an empty response: ignoring"<<endl;
+ return GOOD;
+ }
+
+ kdError(750) << "HERE?: [" << buffer << "]" << endl;
+ kdError(750) << "Please report this to zack@kde.org" << endl;
+ kdError(750) << "Thank you!" << endl;
+
+ emit done( false );
+ emit done( KSpell::origbuffer );
+ return MISTAKE;
+}
+
+bool KSpell::checkList (QStringList *_wordlist, bool _usedialog)
+ // prepare check of string list
+{
+ wordlist=_wordlist;
+ if ((totalpos=wordlist->count())==0)
+ return false;
+ wlIt = wordlist->begin();
+ usedialog=_usedialog;
+
+ // prepare the dialog
+ setUpDialog();
+
+ //set the dialog signal handler
+ dialog3slot = SLOT (checkList4 ());
+
+ proc->writeStdin ("%"); // turn off terse mode & check one word at a time
+
+ //lastpos now counts which *word number* we are at in checkListReplaceCurrent()
+ lastpos = -1;
+ checkList2();
+
+ // when checked, KProcIO calls checkList3a
+ OUTPUT(checkList3a);
+
+ return true;
+}
+
+void KSpell::checkList2 ()
+ // send one word from the list to KProcIO
+ // invoked first time by checkList, later by checkListReplaceCurrent and checkList4
+{
+ // send next word
+ if (wlIt != wordlist->end())
+ {
+ kdDebug(750) << "KS::cklist2 " << lastpos << ": " << *wlIt << endl;
+
+ d->endOfResponse = false;
+ bool put;
+ lastpos++; offset=0;
+ put = cleanFputsWord (*wlIt);
+ ++wlIt;
+
+ // when cleanFPutsWord failed (e.g. on empty word)
+ // try next word; may be this is not good for other
+ // problems, because this will make read the list up to the end
+ if (!put) {
+ checkList2();
+ }
+ }
+ else
+ // end of word list
+ {
+ NOOUTPUT(checkList3a);
+ ksdlg->hide();
+ emit done(true);
+ }
+}
+
+void KSpell::checkList3a (KProcIO *)
+ // invoked by KProcIO, when data from ispell are read
+{
+ //kdDebug(750) << "start of checkList3a" << endl;
+
+ // don't read more data, when dialog is waiting
+ // for user interaction
+ if ( dlgon ) {
+ //kdDebug(750) << "dlgon: don't read more data" << endl;
+ return;
+ }
+
+ int e, tempe;
+
+ QString word;
+ QString line;
+
+ do
+ {
+ tempe=proc->readln( line, true ); //get ispell's response
+
+ //kdDebug(750) << "checkList3a: read bytes [" << tempe << "]" << endl;
+
+
+ if ( tempe == 0 ) {
+ d->endOfResponse = true;
+ //kdDebug(750) << "checkList3a: end of resp" << endl;
+ } else if ( tempe>0 ) {
+ if ( (e=parseOneResponse( line, word, sugg ) ) == MISTAKE ||
+ e==REPLACE )
+ {
+ dlgresult=-1;
+
+ if ( e == REPLACE )
+ {
+ QString old = *(--wlIt); ++wlIt;
+ dlgreplacement = word;
+ checkListReplaceCurrent();
+ // inform application
+ emit corrected( old, *(--wlIt), lastpos ); ++wlIt;
+ }
+ else if( usedialog )
+ {
+ cwword = word;
+ dlgon = true;
+ // show the dialog
+ dialog( word, sugg, SLOT(checkList4()) );
+ return;
+ }
+ else
+ {
+ d->m_bNoMisspellingsEncountered = false;
+ emit misspelling( word, sugg, lastpos );
+ }
+ }
+
+ }
+ emitProgress (); //maybe
+
+ // stop when empty line or no more data
+ } while (tempe > 0);
+
+ //kdDebug(750) << "checkList3a: exit loop with [" << tempe << "]" << endl;
+
+ // if we got an empty line, t.e. end of ispell/aspell response
+ // and the dialog isn't waiting for user interaction, send next word
+ if (d->endOfResponse && !dlgon) {
+ //kdDebug(750) << "checkList3a: send next word" << endl;
+ checkList2();
+ }
+}
+
+void KSpell::checkListReplaceCurrent()
+{
+
+ // go back to misspelled word
+ wlIt--;
+
+ QString s = *wlIt;
+ s.replace(posinline+offset,orig.length(),replacement());
+ offset += replacement().length()-orig.length();
+ wordlist->insert (wlIt, s);
+ wlIt = wordlist->remove (wlIt);
+ // wlIt now points to the word after the repalced one
+
+}
+
+void KSpell::checkList4 ()
+ // evaluate dialog return, when a button was pressed there
+{
+ dlgon=false;
+ QString old;
+
+ disconnect (this, SIGNAL (dialog3()), this, SLOT (checkList4()));
+
+ //others should have been processed by dialog() already
+ switch (dlgresult)
+ {
+ case KS_REPLACE:
+ case KS_REPLACEALL:
+ kdDebug(750) << "KS: cklist4: lastpos: " << lastpos << endl;
+ old = *(--wlIt);
+ ++wlIt;
+ // replace word
+ checkListReplaceCurrent();
+ emit corrected( old, *(--wlIt), lastpos );
+ ++wlIt;
+ break;
+ case KS_CANCEL:
+ ksdlg->hide();
+ emit done( false );
+ return;
+ case KS_STOP:
+ ksdlg->hide();
+ emit done( true );
+ return;
+ case KS_CONFIG:
+ ksdlg->hide();
+ emit done( false );
+ //check( origbuffer.mid( lastpos ), true );
+ //trystart = 0;
+ //proc->disconnect();
+ //proc->kill();
+ //delete proc;
+ //proc = new KProcIO( codec );
+ //startIspell();
+ return;
+ };
+
+ // read more if there is more, otherwise send next word
+ if (!d->endOfResponse) {
+ //kdDebug(750) << "checkList4: read more from response" << endl;
+ checkList3a(NULL);
+ }
+}
+
+bool KSpell::check( const QString &_buffer, bool _usedialog )
+{
+ QString qs;
+
+ usedialog = _usedialog;
+ setUpDialog();
+ //set the dialog signal handler
+ dialog3slot = SLOT(check3());
+
+ kdDebug(750) << "KS: check" << endl;
+ origbuffer = _buffer;
+ if ( ( totalpos = origbuffer.length() ) == 0 )
+ {
+ emit done( origbuffer );
+ return false;
+ }
+
+
+ // Torben: I corrected the \n\n problem directly in the
+ // origbuffer since I got errors otherwise
+ if ( !origbuffer.endsWith("\n\n" ) )
+ {
+ if (origbuffer.at(origbuffer.length()-1)!='\n')
+ {
+ origbuffer+='\n';
+ origbuffer+='\n'; //shouldn't these be removed at some point?
+ }
+ else
+ origbuffer+='\n';
+ }
+
+ newbuffer = origbuffer;
+
+ // KProcIO calls check2 when read from ispell
+ OUTPUT( check2 );
+ proc->writeStdin( "!" );
+
+ //lastpos is a position in newbuffer (it has offset in it)
+ offset = lastlastline = lastpos = lastline = 0;
+
+ emitProgress();
+
+ // send first buffer line
+ int i = origbuffer.find( '\n', 0 ) + 1;
+ qs = origbuffer.mid( 0, i );
+ cleanFputs( qs, false );
+
+ lastline=i; //the character position, not a line number
+
+ if ( usedialog )
+ {
+ emitProgress();
+ }
+ else
+ ksdlg->hide();
+
+ return true;
+}
+
+
+void KSpell::check2( KProcIO * )
+ // invoked by KProcIO when read from ispell
+{
+ int e, tempe;
+ QString word;
+ QString line;
+ static bool recursive = false;
+ if (recursive &&
+ !ksdlg )
+ {
+ return;
+ }
+ recursive = true;
+
+ do
+ {
+ tempe = proc->readln( line, false ); //get ispell's response
+ //kdDebug(750) << "KSpell::check2 (" << tempe << "b)" << endl;
+
+ if ( tempe>0 )
+ {
+ if ( ( e=parseOneResponse (line, word, sugg) )==MISTAKE ||
+ e==REPLACE)
+ {
+ dlgresult=-1;
+
+ // for multibyte encoding posinline needs correction
+ if ((ksconfig->encoding() == KS_E_UTF8) && !d->aspellV6) {
+ // kdDebug(750) << "line: " << origbuffer.mid(lastlastline,
+ // lastline-lastlastline) << endl;
+ // kdDebug(750) << "posinline uncorr: " << posinline << endl;
+
+ // convert line to UTF-8, cut at pos, convert back to UCS-2
+ // and get string length
+ posinline = (QString::fromUtf8(
+ origbuffer.mid(lastlastline,lastline-lastlastline).utf8(),
+ posinline)).length();
+ // kdDebug(750) << "posinline corr: " << posinline << endl;
+ }
+
+ lastpos = posinline+lastlastline+offset;
+
+ //orig is set by parseOneResponse()
+
+ if (e==REPLACE)
+ {
+ dlgreplacement=word;
+ emit corrected( orig, replacement(), lastpos );
+ offset += replacement().length()-orig.length();
+ newbuffer.replace( lastpos, orig.length(), word );
+ }
+ else //MISTAKE
+ {
+ cwword = word;
+ //kdDebug(750) << "(Before dialog) word=[" << word << "] cwword =[" << cwword << "]\n" << endl;
+ if ( usedialog ) {
+ // show the word in the dialog
+ dialog( word, sugg, SLOT(check3()) );
+ } else {
+ // No dialog, just emit misspelling and continue
+ d->m_bNoMisspellingsEncountered = false;
+ emit misspelling( word, sugg, lastpos );
+ dlgresult = KS_IGNORE;
+ check3();
+ }
+ recursive = false;
+ return;
+ }
+ }
+
+ }
+
+ emitProgress(); //maybe
+
+ } while( tempe>0 );
+
+ if ( tempe == -1 ) { //we were called, but no data seems to be ready...
+ // Make sure we don't get called directly again and make sure we do get
+ // called when new data arrives.
+ NOOUTPUT( check2 );
+ proc->enableReadSignals(true);
+ OUTPUT( check2 );
+ recursive = false;
+ return;
+ }
+
+ proc->ackRead();
+
+ //If there is more to check, then send another line to ISpell.
+ if ( (unsigned int)lastline < origbuffer.length() )
+ {
+ int i;
+ QString qs;
+
+ //kdDebug(750) << "[EOL](" << tempe << ")[" << temp << "]" << endl;
+
+ lastpos = (lastlastline=lastline) + offset; //do we really want this?
+ i = origbuffer.find('\n', lastline) + 1;
+ qs = origbuffer.mid( lastline, i-lastline );
+ cleanFputs( qs, false );
+ lastline = i;
+ recursive = false;
+ return;
+ }
+ else
+ //This is the end of it all
+ {
+ ksdlg->hide();
+ // kdDebug(750) << "check2() done" << endl;
+ newbuffer.truncate( newbuffer.length()-2 );
+ emitProgress();
+ emit done( newbuffer );
+ }
+ recursive = false;
+}
+
+void KSpell::check3 ()
+ // evaluates the return value of the dialog
+{
+ disconnect (this, SIGNAL (dialog3()), this, SLOT (check3()));
+ kdDebug(750) << "check3 [" << cwword << "] [" << replacement() << "] " << dlgresult << endl;
+
+ //others should have been processed by dialog() already
+ switch (dlgresult)
+ {
+ case KS_REPLACE:
+ case KS_REPLACEALL:
+ offset+=replacement().length()-cwword.length();
+ newbuffer.replace (lastpos, cwword.length(),
+ replacement());
+ emit corrected (dlgorigword, replacement(), lastpos);
+ break;
+ case KS_CANCEL:
+ // kdDebug(750) << "canceled\n" << endl;
+ ksdlg->hide();
+ emit done( origbuffer );
+ return;
+ case KS_CONFIG:
+ ksdlg->hide();
+ emit done( origbuffer );
+ KMessageBox::information( 0, i18n("You have to restart the dialog for changes to take effect") );
+ //check( origbuffer.mid( lastpos ), true );
+ return;
+ case KS_STOP:
+ ksdlg->hide();
+ //buffer=newbuffer);
+ emitProgress();
+ emit done (newbuffer);
+ return;
+ };
+
+ proc->ackRead();
+}
+
+void
+KSpell::slotStopCancel (int result)
+{
+ if (dialogwillprocess)
+ return;
+
+ kdDebug(750) << "KSpell::slotStopCancel [" << result << "]" << endl;
+
+ if (result==KS_STOP || result==KS_CANCEL)
+ if (!dialog3slot.isEmpty())
+ {
+ dlgresult=result;
+ connect (this, SIGNAL (dialog3()), this, dialog3slot.ascii());
+ emit dialog3();
+ }
+}
+
+
+void KSpell::dialog( const QString & word, QStringList & sugg, const char *_slot )
+{
+ dlgorigword = word;
+
+ dialog3slot = _slot;
+ dialogwillprocess = true;
+ connect( ksdlg, SIGNAL(command(int)), this, SLOT(dialog2(int)) );
+ QString tmpBuf = newbuffer;
+ kdDebug(750)<<" position = "<<lastpos<<endl;
+
+ // extract a context string, replace all characters which might confuse
+ // the RichText display and highlight the possibly wrong word
+ QString marker( "_MARKER_" );
+ tmpBuf.replace( lastpos, word.length(), marker );
+ QString context = tmpBuf.mid(QMAX(lastpos-18,0), 2*18+marker.length());
+ context.replace( '\n',QString::fromLatin1(" "));
+ context.replace( '<', QString::fromLatin1("&lt;") );
+ context.replace( '>', QString::fromLatin1("&gt;") );
+ context.replace( marker, QString::fromLatin1("<b>%1</b>").arg( word ) );
+ context = "<qt>" + context + "</qt>";
+
+ ksdlg->init( word, &sugg, context );
+ d->m_bNoMisspellingsEncountered = false;
+ emit misspelling( word, sugg, lastpos );
+
+ emitProgress();
+ ksdlg->show();
+}
+
+void KSpell::dialog2( int result )
+{
+ QString qs;
+
+ disconnect( ksdlg, SIGNAL(command(int)), this, SLOT(dialog2(int)) );
+ dialogwillprocess = false;
+ dlgresult = result;
+ ksdlg->standby();
+
+ dlgreplacement = ksdlg->replacement();
+
+ //process result here
+ switch ( dlgresult )
+ {
+ case KS_IGNORE:
+ emit ignoreword( dlgorigword );
+ break;
+ case KS_IGNOREALL:
+ // would be better to lower case only words with beginning cap
+ ignorelist.prepend( dlgorigword.lower() );
+ emit ignoreall( dlgorigword );
+ break;
+ case KS_ADD:
+ addPersonal( dlgorigword );
+ personaldict = true;
+ emit addword( dlgorigword );
+ // adding to pesonal dict takes effect at the next line, not the current
+ ignorelist.prepend( dlgorigword.lower() );
+ break;
+ case KS_REPLACEALL:
+ {
+ replacelist.append( dlgorigword );
+ QString _replacement = replacement();
+ replacelist.append( _replacement );
+ emit replaceall( dlgorigword , _replacement );
+ }
+ break;
+ case KS_SUGGEST:
+ checkWord( ksdlg->replacement(), false, true );
+ return;
+ break;
+ }
+
+ connect( this, SIGNAL(dialog3()), this, dialog3slot.ascii() );
+ emit dialog3();
+}
+
+
+KSpell::~KSpell()
+{
+ delete proc;
+ delete ksconfig;
+ delete ksdlg;
+ delete d->checkNextTimer;
+ delete d;
+}
+
+
+KSpellConfig KSpell::ksConfig() const
+{
+ ksconfig->setIgnoreList(ignorelist);
+ ksconfig->setReplaceAllList(replacelist);
+ return *ksconfig;
+}
+
+void KSpell::cleanUp()
+{
+ if ( m_status == Cleaning )
+ return; // Ignore
+
+ if ( m_status == Running )
+ {
+ if ( personaldict )
+ writePersonalDictionary();
+ m_status = Cleaning;
+ }
+ proc->closeStdin();
+}
+
+void KSpell::ispellExit( KProcess* )
+{
+ kdDebug() << "KSpell::ispellExit() " << m_status << endl;
+
+ if ( (m_status == Starting) && (trystart < maxtrystart) )
+ {
+ trystart++;
+ startIspell();
+ return;
+ }
+
+ if ( m_status == Starting )
+ m_status = Error;
+ else if (m_status == Cleaning)
+ m_status = d->m_bNoMisspellingsEncountered ? FinishedNoMisspellingsEncountered : Finished;
+ else if ( m_status == Running )
+ m_status = Crashed;
+ else // Error, Finished, Crashed
+ return; // Dead already
+
+ kdDebug(750) << "Death" << endl;
+ QTimer::singleShot( 0, this, SLOT(emitDeath()) );
+}
+
+// This is always called from the event loop to make
+// sure that the receiver can safely delete the
+// KSpell object.
+void KSpell::emitDeath()
+{
+ bool deleteMe = autoDelete; // Can't access object after next call!
+ emit death();
+ if ( deleteMe )
+ deleteLater();
+}
+
+void KSpell::setProgressResolution (unsigned int res)
+{
+ progres=res;
+}
+
+void KSpell::emitProgress ()
+{
+ uint nextprog = (uint) (100.*lastpos/(double)totalpos);
+
+ if ( nextprog >= curprog )
+ {
+ curprog = nextprog;
+ emit progress( curprog );
+ }
+}
+
+void KSpell::moveDlg( int x, int y )
+{
+ QPoint pt( x,y ), pt2;
+ pt2 = parent->mapToGlobal( pt );
+ ksdlg->move( pt2.x(),pt2.y() );
+}
+
+void KSpell::setIgnoreUpperWords(bool _ignore)
+{
+ d->m_bIgnoreUpperWords=_ignore;
+}
+
+void KSpell::setIgnoreTitleCase(bool _ignore)
+{
+ d->m_bIgnoreTitleCase=_ignore;
+}
+// --------------------------------------------------
+// Stuff for modal (blocking) spell checking
+//
+// Written by Torben Weis <weis@kde.org>. So please
+// send bug reports regarding the modal stuff to me.
+// --------------------------------------------------
+
+int
+KSpell::modalCheck( QString& text )
+{
+ return modalCheck( text,0 );
+}
+
+int
+KSpell::modalCheck( QString& text, KSpellConfig* _kcs )
+{
+ modalreturn = 0;
+ modaltext = text;
+
+ KSpell* spell = new KSpell( 0L, i18n("Spell Checker"), 0 ,
+ 0, _kcs, true, true );
+
+ while (spell->status()!=Finished)
+ kapp->processEvents();
+
+ text = modaltext;
+
+ delete spell;
+ return modalreturn;
+}
+
+void KSpell::slotSpellCheckerCorrected( const QString & oldText, const QString & newText, unsigned int pos )
+{
+ modaltext=modaltext.replace(pos,oldText.length(),newText);
+}
+
+
+void KSpell::slotModalReady()
+{
+ //kdDebug() << qApp->loopLevel() << endl;
+ //kdDebug(750) << "MODAL READY------------------" << endl;
+
+ Q_ASSERT( m_status == Running );
+ connect( this, SIGNAL( done( const QString & ) ),
+ this, SLOT( slotModalDone( const QString & ) ) );
+ QObject::connect( this, SIGNAL( corrected( const QString&, const QString&, unsigned int ) ),
+ this, SLOT( slotSpellCheckerCorrected( const QString&, const QString &, unsigned int ) ) );
+ QObject::connect( this, SIGNAL( death() ),
+ this, SLOT( slotModalSpellCheckerFinished( ) ) );
+ check( modaltext );
+}
+
+void KSpell::slotModalDone( const QString &/*_buffer*/ )
+{
+ //kdDebug(750) << "MODAL DONE " << _buffer << endl;
+ //modaltext = _buffer;
+ cleanUp();
+
+ //kdDebug() << "ABOUT TO EXIT LOOP" << endl;
+ //qApp->exit_loop();
+
+ //modalWidgetHack->close(true);
+ slotModalSpellCheckerFinished();
+}
+
+void KSpell::slotModalSpellCheckerFinished( )
+{
+ modalreturn=(int)this->status();
+}
+
+void KSpell::initialize( QWidget *_parent, const QString &_caption,
+ QObject *obj, const char *slot, KSpellConfig *_ksc,
+ bool _progressbar, bool _modal, SpellerType type )
+{
+ d = new KSpellPrivate;
+
+ d->m_bIgnoreUpperWords =false;
+ d->m_bIgnoreTitleCase =false;
+ d->m_bNoMisspellingsEncountered = true;
+ d->type = type;
+ d->checking = false;
+ d->aspellV6 = false;
+ d->checkNextTimer = new QTimer( this );
+ connect( d->checkNextTimer, SIGNAL( timeout() ),
+ this, SLOT( checkNext() ));
+ autoDelete = false;
+ modaldlg = _modal;
+ progressbar = _progressbar;
+
+ proc = 0;
+ ksconfig = 0;
+ ksdlg = 0;
+ lastpos = 0;
+
+ //won't be using the dialog in ksconfig, just the option values
+ if ( _ksc )
+ ksconfig = new KSpellConfig( *_ksc );
+ else
+ ksconfig = new KSpellConfig;
+
+ codec = 0;
+ switch ( ksconfig->encoding() )
+ {
+ case KS_E_LATIN1:
+ codec = QTextCodec::codecForName("ISO 8859-1");
+ break;
+ case KS_E_LATIN2:
+ codec = QTextCodec::codecForName("ISO 8859-2");
+ break;
+ case KS_E_LATIN3:
+ codec = QTextCodec::codecForName("ISO 8859-3");
+ break;
+ case KS_E_LATIN4:
+ codec = QTextCodec::codecForName("ISO 8859-4");
+ break;
+ case KS_E_LATIN5:
+ codec = QTextCodec::codecForName("ISO 8859-5");
+ break;
+ case KS_E_LATIN7:
+ codec = QTextCodec::codecForName("ISO 8859-7");
+ break;
+ case KS_E_LATIN8:
+ codec = QTextCodec::codecForName("ISO 8859-8-i");
+ break;
+ case KS_E_LATIN9:
+ codec = QTextCodec::codecForName("ISO 8859-9");
+ break;
+ case KS_E_LATIN13:
+ codec = QTextCodec::codecForName("ISO 8859-13");
+ break;
+ case KS_E_LATIN15:
+ codec = QTextCodec::codecForName("ISO 8859-15");
+ break;
+ case KS_E_UTF8:
+ codec = QTextCodec::codecForName("UTF-8");
+ break;
+ case KS_E_KOI8R:
+ codec = QTextCodec::codecForName("KOI8-R");
+ break;
+ case KS_E_KOI8U:
+ codec = QTextCodec::codecForName("KOI8-U");
+ break;
+ case KS_E_CP1251:
+ codec = QTextCodec::codecForName("CP1251");
+ break;
+ case KS_E_CP1255:
+ codec = QTextCodec::codecForName("CP1255");
+ break;
+ default:
+ break;
+ }
+
+ kdDebug(750) << __FILE__ << ":" << __LINE__ << " Codec = " << (codec ? codec->name() : "<default>") << endl;
+
+ // copy ignore list from ksconfig
+ ignorelist += ksconfig->ignoreList();
+
+ replacelist += ksconfig->replaceAllList();
+ texmode=dlgon=false;
+ m_status = Starting;
+ dialogsetup = false;
+ progres=10;
+ curprog=0;
+
+ dialogwillprocess = false;
+ dialog3slot = QString::null;
+
+ personaldict = false;
+ dlgresult = -1;
+
+ caption = _caption;
+
+ parent = _parent;
+
+ trystart = 0;
+ maxtrystart = 2;
+
+ if ( obj && slot )
+ // caller wants to know when kspell is ready
+ connect( this, SIGNAL(ready(KSpell *)), obj, slot);
+ else
+ // Hack for modal spell checking
+ connect( this, SIGNAL(ready(KSpell *)), this, SLOT(slotModalReady()) );
+
+ proc = new KProcIO( codec );
+
+ startIspell();
+}
+
+QString KSpell::modaltext;
+int KSpell::modalreturn = 0;
+QWidget* KSpell::modalWidgetHack = 0;
+
+#include "kspell.moc"
+
diff --git a/kdeui/kspell.h b/kdeui/kspell.h
new file mode 100644
index 000000000..17ad038e1
--- /dev/null
+++ b/kdeui/kspell.h
@@ -0,0 +1,568 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 David Sweet <dsweet@kde.org>
+ Copyright (C) 2003 Zack Rusin <zack@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef __KSPELL_H__
+#define __KSPELL_H__
+
+#include "ksconfig.h"
+
+#include <qobject.h>
+#include <qstringlist.h>
+#include <qstring.h>
+#include <kdelibs_export.h>
+
+class QTextCodec;
+class KProcIO;
+class KProcess;
+class KSpellDlg;
+
+/**
+ * %KDE Spellchecker
+ *
+ * A %KDE programmer's interface to International ISpell 3.1, ASpell,
+ * HSpell and ZPSpell..
+ * A static method, modalCheck() is provided for convenient
+ * access to the spellchecker.
+ *
+ * @author David Sweet <dsweet@kde.org>
+ * @see KSpellConfig, KSyntaxHighlighter
+ */
+
+class KDEUI_EXPORT KSpell : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ /**
+ * Possible states of the spell checker.
+ *
+ * @li @p Starting - After creation of KSpell.
+ * @li @p Running - After the ready signal has been emitted.
+ * @li @p Cleaning - After cleanUp() has been called.
+ * @li @p Finished - After cleanUp() has been completed.
+ *
+ * The following error states exist:
+ *
+ * @li @p Error - An error occurred in the @p Starting state.
+ * @li @p Crashed - An error occurred in the @p Running state.
+ **/
+ enum spellStatus { Starting = 0, Running, Cleaning, Finished, Error, Crashed, FinishedNoMisspellingsEncountered };
+
+ /**
+ * These are possible types of documents which the spell checker can check.
+ *
+ * @li @p Text - The default type, checks every word
+ * @li @p HTML - For HTML/SGML/XML documents, will skip the tags,
+ * @li @p TeX - For TeX/LaTeX documents, will skip commands,
+ * @li @p Nroff - For nroff/troff documents.
+ *
+ * Please note that not every option is supported on every type of
+ * checker (e.g. ASpell doesn't support Nroff). In case a type
+ * of a document is not supported the default Text option will
+ * be used.
+ */
+ enum SpellerType { Text = 0, HTML, TeX, Nroff };
+
+ /**
+ * Starts the spellchecker.
+ *
+ * KSpell emits ready() when it has verified that
+ * ISpell/ASpell is working properly. Pass the name of a slot -- do not pass zero!
+ * Be sure to call cleanUp() when you are done with KSpell.
+ *
+ * If KSpell could not be started correctly, death() is emitted.
+ *
+ * @param parent Parent of KSpellConfig dialog..
+ * @param caption Caption of KSpellConfig dialog.
+ * @param receiver Receiver object for the ready(KSpell *) signal.
+ * @param slot Receiver's slot, will be connected to the ready(KSpell *) signal.
+ * @param kcs Configuration for KSpell.
+ * @param progressbar Indicates if progress bar should be shown.
+ * @param modal Indicates modal or non-modal dialog.
+ */
+ KSpell(QWidget *parent, const QString &caption,
+ QObject *receiver, const char *slot, KSpellConfig *kcs=0,
+ bool progressbar = true, bool modal = false);
+
+ /**
+ * Starts the spellchecker.
+ *
+ * KSpell emits ready() when it has verified that
+ * ISpell/ASpell is working properly. Pass the name of a slot -- do not pass zero!
+ * Be sure to call cleanUp() when you are done with KSpell.
+ *
+ * If KSpell could not be started correctly, death() is emitted.
+ *
+ * @param parent Parent of KSpellConfig dialog..
+ * @param caption Caption of KSpellConfig dialog.
+ * @param receiver Receiver object for the ready(KSpell *) signal.
+ * @param slot Receiver's slot, will be connected to the ready(KSpell *) signal.
+ * @param kcs Configuration for KSpell.
+ * @param progressbar Indicates if progress bar should be shown.
+ * @param modal Indicates modal or non-modal dialog.
+ * @param type Type of the document to check
+ */
+ KSpell(QWidget *parent, const QString &caption,
+ QObject *receiver, const char *slot, KSpellConfig *kcs,
+ bool progressbar, bool modal, SpellerType type);
+
+ /**
+ * Returns the status of KSpell.
+ *
+ * @see spellStatus()
+ */
+ spellStatus status() const { return m_status; }
+
+ /**
+ * Cleans up ISpell.
+ *
+ * Write out the personal dictionary and close ISpell's
+ * stdin. A death() signal will be emitted when the cleanup is
+ * complete, but this method will return immediately.
+ */
+ virtual void cleanUp ();
+
+ /**
+ * Sets the auto-delete flag. If this is set, the KSpell object
+ * is automatically deleted after emitting death().
+ */
+ void setAutoDelete(bool _autoDelete) { autoDelete = _autoDelete; }
+
+ /**
+ * Spellchecks a buffer of many words in plain text
+ * format.
+ *
+ * The @p _buffer is not modified. The signal done() will be
+ * sent when check() is finished and the argument will be a
+ * spell-corrected version of @p _buffer.
+ *
+ * The spell check may be stopped by the user before the entire buffer
+ * has been checked. You can check lastPosition() to see how far
+ * in @p _buffer check() reached before stopping.
+ */
+
+ virtual bool check (const QString &_buffer, bool usedialog = true);
+
+ /**
+ * Returns the position (when using check()) or word
+ * number (when using checkList()) of
+ * the last word checked.
+ */
+ int lastPosition() const
+ { return lastpos;}
+
+ /**
+ * Spellchecks a list of words.
+ *
+ * checkList() is more flexible than check(). You could parse
+ * any type
+ * of document (HTML, TeX, etc.) into a list of spell-checkable words
+ * and send the list to checkList(). Sending a marked-up document
+ * to check() would result in the mark-up tags being
+ * spell checked.
+ */
+ virtual bool checkList (QStringList *_wordlist, bool usedialog = true);
+
+ /**
+ * Spellchecks a single word.
+ *
+ * checkWord() is the most flexible function. Some applications
+ * might need this flexibility but will sacrifice speed when
+ * checking large numbers of words. Consider checkList() for
+ * checking many words.
+ *
+ * Use this method for implementing "online" spellchecking (i.e.,
+ * spellcheck as-you-type).
+ *
+ * checkWord() returns @p false if @p buffer is not a single word (e.g.
+ * if it contains white space), otherwise it returns @p true;
+ *
+ * If @p usedialog is set to @p true, KSpell will open the standard
+ * dialog if the word is not found. The dialog results can be queried
+ * by using dlgResult() and replacement().
+ *
+ * The signal corrected() is emitted when the check is
+ * complete. You can look at suggestions() to see what the
+ * suggested replacements were.
+ */
+ virtual bool checkWord (const QString &_buffer, bool usedialog = false);
+ bool checkWord( const QString & buffer, bool _usedialog, bool suggest );
+
+ /**
+ * Hides the dialog box.
+ *
+ * You'll need to do this when you are done with checkWord();
+ */
+ void hide ();
+
+ /**
+ * Returns list of suggested word replacements.
+ *
+ * After calling checkWord() (an in response to
+ * a misspelled() signal you can
+ * use this to get the list of
+ * suggestions (if any were available).
+ */
+ QStringList suggestions () const { return sugg; }
+
+ /**
+ * Gets the result code of the dialog box.
+ *
+ * After calling checkWord, you can use this to get the dialog box's
+ * result code.
+ * The possible
+ * values are (from kspelldlg.h):
+ * @li KS_CANCEL
+ * @li KS_REPLACE
+ * @li KS_REPLACEALL
+ * @li KS_IGNORE
+ * @li KS_IGNOREALL
+ * @li KS_ADD
+ * @li KS_STOP
+ *
+ */
+ int dlgResult () const
+ { return dlgresult; }
+
+ /**
+ * Moves the dialog.
+ *
+ * If the dialog is not currently visible, it will
+ * be placed at this position when it becomes visible.
+ * Use this to get the dialog out of the way of a highlighted
+ * misspelled word in a document.
+ */
+ void moveDlg (int x, int y);
+
+ /**
+ * Returns the height of the dialog box.
+ */
+ int heightDlg () const;
+ /**
+ * Returns the width of the dialog box.
+ */
+ int widthDlg () const;
+
+ /**
+ * Returns the partially spellchecked buffer.
+ *
+ * You might want the full buffer in its partially-checked state.
+ */
+ QString intermediateBuffer () const {return newbuffer;}
+
+ /**
+ * Tells ISpell/ASpell to ignore this word for the life of this KSpell instance.
+ *
+ * @return false if @p word is not a word or there was an error
+ * communicating with ISpell/ASpell.
+ */
+ virtual bool ignore (const QString & word);
+
+ /**
+ * Adds a word to the user's personal dictionary.
+ *
+ * @return false if @p word
+ * is not a word or there was an error communicating with ISpell/ASpell.
+ */
+ virtual bool addPersonal (const QString & word);
+
+ /**
+ * @return the KSpellConfig object being used by this KSpell instance.
+ */
+ KSpellConfig ksConfig () const;
+
+ /**
+ * Sets the resolution (in percent) of the progress() signals.
+ *
+ * E.g. setProgressResolution (10) instructs KSpell to send progress
+ * signals (at most) every 10% (10%, 20%, 30%...).
+ * The default is 10%.
+ */
+ void setProgressResolution (unsigned int res);
+
+ /**
+ * The destructor instructs ISpell/ASpell to write out the personal
+ * dictionary and then terminates ISpell/ASpell.
+ */
+ virtual ~KSpell();
+
+ /**
+ * @deprecated
+ * Performs a synchronous spellcheck.
+ *
+ * This method does not return until spellchecking is done or canceled.
+ * Your application's GUI will still be updated, however.
+ *
+ */
+ static int modalCheck( QString& text ) KDE_DEPRECATED;
+
+ /**
+ * Performs a synchronous spellcheck.
+ *
+ * This method does not return until spellchecking is done or canceled.
+ * Your application's GUI will still be updated, however.
+ *
+ * This overloaded method uses the spell-check configuration passed as parameter.
+ */
+ static int modalCheck( QString& text, KSpellConfig * kcs );
+
+ /**
+ * Call setIgnoreUpperWords(true) to tell the spell-checker to ignore
+ * words that are completely uppercase. They are spell-checked by default.
+ */
+ void setIgnoreUpperWords(bool b);
+
+ /**
+ * Call setIgnoreTitleCase(true) to tell the spell-checker to ignore
+ * words with a 'title' case, i.e. starting with an uppercase letter.
+ * They are spell-checked by default.
+ */
+ void setIgnoreTitleCase(bool b);
+
+signals:
+
+ /**
+ * Emitted whenever a misspelled word is found by check() or
+ * by checkWord().
+ * If it is emitted by checkWord(), @p pos=0.
+ * If it is emitted by check(), then @p pos indicates the position of
+ * the misspelled word in the (original) @p _buffer.
+ * (The first position is zero.)
+ * If it is emitted by checkList(), @p pos is the index to
+ * the misspelled
+ * word in the QStringList passed to checkList().
+ * Note, that @p originalword can be only a word part, if it's
+ * word with hyphens.
+ *
+ * These are called _before_ the dialog is opened, so that the
+ * calling program's GUI may be updated. (e.g. the misspelled word may
+ * be highlighted).
+ */
+ void misspelling (const QString & originalword, const QStringList & suggestions,
+ unsigned int pos);
+
+ /**
+ * Emitted after the "Replace" or "Replace All" buttons of the dialog
+ * was pressed, or if the word was
+ * corrected without calling the dialog (i.e., the user previously chose
+ * "Replace All" for this word).
+ *
+ * Results from the dialog may be checked with dlgResult()
+ * and replacement().
+ *
+ * Note, that when using checkList() this signal can occur
+ * more then once with same list position, when checking a word with
+ * hyphens. In this case @p originalword is the last replacement.
+ *
+ * @see check()
+ */
+ void corrected (const QString & originalword, const QString & newword, unsigned int pos);
+
+ /**
+ * Emitted when the user pressed "Ignore All" in the dialog.
+ * This could be used to make an application or file specific
+ * user dictionary.
+ *
+ */
+ void ignoreall (const QString & originalword);
+
+ /**
+ * Emitted when the user pressed "Ignore" in the dialog.
+ * Don't know if this could be useful.
+ *
+ */
+ void ignoreword (const QString & originalword);
+
+ /**
+ * Emitted when the user pressed "Add" in the dialog.
+ * This could be used to make an external user dictionary
+ * independent of the ISpell personal dictionary.
+ *
+ */
+ void addword (const QString & originalword);
+
+ /**
+ * Emitted when the user pressed "ReplaceAll" in the dialog.
+ */
+ void replaceall( const QString & origword , const QString &replacement );
+
+ /**
+ * Emitted after KSpell has verified that ISpell/ASpell is running
+ * and working properly.
+ */
+ void ready(KSpell *);
+
+ /**
+ * Emitted during a check().
+ * @p i is between 1 and 100.
+ */
+ void progress (unsigned int i);
+
+ /**
+ * Emitted when check() is done.
+ *
+ * Be sure to copy the results of @p buffer if you need them.
+ * You can only rely
+ * on the contents of buffer for the life of the slot which was signaled
+ * by done().
+ */
+ void done (const QString &buffer);
+
+ /**
+ * Emitted when checkList() is done.
+ *
+ * If the argument is
+ * @p true, then you should update your text from the
+ * wordlist, otherwise not.
+ */
+ void done(bool);
+
+ /**
+ * Emitted on terminal errors and after clean up.
+ *
+ * You can delete the KSpell object in this signal.
+ *
+ * You can check status() to see what caused the death:
+ * @li @p Error - KSpell could not start.
+ * @li @p Crashed - KSpell encountered an unexpected error during execution.
+ * @li @p Finished - Clean up finished.
+ */
+ void death( );
+
+
+protected slots:
+ /* All of those signals from KProcIO get sent here. */
+ void KSpell2 (KProcIO *);
+ void checkWord2 (KProcIO *);
+ void checkWord3 ();
+ void check2 (KProcIO *);
+ void checkList2 ();
+ void checkList3a (KProcIO *);
+ void checkListReplaceCurrent ();
+ void checkList4 ();
+ void dialog2 (int dlgresult);
+ void check3 ();
+ void suggestWord( KProcIO * );
+
+ void slotStopCancel (int);
+ void ispellExit (KProcess *);
+ void emitDeath();
+ void ispellErrors (KProcess *, char *, int);
+ void checkNext();
+
+private slots:
+ /**
+ * Used for modalCheck().
+ */
+ void slotModalReady();
+
+ /**
+ * Used for modalCheck().
+ */
+ void slotModalDone( const QString & );
+
+ /**
+ * Used for modalCheck().
+ */
+ void slotSpellCheckerCorrected( const QString & oldText, const QString & newText, unsigned int );
+
+ /**
+ * Used for modalCheck().
+ */
+ void slotModalSpellCheckerFinished( );
+
+signals:
+ void dialog3 ();
+
+protected:
+
+ KProcIO *proc;
+ QWidget *parent;
+ KSpellConfig *ksconfig;
+ KSpellDlg *ksdlg;
+ QStringList *wordlist;
+ QStringList::Iterator wlIt;
+ QStringList ignorelist;
+ QStringList replacelist;
+ QStringList sugg;
+ QTextCodec* codec;
+
+ spellStatus m_status;
+
+ bool usedialog;
+ bool texmode;
+ bool dlgon;
+ bool personaldict;
+ bool dialogwillprocess;
+ bool progressbar;
+ bool dialogsetup;
+ bool autoDelete;
+
+ QString caption;
+ QString orig;
+ QString origbuffer;
+ QString newbuffer;
+ QString cwword;
+ QString dlgorigword;
+ QString dlgreplacement;
+ QString dialog3slot;
+
+ int dlgresult;
+ int trystart;
+ int maxtrystart;
+ int lastpos;
+ unsigned int totalpos;
+ unsigned int lastline;
+ unsigned int posinline;
+ unsigned int lastlastline;
+ unsigned int offset;
+ unsigned int progres;
+ unsigned int curprog;
+
+ /**
+ * Used for modalCheck.
+ */
+ bool modaldlg;
+ static QString modaltext;
+ static int modalreturn;
+ static QWidget* modalWidgetHack;
+
+ int parseOneResponse (const QString &_buffer, QString &word, QStringList &sugg);
+ QString funnyWord (const QString & word);
+ void dialog (const QString & word, QStringList & sugg, const char* _slot);
+ QString replacement () const
+ { return dlgreplacement; }
+
+ void setUpDialog ( bool reallyusedialogbox = true);
+
+ void emitProgress ();
+ bool cleanFputs (const QString & s, bool appendCR=true);
+ bool cleanFputsWord (const QString & s, bool appendCR=true);
+ void startIspell();
+ bool writePersonalDictionary();
+ void initialize( QWidget *_parent, const QString &_caption,
+ QObject *obj, const char *slot, KSpellConfig *_ksc,
+ bool _progressbar, bool _modal, SpellerType type );
+
+private:
+ class KSpellPrivate;
+ KSpellPrivate *d;
+};
+
+#endif
diff --git a/kdeui/kspelldlg.cpp b/kdeui/kspelldlg.cpp
new file mode 100644
index 000000000..60607dd75
--- /dev/null
+++ b/kdeui/kspelldlg.cpp
@@ -0,0 +1,285 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 David Sweet <dsweet@kde.org>
+ Copyright (C) 2000 Rik Hemsley <rik@kde.org>
+ Copyright (C) 2000-2001 Wolfram Diestel <wolfram@steloj.de>
+ Copyright (C) 2003 Zack Rusin <zack@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qstringlist.h>
+#include <qpushbutton.h>
+#include <qlabel.h>
+#include <qlayout.h>
+
+#include <kapplication.h>
+#include <klocale.h>
+#include <klistbox.h>
+#include <kcombobox.h>
+#include <klistview.h>
+#include <klineedit.h>
+#include <kpushbutton.h>
+#include <kprogress.h>
+#include <kbuttonbox.h>
+#include <kdebug.h>
+
+#include "ksconfig.h"
+#include "kspelldlg.h"
+#include "kspellui.h"
+
+//to initially disable sorting in the suggestions listview
+#define NONSORTINGCOLUMN 2
+
+class KSpellDlg::KSpellDlgPrivate {
+public:
+ KSpellUI* ui;
+ KSpellConfig* spellConfig;
+};
+
+KSpellDlg::KSpellDlg( QWidget * parent, const char * name, bool _progressbar, bool _modal )
+ : KDialogBase(
+ parent, name, _modal, i18n("Check Spelling"), Help|Cancel|User1,
+ Cancel, true, i18n("&Finished")
+ ),
+ progressbar( false )
+{
+ Q_UNUSED( _progressbar );
+ d = new KSpellDlgPrivate;
+ d->ui = new KSpellUI( this );
+ setMainWidget( d->ui );
+
+ connect( d->ui->m_replaceBtn, SIGNAL(clicked()),
+ this, SLOT(replace()));
+ connect( this, SIGNAL(ready(bool)),
+ d->ui->m_replaceBtn, SLOT(setEnabled(bool)) );
+
+ connect( d->ui->m_replaceAllBtn, SIGNAL(clicked()), this, SLOT(replaceAll()));
+ connect(this, SIGNAL(ready(bool)), d->ui->m_replaceAllBtn, SLOT(setEnabled(bool)));
+
+ connect( d->ui->m_skipBtn, SIGNAL(clicked()), this, SLOT(ignore()));
+ connect( this, SIGNAL(ready(bool)), d->ui->m_skipBtn, SLOT(setEnabled(bool)));
+
+ connect( d->ui->m_skipAllBtn, SIGNAL(clicked()), this, SLOT(ignoreAll()));
+ connect( this, SIGNAL(ready(bool)), d->ui->m_skipAllBtn, SLOT(setEnabled(bool)));
+
+ connect( d->ui->m_addBtn, SIGNAL(clicked()), this, SLOT(add()));
+ connect( this, SIGNAL(ready(bool)), d->ui->m_addBtn, SLOT(setEnabled(bool)));
+
+ connect( d->ui->m_suggestBtn, SIGNAL(clicked()), this, SLOT(suggest()));
+ connect( this, SIGNAL(ready(bool)), d->ui->m_suggestBtn, SLOT(setEnabled(bool)) );
+ d->ui->m_suggestBtn->hide();
+
+ connect(this, SIGNAL(user1Clicked()), this, SLOT(stop()));
+
+ connect( d->ui->m_replacement, SIGNAL(textChanged(const QString &)),
+ SLOT(textChanged(const QString &)) );
+
+ connect( d->ui->m_replacement, SIGNAL(returnPressed()), SLOT(replace()) );
+ connect( d->ui->m_suggestions, SIGNAL(selectionChanged(QListViewItem*)),
+ SLOT(slotSelectionChanged(QListViewItem*)) );
+
+ connect( d->ui->m_suggestions, SIGNAL( doubleClicked ( QListViewItem *, const QPoint &, int ) ),
+ SLOT( replace() ) );
+ d->spellConfig = new KSpellConfig( 0, 0 ,0, false );
+ d->spellConfig->fillDicts( d->ui->m_language );
+ connect( d->ui->m_language, SIGNAL(activated(int)),
+ d->spellConfig, SLOT(sSetDictionary(int)) );
+ connect( d->spellConfig, SIGNAL(configChanged()),
+ SLOT(slotConfigChanged()) );
+
+ setHelp( "spelldlg", "kspell" );
+ setMinimumSize( sizeHint() );
+ emit ready( false );
+}
+
+KSpellDlg::~KSpellDlg()
+{
+ delete d->spellConfig;
+ delete d;
+}
+
+void
+KSpellDlg::init( const QString & _word, QStringList * _sugg )
+{
+ sugg = _sugg;
+ word = _word;
+
+ d->ui->m_suggestions->clear();
+ d->ui->m_suggestions->setSorting( NONSORTINGCOLUMN );
+ for ( QStringList::Iterator it = _sugg->begin(); it != _sugg->end(); ++it ) {
+ QListViewItem *item = new QListViewItem( d->ui->m_suggestions,
+ d->ui->m_suggestions->lastItem() );
+ item->setText( 0, *it );
+ }
+ kdDebug(750) << "KSpellDlg::init [" << word << "]" << endl;
+
+ emit ready( true );
+
+ d->ui->m_unknownWord->setText( _word );
+
+ if ( sugg->count() == 0 ) {
+ d->ui->m_replacement->setText( _word );
+ d->ui->m_replaceBtn->setEnabled( false );
+ d->ui->m_replaceAllBtn->setEnabled( false );
+ d->ui->m_suggestBtn->setEnabled( false );
+ } else {
+ d->ui->m_replacement->setText( (*sugg)[0] );
+ d->ui->m_replaceBtn->setEnabled( true );
+ d->ui->m_replaceAllBtn->setEnabled( true );
+ d->ui->m_suggestBtn->setEnabled( false );
+ d->ui->m_suggestions->setSelected( d->ui->m_suggestions->firstChild(), true );
+ }
+}
+
+void
+KSpellDlg::init( const QString& _word, QStringList* _sugg,
+ const QString& context )
+{
+ sugg = _sugg;
+ word = _word;
+
+ d->ui->m_suggestions->clear();
+ d->ui->m_suggestions->setSorting( NONSORTINGCOLUMN );
+ for ( QStringList::Iterator it = _sugg->begin(); it != _sugg->end(); ++it ) {
+ QListViewItem *item = new QListViewItem( d->ui->m_suggestions,
+ d->ui->m_suggestions->lastItem() );
+ item->setText( 0, *it );
+ }
+
+ kdDebug(750) << "KSpellDlg::init [" << word << "]" << endl;
+
+ emit ready( true );
+
+ d->ui->m_unknownWord->setText( _word );
+ d->ui->m_contextLabel->setText( context );
+
+ if ( sugg->count() == 0 ) {
+ d->ui->m_replacement->setText( _word );
+ d->ui->m_replaceBtn->setEnabled( false );
+ d->ui->m_replaceAllBtn->setEnabled( false );
+ d->ui->m_suggestBtn->setEnabled( false );
+ } else {
+ d->ui->m_replacement->setText( (*sugg)[0] );
+ d->ui->m_replaceBtn->setEnabled( true );
+ d->ui->m_replaceAllBtn->setEnabled( true );
+ d->ui->m_suggestBtn->setEnabled( false );
+ d->ui->m_suggestions->setSelected( d->ui->m_suggestions->firstChild(), true );
+ }
+}
+
+void
+KSpellDlg::slotProgress( unsigned int p )
+{
+ if (!progressbar)
+ return;
+
+ progbar->setValue( (int) p );
+}
+
+void
+KSpellDlg::textChanged( const QString & )
+{
+ d->ui->m_replaceBtn->setEnabled( true );
+ d->ui->m_replaceAllBtn->setEnabled( true );
+ d->ui->m_suggestBtn->setEnabled( true );
+}
+
+void
+KSpellDlg::slotSelectionChanged( QListViewItem* item )
+{
+ if ( item )
+ d->ui->m_replacement->setText( item->text( 0 ) );
+}
+
+/*
+ exit functions
+ */
+
+void
+KSpellDlg::closeEvent( QCloseEvent * )
+{
+ cancel();
+}
+
+void
+KSpellDlg::done( int result )
+{
+ emit command( result );
+}
+void
+KSpellDlg::ignore()
+{
+ newword = word;
+ done( KS_IGNORE );
+}
+
+void
+KSpellDlg::ignoreAll()
+{
+ newword = word;
+ done( KS_IGNOREALL );
+}
+
+void
+KSpellDlg::add()
+{
+ newword = word;
+ done( KS_ADD );
+}
+
+
+void
+KSpellDlg::cancel()
+{
+ newword = word;
+ done( KS_CANCEL );
+}
+
+void
+KSpellDlg::replace()
+{
+ newword = d->ui->m_replacement->text();
+ done( KS_REPLACE );
+}
+
+void
+KSpellDlg::stop()
+{
+ newword = word;
+ done( KS_STOP );
+}
+
+void
+KSpellDlg::replaceAll()
+{
+ newword = d->ui->m_replacement->text();
+ done( KS_REPLACEALL );
+}
+
+void
+KSpellDlg::suggest()
+{
+ newword = d->ui->m_replacement->text();
+ done( KS_SUGGEST );
+}
+
+void
+KSpellDlg::slotConfigChanged()
+{
+ d->spellConfig->writeGlobalSettings();
+ done( KS_CONFIG );
+}
+
+#include "kspelldlg.moc"
diff --git a/kdeui/kspelldlg.h b/kdeui/kspelldlg.h
new file mode 100644
index 000000000..532471cf3
--- /dev/null
+++ b/kdeui/kspelldlg.h
@@ -0,0 +1,114 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 David Sweet <dsweet@kde.org>
+ Copyright (C) 2000 Rik Hemsley <rik@kde.org>
+ Copyright (C) 2003 Zack Rusin <zack@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef __KSPELLDLG_H__
+#define __KSPELLDLG_H__
+
+#include <kdialogbase.h>
+
+class QStringList;
+class QLabel;
+class QListViewItem;
+class QPushButton;
+class KListBox;
+class KLineEdit;
+class KProgress;
+
+//Possible result codes
+enum KS_RESULT {
+ KS_CANCEL= 0,
+ KS_REPLACE= 1,
+ KS_REPLACEALL= 2,
+ KS_IGNORE= 3,
+ KS_IGNOREALL= 4,
+ KS_ADD= 5,
+ KS_STOP= 7,
+ KS_SUGGEST= 8,
+ KS_CONFIG= 9
+};
+
+class KDEUI_EXPORT KSpellDlg : public KDialogBase
+{
+ Q_OBJECT
+
+ class KSpellDlgPrivate;
+ KSpellDlgPrivate *d;
+ KLineEdit *editbox;
+ KProgress *progbar;
+ KListBox *listbox;
+ QStringList *sugg;
+ QPushButton *qpbrep, *qpbrepa;
+ QLabel *wordlabel;
+ QString word, newword;
+ bool progressbar;
+
+public:
+ KSpellDlg( QWidget *parent, const char *name,
+ bool _progressbar = false, bool _modal = false );
+ ~KSpellDlg();
+
+ QString replacement() const
+ { return newword; }
+
+ /**
+ * Change the misspelled word and suggested replacements
+ * and enable the disabled buttons on the dialog box.
+ * (Buttons are disabled by standby().)
+ **/
+ void init( const QString& _word, QStringList* _sugg );
+ void init( const QString& _word, QStringList* _sugg,
+ const QString& context );
+
+ void standby() { emit ready( false ); }
+
+ public slots:
+ /**
+ * Adjust the progress bar to @p p percent.
+ **/
+ void slotProgress( unsigned int p );
+
+protected:
+ virtual void closeEvent( QCloseEvent * e );
+ void done( int i );
+
+ signals:
+ /**
+ This signal is emitted when a button is pressed.
+ */
+ void command( int );
+
+ void ready( bool );
+
+protected slots:
+ void ignore();
+ void add();
+ void ignoreAll();
+ void cancel();
+ void replace();
+ void replaceAll();
+ void suggest();
+ void stop();
+ void slotConfigChanged();
+
+ void textChanged( const QString & );
+
+ void slotSelectionChanged( QListViewItem* item );
+};
+
+#endif
diff --git a/kdeui/kspellui.ui b/kdeui/kspellui.ui
new file mode 100644
index 000000000..496662797
--- /dev/null
+++ b/kdeui/kspellui.ui
@@ -0,0 +1,300 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>KSpellUI</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>KSpellUI</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>422</width>
+ <height>282</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="resizeMode">
+ <enum>Minimum</enum>
+ </property>
+ <widget class="QLabel" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Unknown word:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;&lt;p&gt;This word was considered to be an "unknown word" because it does not match any entry in the dictionary currently in use. It may also be a word in a foreign language.&lt;/p&gt;
+&lt;p&gt;If the word is not misspelled, you may add it to the dictionary by clicking &lt;b&gt;Add to Dictionary&lt;/b&gt;. If you don't want to add the unknown word to the dictionary, but you want to leave it unchanged, click &lt;b&gt;Ignore&lt;/b&gt; or &lt;b&gt;Ignore All&lt;/b&gt;.&lt;/p&gt;
+&lt;p&gt;However, if the word is misspelled, you can try to find the correct replacement in the list below. If you cannot find a replacement there, you may type it in the text box below, and click &lt;b&gt;Replace&lt;/b&gt; or &lt;b&gt;Replace All&lt;/b&gt;.&lt;/p&gt;
+&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="2">
+ <property name="name">
+ <cstring>m_unknownWord</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;b&gt;misspelled&lt;/b&gt;</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Unknown word</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;&lt;p&gt;This word was considered to be an "unknown word" because it does not match any entry in the dictionary currently in use. It may also be a word in a foreign language.&lt;/p&gt;
+&lt;p&gt;If the word is not misspelled, you may add it to the dictionary by clicking &lt;b&gt;Add to Dictionary&lt;/b&gt;. If you don't want to add the unknown word to the dictionary, but you want to leave it unchanged, click &lt;b&gt;Ignore&lt;/b&gt; or &lt;b&gt;Ignore All&lt;/b&gt;.&lt;/p&gt;
+&lt;p&gt;However, if the word is misspelled, you can try to find the correct replacement in the list below. If you cannot find a replacement there, you may type it in the text box below, and click &lt;b&gt;Replace&lt;/b&gt; or &lt;b&gt;Replace All&lt;/b&gt;.&lt;/p&gt;
+&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="8" column="0">
+ <property name="name">
+ <cstring>textLabel5</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Language:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_language</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;
+&lt;p&gt;Select the language of the document you are proofing here.&lt;/p&gt;
+&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0" rowspan="1" colspan="6">
+ <property name="name">
+ <cstring>m_contextLabel</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>Box</enum>
+ </property>
+ <property name="text">
+ <string>... the &lt;b&gt;misspelled&lt;/b&gt; word shown in context ...</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignCenter</set>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Text excerpt showing the unknown word in its context.</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;
+&lt;p&gt;Here you can see a text excerpt showing the unknown word in its context. If this information is not sufficient to choose the best replacement for the unknown word, you can click on the document you are proofing, read a larger part of the text and then return here to continue proofing.&lt;/p&gt;
+&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="1" column="4" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>m_addBtn</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;&lt; Add to Dictionary</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;
+&lt;p&gt;The unknown word was detected and considered unknown because it is not included in the dictionary.&lt;br&gt;
+Click here if you consider that the unknown word is not misspelled and you want to avoid wrongly detecting it again in the future. If you want to let it remain as is, but not add it to the dictionary, then click &lt;b&gt;Ignore&lt;/b&gt; or &lt;b&gt;Ignore All&lt;/b&gt; instead.&lt;/p&gt;
+&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <spacer row="1" column="3">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton" row="4" column="5">
+ <property name="name">
+ <cstring>m_replaceAllBtn</cstring>
+ </property>
+ <property name="text">
+ <string>R&amp;eplace All</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;
+&lt;p&gt;Click here to replace all occurrences of the unknown text with the text in the edit box above (to the left).&lt;/p&gt;
+&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QListView" row="3" column="0" rowspan="5" colspan="5">
+ <column>
+ <property name="text">
+ <string>Suggested Words</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>m_suggestions</cstring>
+ </property>
+ <property name="resizeMode">
+ <enum>AllColumns</enum>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Suggestion List</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;
+&lt;p&gt;If the unknown word is misspelled, you should check if the correction for it is available and if it is, click on it. If none of the words in this list is a good replacement you may type the correct word in the edit box above.&lt;/p&gt;
+&lt;p&gt;To correct this word click &lt;b&gt;Replace&lt;/b&gt; if you want to correct only this occurrence or &lt;b&gt;Replace All&lt;/b&gt; if you want to correct all occurrences.&lt;/p&gt;
+&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="3" column="5">
+ <property name="name">
+ <cstring>m_replaceBtn</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Replace</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;
+&lt;p&gt;Click here to replace this occurrence of the unknown text with the text in the edit box above (to the left).&lt;/p&gt;
+&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>Replace &amp;with:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>m_replacement</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;
+&lt;p&gt;If the unknown word is misspelled, you should type the correction for your misspelled word here or select it from the list below.&lt;/p&gt;
+&lt;p&gt;You can then click &lt;b&gt;Replace&lt;/b&gt; if you want to correct only this occurrence of the word or &lt;b&gt;Replace All&lt;/b&gt; if you want to correct all occurrences.&lt;/p&gt;
+&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="5" column="5">
+ <property name="name">
+ <cstring>m_skipBtn</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Ignore</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;
+&lt;p&gt;Click here to let this occurrence of the unknown word remain as is.&lt;/p&gt;
+&lt;p&gt;This action is useful when the word is a name, an acronym, a foreign word or any other unknown word that you want to use but not add to the dictionary.&lt;/p&gt;
+&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="6" column="5">
+ <property name="name">
+ <cstring>m_skipAllBtn</cstring>
+ </property>
+ <property name="text">
+ <string>I&amp;gnore All</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;
+&lt;p&gt;Click here to let all occurrences of the unknown word remain as they are.&lt;/p&gt;
+&lt;p&gt;This action is useful when the word is a name, an acronym, a foreign word or any other unknown word that you want to use but not add to the dictionary.&lt;/p&gt;
+&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="2" column="2" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>m_replacement</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;
+&lt;p&gt;If the unknown word is misspelled, you should type the correction for your misspelled word here or select it from the list below.&lt;/p&gt;
+&lt;p&gt;You can then click &lt;b&gt;Replace&lt;/b&gt; if you want to correct only this occurrence of the word or &lt;b&gt;Replace All&lt;/b&gt; if you want to correct all occurrences.&lt;/p&gt;
+&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="2" column="5">
+ <property name="name">
+ <cstring>m_suggestBtn</cstring>
+ </property>
+ <property name="text">
+ <string>S&amp;uggest</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="8" column="1" rowspan="1" colspan="4">
+ <item>
+ <property name="text">
+ <string>English</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_language</cstring>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Language Selection</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;
+&lt;p&gt;Select the language of the document you are proofing here.&lt;/p&gt;
+&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <spacer row="7" column="5" rowspan="2" colspan="1">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<tabstops>
+ <tabstop>m_addBtn</tabstop>
+ <tabstop>m_replacement</tabstop>
+ <tabstop>m_suggestBtn</tabstop>
+ <tabstop>m_replaceBtn</tabstop>
+ <tabstop>m_replaceAllBtn</tabstop>
+ <tabstop>m_skipBtn</tabstop>
+ <tabstop>m_skipAllBtn</tabstop>
+ <tabstop>m_suggestions</tabstop>
+ <tabstop>m_language</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kdeui/ksplashscreen.cpp b/kdeui/ksplashscreen.cpp
new file mode 100644
index 000000000..219af2595
--- /dev/null
+++ b/kdeui/ksplashscreen.cpp
@@ -0,0 +1,42 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2003 Chris Howells (howells@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <kconfig.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+
+#include <qpixmap.h>
+
+#include "ksplashscreen.h"
+
+KSplashScreen::KSplashScreen(const QPixmap &pixmap, WFlags f): QSplashScreen(pixmap, f)
+{
+ QRect desk = KGlobalSettings::splashScreenDesktopGeometry();
+ resize(pixmap.width(), pixmap.height());
+ setGeometry( ( desk.width() / 2 ) - ( width() / 2 ) + desk.left(),
+ ( desk.height() / 2 ) - ( height() / 2 ) + desk.top(),
+ width(), height() );
+
+}
+
+KSplashScreen::~KSplashScreen()
+{
+}
+
+#include "ksplashscreen.moc"
diff --git a/kdeui/ksplashscreen.h b/kdeui/ksplashscreen.h
new file mode 100644
index 000000000..d88ad478c
--- /dev/null
+++ b/kdeui/ksplashscreen.h
@@ -0,0 +1,62 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2003 Chris Howells (howells@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KSPLASHSCREEN_H
+#define KSPLASHSCREEN_H
+
+#include <qsplashscreen.h>
+
+#include <kdelibs_export.h>
+
+class QPixmap;
+
+/**
+ * @short %KDE splash screen
+ *
+ * This class is based on QSplashScreen and exists solely to make
+ * splash screens obey KDE's Xinerama settings.
+ *
+ * For documentation on how to use the class, see the documentation
+ * for QSplashScreen.
+ *
+ * @author Chris Howells (howells@kde.org)
+ * @since 3.2
+ */
+class KDEUI_EXPORT KSplashScreen : public QSplashScreen
+{
+ Q_OBJECT
+
+public:
+
+ /**
+ * Constructs a splash screen.
+ */
+ KSplashScreen(const QPixmap &pixmap, WFlags f = 0);
+
+ /**
+ * Destructor.
+ *
+ * Deletes all internal objects.
+ */
+ ~KSplashScreen();
+
+};
+
+#endif //KSPLASHSCREEN_H
+
diff --git a/kdeui/ksqueezedtextlabel.cpp b/kdeui/ksqueezedtextlabel.cpp
new file mode 100644
index 000000000..2f12d26ba
--- /dev/null
+++ b/kdeui/ksqueezedtextlabel.cpp
@@ -0,0 +1,87 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Ronny Standtke <Ronny.Standtke@gmx.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "ksqueezedtextlabel.h"
+#include "kstringhandler.h"
+#include <qtooltip.h>
+
+KSqueezedTextLabel::KSqueezedTextLabel( const QString &text , QWidget *parent, const char *name )
+ : QLabel ( parent, name ) {
+ setSizePolicy(QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ));
+ fullText = text;
+ squeezeTextToLabel();
+}
+
+KSqueezedTextLabel::KSqueezedTextLabel( QWidget *parent, const char *name )
+ : QLabel ( parent, name ) {
+ setSizePolicy(QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ));
+}
+
+void KSqueezedTextLabel::resizeEvent( QResizeEvent * ) {
+ squeezeTextToLabel();
+}
+
+QSize KSqueezedTextLabel::minimumSizeHint() const
+{
+ QSize sh = QLabel::minimumSizeHint();
+ sh.setWidth(-1);
+ return sh;
+}
+
+QSize KSqueezedTextLabel::sizeHint() const
+{
+ return QSize(contentsRect().width(), QLabel::sizeHint().height());
+}
+
+void KSqueezedTextLabel::setText( const QString &text ) {
+ fullText = text;
+ squeezeTextToLabel();
+}
+
+void KSqueezedTextLabel::squeezeTextToLabel() {
+ QFontMetrics fm(fontMetrics());
+ int labelWidth = size().width();
+ int textWidth = fm.width(fullText);
+ if (textWidth > labelWidth) {
+ QString squeezedText = KStringHandler::cPixelSqueeze(fullText, fm, labelWidth);
+ QLabel::setText(squeezedText);
+
+ QToolTip::remove( this );
+ QToolTip::add( this, fullText );
+
+ } else {
+ QLabel::setText(fullText);
+
+ QToolTip::remove( this );
+ QToolTip::hide();
+
+ }
+}
+
+void KSqueezedTextLabel::setAlignment( int alignment )
+{
+ // save fullText and restore it
+ QString tmpFull(fullText);
+ QLabel::setAlignment(alignment);
+ fullText = tmpFull;
+}
+
+void KSqueezedTextLabel::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "ksqueezedtextlabel.moc"
diff --git a/kdeui/ksqueezedtextlabel.h b/kdeui/ksqueezedtextlabel.h
new file mode 100644
index 000000000..5410d56c1
--- /dev/null
+++ b/kdeui/ksqueezedtextlabel.h
@@ -0,0 +1,84 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Ronny Standtke <Ronny.Standtke@gmx.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KSQUEEZEDTEXTLABEL_H
+#define KSQUEEZEDTEXTLABEL_H
+
+#include <qlabel.h>
+
+#include <kdelibs_export.h>
+
+/**
+ * @short A replacement for QLabel that squeezes its text
+ *
+ * A label class that squeezes its text into the label
+ *
+ * If the text is too long to fit into the label it is divided into
+ * remaining left and right parts which are separated by three dots.
+ *
+ * Example:
+ * http://www.kde.org/documentation/index.html could be squeezed to
+ * http://www.kde...ion/index.html
+ *
+ * \image html ksqueezedtextlabel.png "KSqueezedTextLabel Widget"
+ *
+ * @author Ronny Standtke <Ronny.Standtke@gmx.de>
+ */
+
+/*
+ * QLabel
+ */
+class KDEUI_EXPORT KSqueezedTextLabel : public QLabel {
+ Q_OBJECT
+
+public:
+ /**
+ * Default constructor.
+ */
+ KSqueezedTextLabel( QWidget *parent, const char *name = 0 );
+ KSqueezedTextLabel( const QString &text, QWidget *parent, const char *name = 0 );
+
+ virtual QSize minimumSizeHint() const;
+ virtual QSize sizeHint() const;
+ /**
+ * Overridden for internal reasons; the API remains unaffected.
+ */
+ virtual void setAlignment( int );
+
+public slots:
+ void setText( const QString & );
+
+protected:
+ /**
+ * used when widget is resized
+ */
+ void resizeEvent( QResizeEvent * );
+ /**
+ * does the dirty work
+ */
+ void squeezeTextToLabel();
+ QString fullText;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KSqueezedTextLabelPrivate;
+ KSqueezedTextLabelPrivate *d;
+};
+
+#endif // KSQUEEZEDTEXTLABEL_H
diff --git a/kdeui/kstatusbar.cpp b/kdeui/kstatusbar.cpp
new file mode 100644
index 000000000..8a2a964b5
--- /dev/null
+++ b/kdeui/kstatusbar.cpp
@@ -0,0 +1,156 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Mark Donohoe (donohoe@kde.org)
+ (C) 1997,1998, 2000 Sven Radej (radej@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <kdebug.h>
+#include <kstatusbar.h>
+#include <kconfig.h>
+#include <kglobal.h>
+
+
+KStatusBarLabel::KStatusBarLabel( const QString& text, int _id,
+ KStatusBar *parent, const char *name) :
+ QLabel( parent, name)
+{
+ id = _id;
+
+ setText( text );
+
+ // umm... Mosfet? Can you help here?
+
+ // Warning: QStatusBar draws shaded rectangle around every item - which
+ // IMHO is stupid.
+ // So NoFrame|Plain is the best you get. the problem is that only in case of
+ // StyledPanel|Something you get QFrame to call QStyle::drawPanel().
+
+ setLineWidth (0);
+ setFrameStyle (QFrame::NoFrame);
+
+ setAlignment( AlignHCenter | AlignVCenter | SingleLine );
+
+ connect (this, SIGNAL(itemPressed(int)), parent, SIGNAL(pressed(int)));
+ connect (this, SIGNAL(itemReleased(int)), parent, SIGNAL(released(int)));
+}
+
+void KStatusBarLabel::mousePressEvent (QMouseEvent *)
+{
+ emit itemPressed (id);
+}
+
+void KStatusBarLabel::mouseReleaseEvent (QMouseEvent *)
+{
+ emit itemReleased (id);
+}
+
+KStatusBar::KStatusBar( QWidget *parent, const char *name )
+ : QStatusBar( parent, name )
+{
+ // make the size grip stuff configurable
+ // ...but off by default (sven)
+ KConfig *config = KGlobal::config();
+ QString group(config->group());
+ config->setGroup(QString::fromLatin1("StatusBar style"));
+ bool grip_enabled = config->readBoolEntry(QString::fromLatin1("SizeGripEnabled"), false);
+ setSizeGripEnabled(grip_enabled);
+ config->setGroup(group);
+}
+
+KStatusBar::~KStatusBar ()
+{
+}
+
+void KStatusBar::insertItem( const QString& text, int id, int stretch, bool permanent)
+{
+ if (items[id])
+ kdDebug() << "KStatusBar::insertItem: item id " << id << " already exists." << endl;
+
+ KStatusBarLabel *l = new KStatusBarLabel (text, id, this);
+ l->setFixedHeight(fontMetrics().height()+2);
+ items.insert(id, l);
+ addWidget (l, stretch, permanent);
+ l->show();
+}
+
+void KStatusBar::removeItem (int id)
+{
+ KStatusBarLabel *l = items[id];
+ if (l)
+ {
+ removeWidget (l);
+ items.remove(id);
+ delete l;
+ }
+ else
+ kdDebug() << "KStatusBar::removeItem: bad item id: " << id << endl;
+}
+
+bool KStatusBar::hasItem( int id ) const
+{
+ KStatusBarLabel *l = items[id];
+ if (l)
+ return true;
+ else
+ return false;
+}
+
+void KStatusBar::changeItem( const QString& text, int id )
+{
+ KStatusBarLabel *l = items[id];
+ if (l)
+ {
+ l->setText(text);
+ if(l->minimumWidth () != l->maximumWidth ())
+ {
+ reformat();
+ }
+ }
+ else
+ kdDebug() << "KStatusBar::changeItem: bad item id: " << id << endl;
+}
+
+void KStatusBar::setItemAlignment (int id, int align)
+{
+ KStatusBarLabel *l = items[id];
+ if (l)
+ {
+ l->setAlignment(align);
+ }
+ else
+ kdDebug() << "KStatusBar::setItemAlignment: bad item id: " << id << endl;
+}
+
+void KStatusBar::setItemFixed(int id, int w)
+{
+ KStatusBarLabel *l = items[id];
+ if (l)
+ {
+ if (w==-1)
+ w=fontMetrics().boundingRect(l->text()).width()+3;
+
+ l->setFixedWidth(w);
+ }
+ else
+ kdDebug() << "KStatusBar::setItemFixed: bad item id: " << id << endl;
+}
+
+#include "kstatusbar.moc"
+
+//Eh!!!
+//Eh what ? :)
+
diff --git a/kdeui/kstatusbar.h b/kdeui/kstatusbar.h
new file mode 100644
index 000000000..9ba05dc5b
--- /dev/null
+++ b/kdeui/kstatusbar.h
@@ -0,0 +1,208 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Mark Donohoe (donohoe@kde.org)
+ Copyright (C) 1997, 1998 1998 Sven Radej (sven@lisa.exp.univie.ac.at)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __KSTATUSBAR_H__
+#define __KSTATUSBAR_H__
+
+#include <qstatusbar.h>
+#include <qintdict.h>
+#include <qlabel.h>
+#include <kdelibs_export.h>
+
+class KStatusBar;
+
+/**
+ * Internal label class for use in KStatusBar
+ * @internal
+ */
+class KDEUI_EXPORT KStatusBarLabel : public QLabel
+{
+ Q_OBJECT
+
+public:
+
+
+ KStatusBarLabel( const QString& text, int _id, KStatusBar* parent = 0L, const char *name=0L );
+ ~KStatusBarLabel () {}
+
+protected:
+
+ void mousePressEvent (QMouseEvent* _event);
+ void mouseReleaseEvent (QMouseEvent* _event);
+
+private:
+
+ int id;
+
+signals:
+
+ void itemPressed (int id);
+ void itemReleased (int id);
+};
+
+/**
+ * @short %KDE statusbar widget
+ *
+ * Display status messages.
+ *
+ * You can insert text labels or custom widgets. Their geometry is managed
+ * internally. KStatusBar resizes itself, but positioning is left to
+ * KMainWindow (or to you, if you don't use KMainWindow ).
+ *
+ * A special type of item is a message which is a temporary text-message
+ * displayed on top of other items in full-width. Messages are visible for
+ * specified time, or until you call the slot QStatusBar::clear(). See
+ * QStatusBar::message for details.
+ *
+ * It is useful to connect the KActionCollection signals to the
+ * QStatusBar::message slots.
+ *
+ * KStatusBar inherits QStatusBar, you can freely use all QStatusBar
+ * methods.
+ *
+ * Empty text items are not visible. They will become visible when you change
+ * (add) text.
+ *
+ * @author Mark Donohoe (donohoe@kde.org) Maintained by Sven Radej <radej@kde.org>
+
+ * @see KActionCollection
+ */
+class KDEUI_EXPORT KStatusBar : public QStatusBar
+{
+ Q_OBJECT
+
+public:
+ /**
+ * @deprecated
+ * WARNING: This enum is only for backward compatibility and it may be removed.
+ * No method here uses it.
+ */
+ enum BarStatus{ Toggle, Show, Hide };
+
+ /**
+ * Constructs a status bar. @p parent is usually KMainWindow.
+ */
+ KStatusBar( QWidget* parent = 0L, const char* name = 0L );
+
+ /**
+ * Destructor.
+ *
+ * Deletes all internal objects.
+ */
+ ~KStatusBar();
+
+ /**
+ * Inserts a text label into the status bar.
+ * Parameters @p stretch and @p permanent are passed to
+ * QStatusBar::addWidget .
+ *
+ * If @p permanent is true, then item will be placed on the far right of
+ * the statusbar and will never be hidden by QStatusBar::message.
+ *
+ * @param text The label's text string.
+ * @param id id of item
+ * @param stretch stretch passed to QStatusBar::addWidget
+ * @param permanent is item permanent or not (passed to QStatusBar::addWidget )
+ *
+ * @see QStatusbar::addWidget
+ *
+ */
+ void insertItem(const QString& text, int id, int stretch=0, bool permanent=false );
+
+ /**
+ * Inserts a fixed width text label into status bar. The width will be set
+ * according to @p text, but will remain fixed even if you change text.
+ * You can change fixed width by calling setItemFixed.
+ *
+ * @param text The label's text string
+ * @param id id of item
+ * @param permanent permanent flag passed to QStatusBar::addWidget
+ */
+ inline void insertFixedItem(const QString& text, int id, bool permanent=false)
+ { insertItem(text, id, 0, permanent); setItemFixed(id); }
+
+ /**
+ * Removes an item.
+ *
+ * @param id The item to remove.
+ */
+ void removeItem( int id );
+
+ /**
+ * @since 3.2
+ *
+ * Returns true if an item with @p id exists already in KStatusBar,
+ * otherwise returns false.
+ *
+ * @param id id of the item
+ */
+ bool hasItem( int id ) const;
+
+ /**
+ * Changes the text in a status bar field.
+ *
+ * The item will be resized to fit the text. If you change text to be empty,
+ * item will not be visible (untill you add some text).
+ *
+ * @param text The label's text string
+ * @param id The id of item.
+ */
+ void changeItem( const QString& text, int id );
+
+ /**
+ * Sets the alignment of item @p id. By default all fields are aligned
+ * @p AlignHCenter | @p AlignVCenter. See QLabel::setAlignment for details.
+ *
+ */
+ void setItemAlignment(int id, int align);
+
+ /**
+ * Sets item @p id to have fixed width. This cannot be undone, but you can
+ * always set new fixed width.
+ *
+ * @param id id of item
+ * @param width fixed width in pixels. Default -1 is to adapt to text width.
+ */
+ void setItemFixed(int id, int width=-1);
+
+signals:
+
+ /**
+ * Emitted when mouse is pressed over item @p id.
+ *
+ * Connect to this signal if you want to respond to mouse press events.
+ *
+ */
+ void pressed( int );
+
+ /**
+ * Emitted when mouse is released over item @p id.
+ *
+ * Connect to this signal if you want to respond to mouse release events (clicks).
+ */
+ void released( int );
+
+private:
+ QIntDict<KStatusBarLabel> items;
+ class KStatusBarPrivate* d;
+};
+
+#endif // __KSTATUSBAR_H__
+
diff --git a/kdeui/kstdaction.cpp b/kdeui/kstdaction.cpp
new file mode 100644
index 000000000..ae22c01c3
--- /dev/null
+++ b/kdeui/kstdaction.cpp
@@ -0,0 +1,323 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999,2000 Kurt Granroth <granroth@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kstdaction.h"
+
+#include <qtoolbutton.h>
+#include <qwhatsthis.h>
+
+#include <kaboutdata.h>
+#include <kaction.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kstdaccel.h>
+#include <kmainwindow.h>
+#include "kstdaction_p.h"
+
+namespace KStdAction
+{
+
+QStringList stdNames()
+{
+ return internal_stdNames();
+}
+
+KAction* create( StdAction id, const char *name, const QObject *recvr, const char *slot, KActionCollection* parent )
+{
+ KAction* pAction = 0;
+ const KStdActionInfo* pInfo = infoPtr( id );
+ kdDebug(125) << "KStdAction::create( " << id << "=" << (pInfo ? pInfo->psName : (const char*)0) << ", " << parent << ", " << name << " )" << endl; // ellis
+ if( pInfo ) {
+ QString sLabel, iconName = pInfo->psIconName;
+ switch( id ) {
+ case Back: sLabel = i18n("go back", "&Back");
+ if (QApplication::reverseLayout() )
+ iconName = "forward";
+ break;
+
+ case Forward: sLabel = i18n("go forward", "&Forward");
+ if (QApplication::reverseLayout() )
+ iconName = "back";
+ break;
+
+ case Home: sLabel = i18n("beginning (of line)", "&Home"); break;
+ case Help: sLabel = i18n("show help", "&Help"); break;
+ case AboutApp: iconName = kapp->miniIconName();
+ case Preferences:
+ case HelpContents:
+ {
+ const KAboutData *aboutData = KGlobal::instance()->aboutData();
+ /* TODO KDE4
+ const KAboutData *aboutData;
+ if ( parent )
+ aboutData = parent->instance()->aboutData();
+ else
+ aboutData = KGlobal::instance()->aboutData();
+ */
+ QString appName = (aboutData) ? aboutData->programName() : QString::fromLatin1(qApp->name());
+ sLabel = i18n(pInfo->psLabel).arg(appName);
+ }
+ break;
+ default: sLabel = i18n(pInfo->psLabel);
+ }
+
+ if (QApplication::reverseLayout()){
+ if (id == Prior) iconName = "forward";
+ if (id == Next ) iconName = "back";
+ if (id == FirstPage) iconName = "finish";
+ if (id == LastPage) iconName = "start";
+ }
+
+ KShortcut cut = KStdAccel::shortcut(pInfo->idAccel);
+ switch( id ) {
+ case OpenRecent:
+ pAction = new KRecentFilesAction( sLabel, pInfo->psIconName, cut,
+ recvr, slot,
+ parent, (name) ? name : pInfo->psName );
+ break;
+ case ShowMenubar:
+ case ShowToolbar:
+ case ShowStatusbar:
+ {
+ KToggleAction *ret;
+ ret = new KToggleAction( sLabel, pInfo->psIconName, cut,
+ recvr, slot,
+ parent, (name) ? name : pInfo->psName );
+ ret->setChecked( true );
+ pAction = ret;
+ break;
+ }
+ case FullScreen:
+ {
+ KToggleFullScreenAction *ret;
+ ret = new KToggleFullScreenAction( cut, recvr, slot,
+ parent, NULL, (name) ? name : pInfo->psName );
+ ret->setChecked( false );
+ pAction = ret;
+ break;
+ }
+ case PasteText:
+ {
+ KPasteTextAction *ret;
+ ret = new KPasteTextAction(sLabel, iconName, cut,
+ recvr, slot,
+ parent, (name) ? name : pInfo->psName );
+ pAction = ret;
+ break;
+ }
+ default:
+ pAction = new KAction( sLabel, iconName, cut,
+ recvr, slot,
+ parent, (name) ? name : pInfo->psName );
+ break;
+ }
+ }
+ return pAction;
+}
+
+const char* name( StdAction id )
+{
+ const KStdActionInfo* pInfo = infoPtr( id );
+ return (pInfo) ? pInfo->psName : 0;
+}
+
+KAction *openNew( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( New, name, recvr, slot, parent ); }
+KAction *open( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Open, name, recvr, slot, parent ); }
+KRecentFilesAction *openRecent( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return (KRecentFilesAction*) KStdAction::create( OpenRecent, name, recvr, slot, parent ); }
+KAction *save( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Save, name, recvr, slot, parent ); }
+KAction *saveAs( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( SaveAs, name, recvr, slot, parent ); }
+KAction *revert( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Revert, name, recvr, slot, parent ); }
+KAction *print( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Print, name, recvr, slot, parent ); }
+KAction *printPreview( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( PrintPreview, name, recvr, slot, parent ); }
+KAction *close( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Close, name, recvr, slot, parent ); }
+KAction *mail( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Mail, name, recvr, slot, parent ); }
+KAction *quit( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Quit, name, recvr, slot, parent ); }
+KAction *undo( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Undo, name, recvr, slot, parent ); }
+KAction *redo( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Redo, name, recvr, slot, parent ); }
+KAction *cut( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Cut, name, recvr, slot, parent ); }
+KAction *copy( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Copy, name, recvr, slot, parent ); }
+KAction *paste( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Paste, name, recvr, slot, parent ); }
+KAction *pasteText( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( PasteText, name, recvr, slot, parent ); }
+KAction *clear( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Clear, name, recvr, slot, parent ); }
+KAction *selectAll( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( SelectAll, name, recvr, slot, parent ); }
+KAction *deselect( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Deselect, name, recvr, slot, parent ); }
+KAction *find( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Find, name, recvr, slot, parent ); }
+KAction *findNext( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( FindNext, name, recvr, slot, parent ); }
+KAction *findPrev( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( FindPrev, name, recvr, slot, parent ); }
+KAction *replace( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Replace, name, recvr, slot, parent ); }
+KAction *actualSize( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( ActualSize, name, recvr, slot, parent ); }
+KAction *fitToPage( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( FitToPage, name, recvr, slot, parent ); }
+KAction *fitToWidth( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( FitToWidth, name, recvr, slot, parent ); }
+KAction *fitToHeight( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( FitToHeight, name, recvr, slot, parent ); }
+KAction *zoomIn( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( ZoomIn, name, recvr, slot, parent ); }
+KAction *zoomOut( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( ZoomOut, name, recvr, slot, parent ); }
+KAction *zoom( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Zoom, name, recvr, slot, parent ); }
+KAction *redisplay( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Redisplay, name, recvr, slot, parent ); }
+KAction *up( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Up, name, recvr, slot, parent ); }
+KAction *back( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Back, name, recvr, slot, parent ); }
+KAction *forward( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Forward, name, recvr, slot, parent ); }
+KAction *home( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Home, name, recvr, slot, parent ); }
+KAction *prior( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Prior, name, recvr, slot, parent ); }
+KAction *next( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Next, name, recvr, slot, parent ); }
+KAction *goTo( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Goto, name, recvr, slot, parent ); }
+KAction *gotoPage( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( GotoPage, name, recvr, slot, parent ); }
+KAction *gotoLine( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( GotoLine, name, recvr, slot, parent ); }
+KAction *firstPage( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( FirstPage, name, recvr, slot, parent ); }
+KAction *lastPage( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( LastPage, name, recvr, slot, parent ); }
+KAction *addBookmark( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( AddBookmark, name, recvr, slot, parent ); }
+KAction *editBookmarks( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( EditBookmarks, name, recvr, slot, parent ); }
+KAction *spelling( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Spelling, name, recvr, slot, parent ); }
+
+KToggleAction *showMenubar( const QObject *recvr, const char *slot, KActionCollection* parent, const char *_name )
+{
+ KToggleAction *ret;
+ ret = new KToggleAction(i18n("Show &Menubar"), "showmenu", KStdAccel::shortcut(KStdAccel::ShowMenubar), recvr, slot,
+ parent, _name ? _name : name(ShowMenubar));
+ ret->setWhatsThis( i18n( "Show Menubar<p>"
+ "Shows the menubar again after it has been hidden" ) );
+ KGuiItem guiItem( i18n("Hide &Menubar"), 0 /*same icon*/, QString::null,
+ i18n( "Hide Menubar<p>"
+ "Hide the menubar. You can usually get it back using the right mouse button inside the window itself." ) );
+ ret->setCheckedState( guiItem );
+ ret->setChecked(true);
+ return ret;
+}
+
+// obsolete
+KToggleAction *showToolbar( const QObject *recvr, const char *slot, KActionCollection* parent, const char *_name )
+{
+ KToggleAction *ret;
+ ret = new KToggleAction(i18n("Show &Toolbar"), 0, recvr, slot, parent,
+ _name ? _name : name(ShowToolbar));
+ ret->setChecked(true);
+ return ret;
+
+}
+
+// obsolete
+KToggleToolBarAction *showToolbar( const char* toolBarName, KActionCollection* parent, const char *_name )
+{
+ KToggleToolBarAction *ret;
+ ret = new KToggleToolBarAction(toolBarName, i18n("Show &Toolbar"), parent,
+ _name ? _name : name(ShowToolbar));
+ return ret;
+}
+
+KToggleAction *showStatusbar( const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *_name )
+{
+ KToggleAction *ret;
+ ret = new KToggleAction(i18n("Show St&atusbar"), 0, recvr, slot, parent,
+ _name ? _name : name(ShowStatusbar));
+ ret->setWhatsThis( i18n( "Show Statusbar<p>"
+ "Shows the statusbar, which is the bar at the bottom of the window used for status information." ) );
+ KGuiItem guiItem( i18n("Hide St&atusbar"), QString::null, QString::null,
+ i18n( "Hide Statusbar<p>"
+ "Hides the statusbar, which is the bar at the bottom of the window used for status information." ) );
+ ret->setCheckedState( guiItem );
+
+ ret->setChecked(true);
+ return ret;
+}
+
+KToggleFullScreenAction *fullScreen( const QObject *recvr, const char *slot, KActionCollection* parent,
+ QWidget* window, const char *name )
+{
+ KToggleFullScreenAction *ret;
+ ret = static_cast< KToggleFullScreenAction* >( KStdAction::create( FullScreen, name, recvr, slot, parent ));
+ ret->setWindow( window );
+ return ret;
+}
+
+KAction *saveOptions( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( SaveOptions, name, recvr, slot, parent ); }
+KAction *keyBindings( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( KeyBindings, name, recvr, slot, parent ); }
+KAction *preferences( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Preferences, name, recvr, slot, parent ); }
+KAction *configureToolbars( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( ConfigureToolbars, name, recvr, slot, parent ); }
+KAction *configureNotifications( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( ConfigureNotifications, name, recvr, slot, parent ); }
+KAction *help( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( Help, name, recvr, slot, parent ); }
+KAction *helpContents( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( HelpContents, name, recvr, slot, parent ); }
+KAction *whatsThis( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( WhatsThis, name, recvr, slot, parent ); }
+KAction *tipOfDay( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( TipofDay, name, recvr, slot, parent ); }
+KAction *reportBug( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( ReportBug, name, recvr, slot, parent ); }
+KAction *switchApplicationLanguage( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( SwitchApplicationLanguage, name, recvr, slot, parent ); }
+KAction *aboutApp( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( AboutApp, name, recvr, slot, parent ); }
+KAction *aboutKDE( const QObject *recvr, const char *slot, KActionCollection* parent, const char *name )
+ { return KStdAction::create( AboutKDE, name, recvr, slot, parent ); }
+
+}
diff --git a/kdeui/kstdaction.h b/kdeui/kstdaction.h
new file mode 100644
index 000000000..d45f76b99
--- /dev/null
+++ b/kdeui/kstdaction.h
@@ -0,0 +1,614 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999,2000 Kurt Granroth <granroth@kde.org>
+ Copyright (C) 2001,2002 Ellis Whitehead <ellis@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef KSTDACTION_H
+#define KSTDACTION_H
+
+class QObject;
+class QWidget;
+class KAction;
+class KActionCollection;
+class KRecentFilesAction;
+class KToggleAction;
+class KToggleToolBarAction;
+class KToggleFullScreenAction;
+
+#include <qstringlist.h>
+
+#include <kdelibs_export.h>
+
+/**
+ * Convenience methods to access all standard KDE actions.
+ *
+ * These actions should be used instead of hardcoding menubar and
+ * toolbar items. Using these actions helps your application easily
+ * conform to the KDE UI Style Guide
+ * @see http://developer.kde.org/documentation/standards/kde/style/basics/index.html .
+ *
+ * All of the documentation for KAction holds for KStdAction
+ * also. When in doubt on how things work, check the KAction
+ * documention first.
+ *
+ * <b>Simple Example:</b>\n
+ *
+ * In general, using standard actions should be a drop in replacement
+ * for regular actions. For example, if you previously had:
+ *
+ * \code
+ * KAction *newAct = new KAction(i18n("&New"), QIconSet(BarIcon("filenew")),
+ * KStdAccel::shortcut(KStdAccel::New), this,
+ * SLOT(fileNew()), actionCollection());
+ * \endcode
+ *
+ * You could drop that and replace it with:
+ *
+ * \code
+ * KAction *newAct = KStdAction::openNew(this, SLOT(fileNew()),
+ * actionCollection());
+ * \endcode
+ *
+ * <b>Non-standard Usages</b>\n
+ *
+ * It is possible to use the standard actions in various
+ * non-recommended ways. Say, for instance, you wanted to have a
+ * standard action (with the associated correct text and icon and
+ * accelerator, etc) but you didn't want it to go in the standard
+ * place (this is not recommended, by the way). One way to do this is
+ * to simply not use the XML UI framework and plug it into wherever
+ * you want. If you do want to use the XML UI framework (good!), then
+ * it is still possible.
+ *
+ * Basically, the XML building code matches names in the XML code with
+ * the internal names of the actions. You can find out the internal
+ * names of each of the standard actions by using the stdName
+ * action like so: KStdAction::stdName(KStdAction::Cut) would return
+ * 'edit_cut'. The XML building code will match 'edit_cut' to the
+ * attribute in the global XML file and place your action there.
+ *
+ * However, you can change the internal name. In this example, just
+ * do something like:
+ *
+ * \code
+ * (void)KStdAction::cut(this, SLOT(editCut()), actionCollection(), "my_cut");
+ * \endcode
+ *
+ * Now, in your local XML resource file (e.g., yourappui.rc), simply
+ * put 'my_cut' where you want it to go.
+ *
+ * Another non-standard usage concerns getting a pointer to an
+ * existing action if, say, you want to enable or disable the action.
+ * You could do it the recommended way and just grab a pointer when
+ * you instantiate it as in the the 'openNew' example above... or you
+ * could do it the hard way:
+ *
+ * \code
+ * KAction *cut = actionCollection()->action(KStdAction::stdName(KStdAction::Cut));
+ * \endcode
+ *
+ * Another non-standard usage concerns instantiating the action in the
+ * first place. Usually, you would use the member functions as
+ * shown above (e.g., KStdAction::cut(this, SLOT, parent)). You
+ * may, however, do this using the enums provided. This author can't
+ * think of a reason why you would want to, but, hey, if you do,
+ * here's how:
+ *
+ * \code
+ * (void)KStdAction::action(KStdAction::New, this, SLOT(fileNew()), actionCollection());
+ * (void)KStdAction::action(KStdAction::Cut, this, SLOT(editCut()), actionCollection());
+ * \endcode
+ *
+ * @author Kurt Granroth <granroth@kde.org>
+ */
+namespace KStdAction
+{
+ /**
+ * The standard menubar and toolbar actions.
+ */
+ enum StdAction {
+ ActionNone,
+
+ // File Menu
+ New, Open, OpenRecent, Save, SaveAs, Revert, Close,
+ Print, PrintPreview, Mail, Quit,
+
+ // Edit Menu
+ Undo, Redo, Cut, Copy, Paste, SelectAll, Deselect, Find, FindNext, FindPrev,
+ Replace,
+
+ // View Menu
+ ActualSize, FitToPage, FitToWidth, FitToHeight, ZoomIn, ZoomOut,
+ Zoom, Redisplay,
+
+ // Go Menu
+ Up, Back, Forward, Home, Prior, Next, Goto, GotoPage, GotoLine,
+ FirstPage, LastPage,
+
+ // Bookmarks Menu
+ AddBookmark, EditBookmarks,
+
+ // Tools Menu
+ Spelling,
+
+ // Settings Menu
+ ShowMenubar, ShowToolbar, ShowStatusbar,
+ SaveOptions, KeyBindings,
+ Preferences, ConfigureToolbars,
+
+ // Help Menu
+ Help, HelpContents, WhatsThis, ReportBug, AboutApp, AboutKDE,
+ TipofDay, ///< @since 3.1
+
+ // Another settings menu item
+ ConfigureNotifications,
+ FullScreen, ///< @since 3.2
+ Clear, ///< @since 3.2
+ PasteText, ///< @since 3.2
+ SwitchApplicationLanguage ///< @since 3.5.8
+ };
+
+ /**
+ * Creates an action corresponding to the
+ * KStdAction::StdAction enum.
+ */
+ KDEUI_EXPORT KAction* create( StdAction id, const char *name,
+ const QObject *recvr, const char *slot,
+ KActionCollection* parent );
+
+ inline KAction* create( StdAction id,
+ const QObject *recvr, const char *slot,
+ KActionCollection* parent )
+ { return KStdAction::create( id, 0, recvr, slot, parent ); }
+
+ /**
+ * @obsolete. Creates an action corresponding to the
+ * KStdAction::StdAction enum.
+ */
+ inline KAction *action(StdAction act_enum,
+ const QObject *recvr, const char *slot,
+ KActionCollection *parent, const char *name = 0L )
+ { return KStdAction::create( act_enum, name, recvr, slot, parent ); }
+
+ /**
+ * This will return the internal name of a given standard action.
+ */
+ KDEUI_EXPORT const char* name( StdAction id );
+
+ /// @obsolete. Use name()
+ inline const char* stdName(StdAction act_enum) { return name( act_enum ); }
+
+ /**
+ * Returns a list of all standard names. Used by KAccelManager
+ * to give those heigher weight.
+ * @since 3.1
+ */
+ KDEUI_EXPORT QStringList stdNames();
+
+ /**
+ * Create a new document or window.
+ */
+ KDEUI_EXPORT KAction *openNew(const QObject *recvr, const char *slot, KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Open an existing file.
+ */
+ KDEUI_EXPORT KAction *open(const QObject *recvr, const char *slot, KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Open a recently used document. The signature of the slot being called
+ * is of the form slotURLSelected( const KURL & ).
+ * @param recvr object to receive slot
+ * @param slot The SLOT to invoke when a URL is selected. The slot's
+ * signature is slotURLSelected( const KURL & ).
+ * @param parent parent widget
+ * @param name name of widget
+ */
+ KDEUI_EXPORT KRecentFilesAction *openRecent(const QObject *recvr, const char *slot, KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Save the current document.
+ */
+ KDEUI_EXPORT KAction *save(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Save the current document under a different name.
+ */
+ KDEUI_EXPORT KAction *saveAs(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Revert the current document to the last saved version
+ * (essentially will undo all changes).
+ */
+ KDEUI_EXPORT KAction *revert(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Close the current document.
+ */
+ KDEUI_EXPORT KAction *close(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Print the current document.
+ */
+ KDEUI_EXPORT KAction *print(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Show a print preview of the current document.
+ */
+ KDEUI_EXPORT KAction *printPreview(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Mail this document.
+ */
+ KDEUI_EXPORT KAction *mail(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Quit the program.
+ */
+ KDEUI_EXPORT KAction *quit(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Undo the last operation.
+ */
+ KDEUI_EXPORT KAction *undo(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Redo the last operation.
+ */
+ KDEUI_EXPORT KAction *redo(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Cut selected area and store it in the clipboard.
+ */
+ KDEUI_EXPORT KAction *cut(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Copy the selected area into the clipboard.
+ */
+ KDEUI_EXPORT KAction *copy(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Paste the contents of clipboard at the current mouse or cursor
+ * position.
+ */
+ KDEUI_EXPORT KAction *paste(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Paste the contents of clipboard at the current mouse or cursor
+ * position. Provide a button on the toolbar with the clipboard history
+ * menu if Klipper is running.
+ * @since 3.2
+ */
+ KDEUI_EXPORT KAction *pasteText(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Clear the content of the focus widget
+ * @since 3.2
+ */
+ KDEUI_EXPORT KAction *clear(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Select all elements in the current document.
+ */
+ KDEUI_EXPORT KAction *selectAll(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Deselect any selected elements in the current document.
+ */
+ KDEUI_EXPORT KAction *deselect(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Initiate a 'find' request in the current document.
+ */
+ KDEUI_EXPORT KAction *find(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Find the next instance of a stored 'find'.
+ */
+ KDEUI_EXPORT KAction *findNext(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Find a previous instance of a stored 'find'.
+ */
+ KDEUI_EXPORT KAction *findPrev(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Find and replace matches.
+ */
+ KDEUI_EXPORT KAction *replace(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * View the document at its actual size.
+ */
+ KDEUI_EXPORT KAction *actualSize(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Fit the document view to the size of the current window.
+ */
+ KDEUI_EXPORT KAction *fitToPage(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Fit the document view to the width of the current window.
+ */
+ KDEUI_EXPORT KAction *fitToWidth(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Fit the document view to the height of the current window.
+ */
+ KDEUI_EXPORT KAction *fitToHeight(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Zoom in.
+ */
+ KDEUI_EXPORT KAction *zoomIn(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Zoom out.
+ */
+ KDEUI_EXPORT KAction *zoomOut(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Popup a zoom dialog.
+ */
+ KDEUI_EXPORT KAction *zoom(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Redisplay or redraw the document.
+ */
+ KDEUI_EXPORT KAction *redisplay(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Move up (web style menu).
+ */
+ KDEUI_EXPORT KAction *up(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Move back (web style menu).
+ */
+ KDEUI_EXPORT KAction *back(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Move forward (web style menu).
+ */
+ KDEUI_EXPORT KAction *forward(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Go to the "Home" position or document.
+ */
+ KDEUI_EXPORT KAction *home(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Scroll up one page.
+ */
+ KDEUI_EXPORT KAction *prior(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Scroll down one page.
+ */
+ KDEUI_EXPORT KAction *next(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Go to somewhere in general.
+ */
+ KDEUI_EXPORT KAction *goTo(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+
+ /**
+ * Go to a specific page (dialog).
+ */
+ KDEUI_EXPORT KAction *gotoPage(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Go to a specific line (dialog).
+ */
+ KDEUI_EXPORT KAction *gotoLine(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Jump to the first page.
+ */
+ KDEUI_EXPORT KAction *firstPage(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Jump to the last page.
+ */
+ KDEUI_EXPORT KAction *lastPage(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Add the current page to the bookmarks tree.
+ */
+ KDEUI_EXPORT KAction *addBookmark(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Edit the application bookmarks.
+ */
+ KDEUI_EXPORT KAction *editBookmarks(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Pop up the spell checker.
+ */
+ KDEUI_EXPORT KAction *spelling(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+
+ /**
+ * Show/Hide the menubar.
+ */
+ KDEUI_EXPORT KToggleAction *showMenubar(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * @obsolete. toolbar actions are created automatically now in the
+ * Settings menu. Don't use this anymore.
+ * See: KMainWindow::createStandardStatusBarAction()
+ * Show/Hide the primary toolbar.
+ * @since 3.1
+ */
+ KDEUI_EXPORT KToggleAction *showToolbar(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 ) KDE_DEPRECATED;
+ /**
+ * @obsolete. toolbar actions are created automatically now in the
+ * Settings menu. Don't use this anymore.
+ * See: KMainWindow::setStandardToolBarMenuEnabled(bool);
+ * Show/Hide the primary toolbar.
+ */
+ KDEUI_EXPORT KToggleToolBarAction *showToolbar(const char* toolBarName,
+ KActionCollection* parent, const char *name = 0 ) KDE_DEPRECATED;
+
+ /**
+ * Show/Hide the statusbar.
+ */
+ KDEUI_EXPORT KToggleAction *showStatusbar(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Switch to/from full screen mode
+ * @since 3.2
+ */
+ KDEUI_EXPORT KToggleFullScreenAction *fullScreen(const QObject *recvr, const char *slot,
+ KActionCollection* parent, QWidget* window, const char *name = 0 );
+
+ /**
+ * Display the save options dialog.
+ */
+ KDEUI_EXPORT KAction *saveOptions(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Display the configure key bindings dialog.
+ *
+ * Note that you might be able to use the pre-built KXMLGUIFactory's fuction:
+ * KStdAction::keyBindings(guiFactory(), SLOT(configureShortcuts()), actionCollection());
+ */
+ KDEUI_EXPORT KAction *keyBindings(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Display the preferences/options dialog.
+ */
+ KDEUI_EXPORT KAction *preferences(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * The Customize Toolbar dialog.
+ */
+ KDEUI_EXPORT KAction *configureToolbars(const QObject *recvr,
+ const char *slot,
+ KActionCollection* parent,
+ const char *name = 0 );
+
+ /**
+ * The Configure Notifications dialog.
+ * @since 3.1
+ */
+ KDEUI_EXPORT KAction *configureNotifications(const QObject *recvr,
+ const char *slot,
+ KActionCollection *parent,
+ const char *name = 0);
+
+ /**
+ * Display the help.
+ */
+ KDEUI_EXPORT KAction *help(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Display the help contents.
+ */
+ KDEUI_EXPORT KAction *helpContents(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Trigger the What's This cursor.
+ */
+ KDEUI_EXPORT KAction *whatsThis(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Display "Tip of the Day"
+ * @since 3.1
+ */
+ KDEUI_EXPORT KAction *tipOfDay(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Open up the Report Bug dialog.
+ */
+ KDEUI_EXPORT KAction *reportBug(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Display the application's About box.
+ */
+ KDEUI_EXPORT KAction *aboutApp(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Display the About KDE dialog.
+ */
+ KDEUI_EXPORT KAction *aboutKDE(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+
+ /**
+ * Display "Switch application language" dialog.
+ * @since 3.5.8
+ */
+ KDEUI_EXPORT KAction *switchApplicationLanguage(const QObject *recvr, const char *slot,
+ KActionCollection* parent, const char *name = 0 );
+}
+
+#endif // KSTDACTION_H
diff --git a/kdeui/kstdaction_p.h b/kdeui/kstdaction_p.h
new file mode 100644
index 000000000..e41002508
--- /dev/null
+++ b/kdeui/kstdaction_p.h
@@ -0,0 +1,139 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999,2000 Kurt Granroth <granroth@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _KSTDACTION_PRIVATE_H_
+#define _KSTDACTION_PRIVATE_H_
+
+#include <klocale.h>
+#include <kstdaccel.h>
+
+namespace KStdAction
+{
+
+struct KStdActionInfo
+{
+ StdAction id;
+ KStdAccel::StdAccel idAccel;
+ const char* psName;
+ const char* psLabel;
+ const char* psWhatsThis;
+ const char* psIconName;
+};
+
+static const KStdActionInfo g_rgActionInfo[] =
+{
+ { New, KStdAccel::New, "file_new", I18N_NOOP("&New"), 0, "filenew" },
+ { Open, KStdAccel::Open, "file_open", I18N_NOOP("&Open..."), 0, "fileopen" },
+ { OpenRecent, KStdAccel::AccelNone, "file_open_recent", I18N_NOOP("Open &Recent"), 0, "fileopen" },
+ { Save, KStdAccel::Save, "file_save", I18N_NOOP("&Save"), 0, "filesave" },
+ { SaveAs, KStdAccel::AccelNone, "file_save_as", I18N_NOOP("Save &As..."), 0, "filesaveas" },
+ { Revert, KStdAccel::AccelNone, "file_revert", I18N_NOOP("Re&vert"), 0, "revert" },
+ { Close, KStdAccel::Close, "file_close", I18N_NOOP("&Close"), 0, "fileclose" },
+ { Print, KStdAccel::Print, "file_print", I18N_NOOP("&Print..."), 0, "fileprint" },
+ { PrintPreview, KStdAccel::AccelNone, "file_print_preview", I18N_NOOP("Print Previe&w..."), 0, "filequickprint" },
+ { Mail, KStdAccel::AccelNone, "file_mail", I18N_NOOP("&Mail..."), 0, "mail_send" },
+ { Quit, KStdAccel::Quit, "file_quit", I18N_NOOP("&Quit"), 0, "exit" },
+
+ { Undo, KStdAccel::Undo, "edit_undo", I18N_NOOP("&Undo"), 0, "undo" },
+ { Redo, KStdAccel::Redo, "edit_redo", I18N_NOOP("Re&do"), 0, "redo" },
+ { Cut, KStdAccel::Cut, "edit_cut", I18N_NOOP("Cu&t"), 0, "editcut" },
+ { Copy, KStdAccel::Copy, "edit_copy", I18N_NOOP("&Copy"), 0, "editcopy" },
+ { Paste, KStdAccel::Paste, "edit_paste", I18N_NOOP("&Paste"), 0, "editpaste" },
+ { PasteText, KStdAccel::Paste, "edit_paste", I18N_NOOP("&Paste"), 0, "editpaste" },
+ { Clear, KStdAccel::AccelNone, "edit_clear", I18N_NOOP("C&lear"), 0, "editclear" },
+ { SelectAll, KStdAccel::SelectAll, "edit_select_all", I18N_NOOP("Select &All"), 0, 0 },
+ { Deselect, KStdAccel::Deselect, "edit_deselect", I18N_NOOP("Dese&lect"), 0, 0 },
+ { Find, KStdAccel::Find, "edit_find", I18N_NOOP("&Find..."), 0, "find" },
+ { FindNext, KStdAccel::FindNext, "edit_find_next", I18N_NOOP("Find &Next"), 0, "next" },
+ // FIXME: rename edit_find_last to edit_find_prev for KDE 4
+ { FindPrev, KStdAccel::FindPrev, "edit_find_last", I18N_NOOP("Find Pre&vious"), 0, "previous" },
+ { Replace, KStdAccel::Replace, "edit_replace", I18N_NOOP("&Replace..."), 0, 0 },
+
+ { ActualSize, KStdAccel::AccelNone, "view_actual_size", I18N_NOOP("&Actual Size"), 0, "viewmag1" },
+ { FitToPage, KStdAccel::AccelNone, "view_fit_to_page", I18N_NOOP("&Fit to Page"), 0, "view_fit_window" },
+ { FitToWidth, KStdAccel::AccelNone, "view_fit_to_width", I18N_NOOP("Fit to Page &Width"), 0, "view_fit_width" },
+ { FitToHeight, KStdAccel::AccelNone, "view_fit_to_height", I18N_NOOP("Fit to Page &Height"), 0, "view_fit_height" },
+ { ZoomIn, KStdAccel::ZoomIn, "view_zoom_in", I18N_NOOP("Zoom &In"), 0, "viewmag+" },
+ { ZoomOut, KStdAccel::ZoomOut, "view_zoom_out", I18N_NOOP("Zoom &Out"), 0, "viewmag-" },
+ { Zoom, KStdAccel::AccelNone, "view_zoom", I18N_NOOP("&Zoom..."), 0, "viewmag" },
+ // KDE4: give Redisplay the shortcut KStdAccel::AccelReload
+ { Redisplay, KStdAccel::AccelNone, "view_redisplay", I18N_NOOP("&Redisplay"), 0, "reload" },
+
+ { Up, KStdAccel::Up, "go_up", I18N_NOOP("&Up"), 0, "up" },
+ // The following three have special i18n() needs for sLabel
+ { Back, KStdAccel::Back, "go_back", 0, 0, "back" },
+ { Forward, KStdAccel::Forward, "go_forward", 0, 0, "forward" },
+ { Home, KStdAccel::Home, "go_home", 0, 0, "gohome" },
+ { Prior, KStdAccel::Prior, "go_previous", I18N_NOOP("&Previous Page"), 0, "back" },
+ { Next, KStdAccel::Next, "go_next", I18N_NOOP("&Next Page"), 0, "forward" },
+ { Goto, KStdAccel::AccelNone, "go_goto", I18N_NOOP("&Go To..."), 0, 0 },
+ { GotoPage, KStdAccel::AccelNone, "go_goto_page", I18N_NOOP("&Go to Page..."), 0, "goto" },
+ { GotoLine, KStdAccel::GotoLine, "go_goto_line", I18N_NOOP("&Go to Line..."), 0, 0 },
+ { FirstPage, KStdAccel::Home, "go_first", I18N_NOOP("&First Page"), 0, "start" },
+ { LastPage, KStdAccel::End, "go_last", I18N_NOOP("&Last Page"), 0, "finish" },
+
+ { AddBookmark, KStdAccel::AddBookmark, "bookmark_add", I18N_NOOP("&Add Bookmark"), 0, "bookmark_add" },
+ { EditBookmarks, KStdAccel::AccelNone, "bookmark_edit", I18N_NOOP("&Edit Bookmarks"), 0, "bookmark" },
+
+ { Spelling, KStdAccel::AccelNone, "tools_spelling", I18N_NOOP("&Spelling..."), 0, "spellcheck" },
+
+ { ShowMenubar, KStdAccel::ShowMenubar, "options_show_menubar", I18N_NOOP("Show &Menubar"), 0, "showmenu" },
+ { ShowToolbar, KStdAccel::AccelNone, "options_show_toolbar", I18N_NOOP("Show &Toolbar"), 0, 0 },
+ { ShowStatusbar, KStdAccel::AccelNone, "options_show_statusbar", I18N_NOOP("Show St&atusbar"), 0, 0 },
+ { FullScreen, KStdAccel::FullScreen, "fullscreen", I18N_NOOP("F&ull Screen Mode"), 0, "window_fullscreen" },
+ { SaveOptions, KStdAccel::AccelNone, "options_save_options", I18N_NOOP("&Save Settings"), 0, 0 },
+ { KeyBindings, KStdAccel::AccelNone, "options_configure_keybinding", I18N_NOOP("Configure S&hortcuts..."), 0,"configure_shortcuts" },
+ { Preferences, KStdAccel::AccelNone, "options_configure", I18N_NOOP("&Configure %1..."), 0, "configure" },
+ { ConfigureToolbars, KStdAccel::AccelNone, "options_configure_toolbars", I18N_NOOP("Configure Tool&bars..."), 0,"configure_toolbars" },
+ { ConfigureNotifications, KStdAccel::AccelNone, "options_configure_notifications", I18N_NOOP("Configure &Notifications..."), 0, "knotify" },
+
+ // the idea here is that Contents is used in menus, and Help in dialogs, so both share the same
+ // shortcut
+ { Help, KStdAccel::Help, "help", 0, 0, "help" },
+ { HelpContents, KStdAccel::Help, "help_contents", I18N_NOOP("%1 &Handbook"), 0, "contents" },
+ { WhatsThis, KStdAccel::WhatsThis, "help_whats_this", I18N_NOOP("What's &This?"), 0, "contexthelp" },
+ { TipofDay, KStdAccel::AccelNone, "help_show_tip", I18N_NOOP("Tip of the &Day"), 0, "idea" },
+ { ReportBug, KStdAccel::AccelNone, "help_report_bug", I18N_NOOP("&Report Bug..."), 0, 0 },
+ { SwitchApplicationLanguage, KStdAccel::AccelNone, "switch_application_language", I18N_NOOP("Switch application &language..."), 0, 0 },
+ { AboutApp, KStdAccel::AccelNone, "help_about_app", I18N_NOOP("&About %1"), 0, 0 },
+ { AboutKDE, KStdAccel::AccelNone, "help_about_kde", I18N_NOOP("About &KDE"), 0,"about_kde" },
+ { ActionNone, KStdAccel::AccelNone, 0, 0, 0, 0 }
+};
+
+inline const KStdActionInfo* infoPtr( StdAction id )
+{
+ for( uint i = 0; g_rgActionInfo[i].id != ActionNone; i++ ) {
+ if( g_rgActionInfo[i].id == id )
+ return &g_rgActionInfo[i];
+ }
+ return 0;
+}
+
+static inline QStringList internal_stdNames()
+{
+ QStringList result;
+
+ for( uint i = 0; g_rgActionInfo[i].id != ActionNone; i++ )
+ if (g_rgActionInfo[i].psLabel)
+ result.append(i18n(g_rgActionInfo[i].psLabel));
+ return result;
+}
+
+}
+
+#endif
diff --git a/kdeui/kstdguiitem.cpp b/kdeui/kstdguiitem.cpp
new file mode 100644
index 000000000..ce9466091
--- /dev/null
+++ b/kdeui/kstdguiitem.cpp
@@ -0,0 +1,287 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2001 Holger Freyther <freyther@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kstdguiitem.h"
+
+#include <kguiitem.h>
+#include <klocale.h>
+#include <kapplication.h>
+
+KGuiItem KStdGuiItem::guiItem ( StdItem ui_enum )
+{
+ switch (ui_enum ) {
+ case Ok : return ok();
+ case Cancel : return cancel();
+ case Yes : return yes();
+ case No : return no();
+ case Discard : return discard();
+ case Save : return save();
+ case DontSave : return dontSave();
+ case SaveAs : return saveAs();
+ case Apply : return apply();
+ case Clear : return clear();
+ case Help : return help();
+ case Close : return close();
+ case Defaults : return defaults();
+ case Back : return back();
+ case Forward : return forward();
+ case Print : return print();
+ case Continue : return cont();
+ case Open : return open();
+ case Quit : return quit();
+ case AdminMode: return adminMode();
+ case Reset : return reset();
+ case Delete : return del();
+ case Insert : return insert();
+ case Find : return find();
+ case Stop : return stop();
+ case Add : return add();
+ case Remove : return remove();
+ case Test : return test();
+ case Properties : return properties();
+ case Overwrite : return overwrite();
+ default : return KGuiItem();
+ };
+}
+
+QString KStdGuiItem::stdItem( StdItem ui_enum )
+{
+ switch (ui_enum ) {
+ case Ok : return QString::fromLatin1("ok");
+ case Cancel : return QString::fromLatin1("cancel");
+ case Yes : return QString::fromLatin1("yes");
+ case No : return QString::fromLatin1("no");
+ case Discard : return QString::fromLatin1("discard");
+ case Save : return QString::fromLatin1("save");
+ case DontSave : return QString::fromLatin1("dontSave");
+ case SaveAs : return QString::fromLatin1("saveAs");
+ case Apply : return QString::fromLatin1("apply");
+ case Help : return QString::fromLatin1("help");
+ case Close : return QString::fromLatin1("close");
+ case Defaults : return QString::fromLatin1("defaults");
+ case Back : return QString::fromLatin1("back");
+ case Forward : return QString::fromLatin1("forward");
+ case Print : return QString::fromLatin1("print");
+ case Continue : return QString::fromLatin1("continue");
+ case Open : return QString::fromLatin1("open");
+ case Quit : return QString::fromLatin1("quit");
+ case AdminMode: return QString::fromLatin1("adminMode");
+ case Delete : return QString::fromLatin1("delete");
+ case Insert : return QString::fromLatin1("insert");
+ case Find : return QString::fromLatin1("find");
+ case Stop : return QString::fromLatin1("stop");
+ case Add : return QString::fromLatin1("add");
+ case Remove : return QString::fromLatin1("remove");
+ case Test : return QString::fromLatin1("test");
+ case Properties : return QString::fromLatin1("properties");
+ case Overwrite : return QString::fromLatin1("overwrite");
+ default : return QString::null;
+ };
+}
+
+KGuiItem KStdGuiItem::ok()
+{
+ return KGuiItem( i18n( "&OK" ), "button_ok" );
+}
+
+
+KGuiItem KStdGuiItem::cancel()
+{
+ return KGuiItem( i18n( "&Cancel" ), "button_cancel" );
+}
+
+KGuiItem KStdGuiItem::yes()
+{
+ return KGuiItem( i18n( "&Yes" ), "button_ok", i18n( "Yes" ) );
+}
+
+KGuiItem KStdGuiItem::no()
+{
+ return KGuiItem( i18n( "&No" ), "", i18n( "No" ) );
+}
+
+KGuiItem KStdGuiItem::discard()
+{
+ return KGuiItem( i18n( "&Discard" ), "", i18n( "Discard changes" ),
+ i18n( "Pressing this button will discard all recent "
+ "changes made in this dialog" ) );
+}
+
+KGuiItem KStdGuiItem::save()
+{
+ return KGuiItem( i18n( "&Save" ), "filesave", i18n( "Save data" ) );
+}
+
+KGuiItem KStdGuiItem::dontSave()
+{
+ return KGuiItem( i18n( "&Do Not Save" ), "",
+ i18n( "Don't save data" ) );
+}
+
+KGuiItem KStdGuiItem::saveAs()
+{
+ return KGuiItem( i18n( "Save &As..." ), "filesaveas",
+ i18n( "Save file with another name" ) );
+}
+
+KGuiItem KStdGuiItem::apply()
+{
+ return KGuiItem( i18n( "&Apply" ), "apply", i18n( "Apply changes" ),
+ i18n( "When clicking <b>Apply</b>, the settings will be "
+ "handed over to the program, but the dialog "
+ "will not be closed.\n"
+ "Use this to try different settings." ) );
+}
+
+KGuiItem KStdGuiItem::adminMode()
+{
+ return KGuiItem( i18n( "Administrator &Mode..." ), "", i18n( "Enter Administrator Mode" ),
+ i18n( "When clicking <b>Administrator Mode</b> you will be prompted "
+ "for the administrator (root) password in order to make changes "
+ "which require root privileges." ) );
+}
+
+KGuiItem KStdGuiItem::clear()
+{
+ return KGuiItem( i18n( "C&lear" ), "locationbar_erase",
+ i18n( "Clear input" ),
+ i18n( "Clear the input in the edit field" ) );
+}
+
+KGuiItem KStdGuiItem::help()
+{
+ return KGuiItem( i18n( "show help", "&Help" ), "help",
+ i18n( "Show help" ) );
+}
+
+KGuiItem KStdGuiItem::close()
+{
+ return KGuiItem( i18n( "&Close" ), "fileclose",
+ i18n( "Close the current window or document" ) );
+}
+
+KGuiItem KStdGuiItem::defaults()
+{
+ return KGuiItem( i18n( "&Defaults" ), "",
+ i18n( "Reset all items to their default values" ) );
+}
+
+KGuiItem KStdGuiItem::back( BidiMode useBidi )
+{
+ QString icon = ( useBidi == UseRTL && QApplication::reverseLayout() )
+ ? "forward" : "back";
+ return KGuiItem( i18n( "go back", "&Back" ), icon,
+ i18n( "Go back one step" ) );
+}
+
+KGuiItem KStdGuiItem::forward( BidiMode useBidi )
+{
+ QString icon = ( useBidi == UseRTL && QApplication::reverseLayout() )
+ ? "back" : "forward";
+ return KGuiItem( i18n( "go forward", "&Forward" ), icon,
+ i18n( "Go forward one step" ) );
+}
+
+QPair<KGuiItem, KGuiItem> KStdGuiItem::backAndForward()
+{
+ return qMakePair( back( UseRTL ), forward( UseRTL ) );
+}
+
+KGuiItem KStdGuiItem::print()
+{
+ return KGuiItem( i18n( "&Print..." ), "fileprint",
+ i18n( "Opens the print dialog to print "
+ "the current document" ) );
+}
+
+KGuiItem KStdGuiItem::cont()
+{
+ return KGuiItem( i18n( "C&ontinue" ), QString::null,
+ i18n( "Continue operation" ) );
+}
+
+KGuiItem KStdGuiItem::del()
+{
+ return KGuiItem( i18n( "&Delete" ), "editdelete",
+ i18n( "Delete item(s)" ) );
+}
+
+KGuiItem KStdGuiItem::open()
+{
+ return KGuiItem( i18n( "&Open..." ), "fileopen",
+ i18n( "Open file" ) );
+}
+
+KGuiItem KStdGuiItem::quit()
+{
+ return KGuiItem( i18n( "&Quit" ), "exit",
+ i18n( "Quit application" ) );
+}
+
+KGuiItem KStdGuiItem::reset()
+{
+ return KGuiItem( i18n( "&Reset" ), "undo",
+ i18n( "Reset configuration" ) );
+}
+
+KGuiItem KStdGuiItem::insert()
+{
+ return KGuiItem( i18n( "Verb", "&Insert" ) );
+}
+
+KGuiItem KStdGuiItem::configure()
+{
+ return KGuiItem( i18n( "Confi&gure..." ), "configure" );
+}
+
+KGuiItem KStdGuiItem::find()
+{
+ return KGuiItem(i18n("&Find"), "find");
+}
+
+KGuiItem KStdGuiItem::stop()
+{
+ return KGuiItem(i18n("Stop"), "stop");
+}
+
+KGuiItem KStdGuiItem::add()
+{
+ return KGuiItem(i18n("Add"), "add");
+}
+
+KGuiItem KStdGuiItem::remove()
+{
+ return KGuiItem(i18n("Remove"), "remove");
+}
+
+KGuiItem KStdGuiItem::test()
+{
+ return KGuiItem(i18n("Test"));
+}
+
+KGuiItem KStdGuiItem::properties()
+{
+ return KGuiItem(i18n("Properties"));
+}
+
+KGuiItem KStdGuiItem::overwrite()
+{
+ return KGuiItem(i18n("&Overwrite"));
+}
+
+// vim: set ts=2 sts=2 sw=2 et:
diff --git a/kdeui/kstdguiitem.h b/kdeui/kstdguiitem.h
new file mode 100644
index 000000000..413a47296
--- /dev/null
+++ b/kdeui/kstdguiitem.h
@@ -0,0 +1,183 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2001 Holger Freyther <freyther@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __kstdguiitem_h
+#define __kstdguiitem_h
+
+// Needed for the template below
+#include <kguiitem.h>
+
+#include <qstring.h>
+#include <qpair.h>
+
+/**
+ * @short Provides a set of standardized KGuiItems.
+ *
+ * The various static methods returns standardized @ref KGuiItem's
+ * conforming to the KDE UI Standards. Use them instead of creating
+ * your own.
+ *
+ * @author Holger Freyther <freyther@kde.org>
+ */
+class KDEUI_EXPORT KStdGuiItem
+{
+public:
+ /**
+ * The back and forward items by default use the RTL settings for Hebrew
+ * and Arab countries. If you want those actions to ignore the RTL value
+ * and force 'Western' behavior instead, use the IgnoreRTL value instead.
+ */
+ enum BidiMode { UseRTL = 0, IgnoreRTL };
+
+ enum StdItem
+ {
+ Ok=1, Cancel, Yes, No, Discard, Save, DontSave, SaveAs,
+ Apply, Clear, Help, Defaults, Close, Back, Forward, Print,
+ Continue, Open, Quit, AdminMode, Reset, Delete, Insert,
+ Configure, ///< @since 3.4
+ Find, ///< @since 3.4
+ Stop, ///< @since 3.4
+ Add, ///< @since 3.4
+ Remove, ///< @since 3.4
+ Test, ///< @since 3.4
+ Properties, ///< @since 3.4
+ Overwrite ///< @since 3.5
+ };
+ static KGuiItem guiItem ( StdItem ui_enum );
+ static QString stdItem ( StdItem ui_enum );
+ static KGuiItem ok();
+ static KGuiItem cancel();
+ static KGuiItem yes();
+ static KGuiItem no();
+ static KGuiItem insert();
+ static KGuiItem discard();
+ static KGuiItem save();
+ static KGuiItem help();
+ static KGuiItem dontSave();
+ static KGuiItem saveAs();
+ static KGuiItem apply();
+ static KGuiItem clear();
+ static KGuiItem defaults();
+ static KGuiItem close();
+ static KGuiItem print();
+ /**
+ * @since 3.4
+ */
+ static KGuiItem properties();
+ static KGuiItem reset();
+ /**
+ * @since 3.5
+ */
+ static KGuiItem overwrite();
+ /**
+ * Returns a KGuiItem suiting for cases where code or functionality
+ * runs under root privileges. Used in conjunction with KConfig Modules.
+ */
+ static KGuiItem adminMode();
+
+ /**
+ * Returns a "continue" item. The short name is due to "continue" being a
+ * reserved word in the C++ language.
+ */
+ static KGuiItem cont();
+
+ /**
+ * Returns a "delete" item. The short name is due to "delete" being a
+ * reserved word in the C++ language.
+ * @since 3.3
+ */
+ static KGuiItem del();
+
+ static KGuiItem open();
+
+ /**
+ * Return a GUI item for a 'back' action, like Konqueror's back button.
+ * This GUI item can optionally honor the user's setting for BiDi, so the
+ * icon for right-to-left languages (Hebrew and Arab) has the arrow
+ * pointing in the opposite direction.
+ * By default the arrow points in the Western 'back' direction (i.e.
+ * to the left). This is because usually you only want the Bidi aware
+ * GUI item if you also want the 'forward' item. Those two are available
+ * in the separate backAndForward() method.
+ */
+ static KGuiItem back( BidiMode useBidi = IgnoreRTL );
+
+ /**
+ * Return a GUI item for a 'forward' action, like Konqueror's forward
+ * button. This GUI item can optionally honor the user's setting for BiDi,
+ * so the icon for right-to-left languages (Hebrew and Arab) has the arrow
+ * pointing in the opposite direction.
+ * By default the arrow points in the Western 'forward' direction (i.e.
+ * to the right). This is because usually you only want the Bidi aware
+ * GUI item if you also want the 'back' item. Those two are available
+ * in the separate backAndForward() method.
+ */
+ static KGuiItem forward( BidiMode useBidi = IgnoreRTL );
+
+ /**
+ * Returns a "configure" item.
+ * @since 3.4
+ */
+ static KGuiItem configure();
+
+ /**
+ * Return both a back and a forward item. This function always returns
+ * items that are aware of the Right-to-Left setting for Arab and Hebrew
+ * locales. If you have a reason for wanting the 'Western' back/forward
+ * buttons, please use the back() and forward() items instead.
+ */
+ static QPair<KGuiItem, KGuiItem> backAndForward();
+
+ static KGuiItem quit();
+
+ /**
+ * Returns a "find" item.
+ * @since 3.4
+ */
+ static KGuiItem find();
+
+ /**
+ * Returns a "stop" item.
+ * @since 3.4
+ */
+ static KGuiItem stop();
+
+ /**
+ * Returns a "add" item.
+ * @since 3.4
+ */
+ static KGuiItem add();
+
+ /**
+ * Returns a "remove" item.
+ * @since 3.4
+ */
+ static KGuiItem remove();
+
+ /**
+ * Returns a "test" item.
+ * @since 3.4
+ */
+ static KGuiItem test();
+
+};
+
+#endif
+
+// vim: set et ts=4 sw=4 sts=4:
+
diff --git a/kdeui/kstringvalidator.cpp b/kdeui/kstringvalidator.cpp
new file mode 100644
index 000000000..e45e0dcbe
--- /dev/null
+++ b/kdeui/kstringvalidator.cpp
@@ -0,0 +1,90 @@
+/*
+ kstringvalidator.cpp
+
+ Copyright (c) 2001 Marc Mutz <mutz@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; version 2.0
+ of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA
+*/
+
+#include "kstringvalidator.h"
+#include "kdebug.h"
+
+//
+// KStringListValidator
+//
+
+QValidator::State KStringListValidator::validate( QString & input, int& ) const {
+ if ( input.isEmpty() ) return Intermediate;
+
+ if ( isRejecting() ) // anything not in mStringList is acceptable:
+ if ( mStringList.find( input ) == mStringList.end() )
+ return Acceptable;
+ else
+ return Intermediate;
+ else // only what is in mStringList is acceptable:
+ if ( mStringList.find( input ) != mStringList.end() )
+ return Acceptable;
+ else
+ for ( QStringList::ConstIterator it = mStringList.begin() ;
+ it != mStringList.end() ; ++it )
+ if ( (*it).startsWith( input ) || input.startsWith( *it ) )
+ return Intermediate;
+
+ return Invalid;
+}
+
+void KStringListValidator::fixup( QString & /* input */ ) const {
+ if ( !isFixupEnabled() ) return;
+ // warn (but only once!) about non-implemented fixup():
+ static bool warn = true;
+ if ( warn ) {
+ kdDebug() << "KStringListValidator::fixup() isn't yet implemented!"
+ << endl;
+ warn = false;
+ }
+}
+
+//
+// KMimeTypeValidator
+//
+
+#define ALLOWED_CHARS "!#-'*+.0-9^-~+-"
+
+QValidator::State KMimeTypeValidator::validate( QString & input, int& ) const
+{
+ if ( input.isEmpty() )
+ return Intermediate;
+
+ QRegExp acceptable( "[" ALLOWED_CHARS "]+/[" ALLOWED_CHARS "]+",
+ false /*case-insens.*/);
+ if ( acceptable.exactMatch( input ) )
+ return Acceptable;
+
+ QRegExp intermediate( "[" ALLOWED_CHARS "]*/?[" ALLOWED_CHARS "]*",
+ false /*case-insensitive*/);
+ if ( intermediate.exactMatch( input ) )
+ return Intermediate;
+
+ return Invalid;
+}
+
+void KMimeTypeValidator::fixup( QString & input ) const
+{
+ QRegExp invalidChars("[^/" ALLOWED_CHARS "]+");
+ input.replace( invalidChars, QString::null);
+}
+
+#include "kstringvalidator.moc"
diff --git a/kdeui/kstringvalidator.h b/kdeui/kstringvalidator.h
new file mode 100644
index 000000000..42e1c7b3b
--- /dev/null
+++ b/kdeui/kstringvalidator.h
@@ -0,0 +1,141 @@
+/*
+ kstringvalidator.h
+
+ Copyright (c) 2001 Marc Mutz <mutz@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; version 2.0
+ of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA
+*/
+
+#ifndef __KSTRINGVALIDATOR_H__
+#define __KSTRINGVALIDATOR_H__
+
+#include <qvalidator.h>
+#include <qstringlist.h>
+
+#include <kdelibs_export.h>
+
+/**
+ * @short A QValidator to (dis)allow certain strings
+ *
+ * This validator allows you to accept only certain or to accept all
+ * but certain strings.
+ *
+ * When used in rejecting mode, accepts only strings not in the
+ * stringlist. This mode is the default and comes in handy when asking
+ * the user for a name of some listed entity. Set the list of already
+ * used names to prevent the user from entering duplicate names.
+ *
+ * When used in non-rejecting mode, accepts only strings that appear
+ * in the stringlist. Use with care! From a user's point of view this
+ * mode is hard to grasp.
+ *
+ * This validator can also fix strings. In rejecting mode, a number
+ * will be appended to the string until it is Acceptable. E.g. if
+ * "foo" and "foo 1" are in the stringlist, then fixup will change
+ * "foo" to "foo 2", provided "foo 2" isn't in the list of forbidden
+ * strings.
+ *
+ * In accepting mode, when the input starts with an Acceptable
+ * substring, truncates to the longest Acceptable string. When the
+ * input is the start of an Acceptable string, completes to the
+ * shortest Acceptable string.
+ *
+ * NOTE: fixup isn't yet implemented.
+ *
+ * @author Marc Mutz <mutz@kde.org>
+ **/
+class KDEUI_EXPORT KStringListValidator : public QValidator {
+ Q_OBJECT
+ Q_PROPERTY( QStringList stringList READ stringList WRITE setStringList )
+ Q_PROPERTY( bool rejecting READ isRejecting WRITE setRejecting )
+ Q_PROPERTY( bool fixupEnabled READ isFixupEnabled WRITE setFixupEnabled )
+public:
+ /** Construct a new validator.
+ *
+ * @param list The list of strings to (dis)allow.
+ * @param rejecting Selects the validator's mode
+ * (rejecting: true; accepting: false)
+ * @param fixupEnabled Selects whether to fix strings or not.
+ * @param parent Passed to lower level constructor.
+ * @param name Passed to lower level constructor
+ *
+ **/
+ KStringListValidator( const QStringList & list=QStringList(),
+ bool rejecting=true, bool fixupEnabled=false,
+ QObject * parent=0, const char * name=0 )
+ : QValidator( parent, name ), mStringList( list ),
+ mRejecting( rejecting ), mFixupEnabled( fixupEnabled ) {}
+
+ virtual State validate( QString & input, int & pos ) const;
+ virtual void fixup( QString & input ) const;
+
+ void setRejecting( bool rejecting ) { mRejecting = rejecting; }
+ bool isRejecting() const { return mRejecting; }
+
+ void setFixupEnabled( bool fixupEnabled ) { mFixupEnabled = fixupEnabled; }
+ bool isFixupEnabled() const { return mFixupEnabled; }
+
+ void setStringList( const QStringList & list ) { mStringList = list; }
+ QStringList stringList() const { return mStringList; }
+
+protected:
+ QStringList mStringList;
+ bool mRejecting;
+ bool mFixupEnabled;
+private:
+ class KStringListValidator* d;
+};
+
+/**
+ * @short A QValidator for mime types.
+ *
+ * This validator allows you to validate mimetype names
+ * (e.g. text/plain, image/jpeg). Note that the validation is only
+ * syntactically. It will e.g. not reject "foo/bar", although that
+ * particular mime type isn't yet registered. It suffices for the name
+ * to adhere to the production
+ *
+ * \code
+ * mime-type := token "/" token ; 'token' is defined in rfc2045
+ * \endcode
+ *
+ * The fixup will simply remove all non-token characters.
+ *
+ * @author Marc Mutz <mutz@kde.org>
+ **/
+class KDEUI_EXPORT KMimeTypeValidator : public QValidator
+{
+ Q_OBJECT
+public:
+ KMimeTypeValidator( QObject* parent, const char* name=0)
+ : QValidator( parent, name ) {}
+
+ /**
+ * Checks for well-formed mimetype. Returns
+ * @li Acceptable iff input ~= /^[:allowed chars:]+\/[:allowed chars:]+$/
+ * @li Intermediate iff input ~= /^[:allowed chars:]*\/?[:allowed chars:]*$/
+ * @li Invalid else
+ */
+ virtual State validate( QString & input, int & pos ) const;
+ /**
+ * Removes all characters that are forbidden in mimetypes.
+ */
+ virtual void fixup( QString & input ) const;
+private:
+ class KMimeTypeValidator* d;
+};
+
+#endif // __KSTRINGVALIDATOR_H__
diff --git a/kdeui/kswitchlanguagedialog.cpp b/kdeui/kswitchlanguagedialog.cpp
new file mode 100644
index 000000000..9b390a7de
--- /dev/null
+++ b/kdeui/kswitchlanguagedialog.cpp
@@ -0,0 +1,349 @@
+/*
+ * This file is part of the KDE Libraries
+ * Copyright (C) 2007 Krzysztof Lichota (lichota@mimuw.edu.pl)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "kswitchlanguagedialog.h"
+
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qlabel.h>
+#include <qmap.h>
+
+#include <klanguagebutton.h>
+#include <kconfig.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+#include <kpushbutton.h>
+
+struct LanguageRowData
+{
+ QLabel *label;
+ KLanguageButton *languageButton;
+ KPushButton *removeButton;
+
+ void setRowWidgets(
+ QLabel *label,
+ KLanguageButton *languageButton,
+ KPushButton *removeButton
+ )
+ {
+ this->label = label;
+ this->languageButton = languageButton;
+ this->removeButton = removeButton;
+ }
+
+};
+
+class KSwitchLanguageDialogPrivate
+{
+public:
+ KSwitchLanguageDialogPrivate(KSwitchLanguageDialog *parent);
+
+ KSwitchLanguageDialog *p; //parent class
+
+ /**
+ Fills language button with names of languages for which given application has translation.
+ */
+ void fillApplicationLanguages(KLanguageButton *button);
+
+ /**
+ Adds one button with language to widget.
+ */
+ void addLanguageButton(const QString & languageCode, bool primaryLanguage);
+
+ /**
+ Returns list of languages chosen for application or default languages is they are not set.
+ */
+ QStringList applicationLanguageList();
+
+ QMap<KPushButton*, LanguageRowData> languageRows;
+ QPtrList<KLanguageButton> languageButtons;
+ QGridLayout *languagesLayout;
+ QWidget *page;
+};
+
+/*************************** KSwitchLanguageDialog **************************/
+
+KSwitchLanguageDialog::KSwitchLanguageDialog(
+ QWidget *parent,
+ const char *name,
+ bool modal
+ ):
+ KDialogBase(parent, name, modal, i18n("Switch application language"), Ok|Cancel, Ok, true ),
+ d(new KSwitchLanguageDialogPrivate(this))
+{
+ d->page = new QWidget( this );
+ setMainWidget(d->page);
+ QVBoxLayout *topLayout = new QVBoxLayout( d->page, 0, spacingHint() );
+ QLabel *label = new QLabel( i18n("Please choose language which should be used for this application"), d->page, "label1" );
+ topLayout->addWidget( label );
+
+ QHBoxLayout *languageHorizontalLayout = new QHBoxLayout();
+ topLayout->addLayout(languageHorizontalLayout);
+
+ d->languagesLayout = new QGridLayout(0 , 2);
+ languageHorizontalLayout->addLayout(d->languagesLayout);
+ languageHorizontalLayout->addStretch();
+
+ QStringList defaultLanguages = d->applicationLanguageList();
+
+ for ( QStringList::ConstIterator it = defaultLanguages.begin(); it != defaultLanguages.end(); ++it )
+ {
+ QString language = *it;
+ bool primaryLanguage = (it == defaultLanguages.begin());
+ d->addLanguageButton(language, primaryLanguage);
+ }
+
+ if (defaultLanguages.count() == 0)
+ {
+ d->addLanguageButton(KGlobal::locale()->defaultLanguage(), true);
+ }
+
+ QHBoxLayout *addButtonHorizontalLayout = new QHBoxLayout();
+ topLayout->addLayout(addButtonHorizontalLayout);
+
+ KPushButton *addLangButton = new KPushButton(i18n("Add fallback language"), d->page, "addLangButton");
+ QToolTip::add(addLangButton, i18n("Adds one more language which will be used if other translations do not contain proper translation"));
+ connect(addLangButton, SIGNAL(clicked()), this, SLOT(slotAddLanguageButton()));
+ addButtonHorizontalLayout->addWidget(addLangButton);
+ addButtonHorizontalLayout->addStretch();
+
+ topLayout->addStretch(10);
+}
+
+KSwitchLanguageDialog::~KSwitchLanguageDialog()
+{
+ delete this->d;
+}
+
+void KSwitchLanguageDialog::slotAddLanguageButton()
+{
+ //adding new button with en_US as it should always be present
+ d->addLanguageButton("en_US", d->languageButtons.isEmpty() ? true : false);
+}
+
+void KSwitchLanguageDialog::removeButtonClicked()
+{
+ QObject const *signalSender = sender();
+
+ if (signalSender == NULL)
+ {
+ kdError() << "KSwitchLanguageDialog::removeButtonClicked() called directly, not using signal";
+ return;
+ }
+
+ KPushButton *removeButton = const_cast<KPushButton*>(::qt_cast<const KPushButton*>(signalSender));
+
+ if (removeButton == NULL)
+ {
+ kdError() << "KSwitchLanguageDialog::removeButtonClicked() called from something else than KPushButton";
+ return;
+ }
+
+ QMap<KPushButton *, LanguageRowData>::iterator it = d->languageRows.find(removeButton);
+
+ if (it == d->languageRows.end())
+ {
+ kdError() << "KSwitchLanguageDialog::removeButtonClicked called from unknown KPushButton";
+ return;
+ }
+
+ LanguageRowData languageRowData = it.data();
+
+ d->languageButtons.removeRef(languageRowData.languageButton);
+
+ languageRowData.label->deleteLater();
+ languageRowData.languageButton->deleteLater();
+ languageRowData.removeButton->deleteLater();
+ d->languageRows.erase(it);
+}
+
+void KSwitchLanguageDialog::languageOnButtonChanged(const QString & languageCode)
+{
+ for ( QPtrList<KLanguageButton>::ConstIterator it = d->languageButtons.begin(); it != d->languageButtons.end(); ++it )
+ {
+ KLanguageButton *languageButton = *it;
+ if (languageButton->current() == languageCode)
+ {
+ //update all buttons which have matching id
+ //might update buttons which were not changed, but well...
+ languageButton->setText(KGlobal::locale()->twoAlphaToLanguageName(languageCode));
+ }
+ }
+}
+
+void KSwitchLanguageDialog::slotOk()
+{
+ QString languageString;
+ bool first = true;
+
+ for ( QPtrList<KLanguageButton>::ConstIterator it = d->languageButtons.begin(); it != d->languageButtons.end(); ++it )
+ {
+ KLanguageButton *languageButton = *it;
+
+ if (first == false)
+ {
+ languageString += ':';
+ }
+ languageString += languageButton->current();
+ first = false;
+ }
+
+ KConfig *config = KGlobal::config();
+
+ if (d->applicationLanguageList().join(":") != languageString)
+ {
+ //list is different from defaults or saved languages list
+ KConfigGroup group(config, "Locale");
+
+ group.writeEntry("Language", languageString);
+ config->sync();
+
+ KMessageBox::information(
+ this,
+ i18n("Language for this application has been changed. The change will take effect upon next start of application"), //text
+ i18n("Application language changed"), //caption
+ "ApplicationLanguageChangedWarning" //dontShowAgainName
+ );
+ }
+
+ emit okClicked();
+ accept();
+}
+
+/************************ KSwitchLanguageDialogPrivate ***********************/
+
+KSwitchLanguageDialogPrivate::KSwitchLanguageDialogPrivate(
+ KSwitchLanguageDialog *parent
+ ):
+ p(parent)
+{
+ //NOTE: do NOT use "p" in constructor, it is not fully constructed
+}
+
+void KSwitchLanguageDialogPrivate::fillApplicationLanguages(KLanguageButton *button)
+{
+ KLocale *locale = KGlobal::locale();
+ QStringList allLanguages = locale->allLanguagesTwoAlpha();
+ for ( QStringList::ConstIterator it = allLanguages.begin(); it != allLanguages.end(); ++it )
+ {
+ QString languageCode = *it;
+ if (locale->isApplicationTranslatedInto(languageCode))
+ {
+ button->insertItem(
+ locale->twoAlphaToLanguageName(languageCode),
+ languageCode
+ );
+ }
+ }
+}
+
+QStringList KSwitchLanguageDialogPrivate::applicationLanguageList()
+{
+ KConfig *config = KGlobal::config();
+ QStringList languagesList;
+
+ if (config->hasGroup("Locale"))
+ {
+ KConfigGroupSaver saver(config, "Locale");
+
+ if (config->hasKey("Language"))
+ {
+ languagesList = config->readListEntry("Language", ':');
+ }
+ }
+ if (languagesList.empty())
+ {
+ languagesList = KGlobal::locale()->languageList();
+ }
+ return languagesList;
+}
+
+void KSwitchLanguageDialogPrivate::addLanguageButton(const QString & languageCode, bool primaryLanguage)
+{
+ QString labelText = primaryLanguage ? i18n("Primary language:") : i18n("Fallback language:");
+
+ KLanguageButton *languageButton = new KLanguageButton(page);
+
+ languageButton->setText(KGlobal::locale()->twoAlphaToLanguageName(languageCode));
+
+ fillApplicationLanguages(languageButton);
+
+ languageButton->setCurrentItem(languageCode);
+
+ QObject::connect(
+ languageButton,
+ SIGNAL(activated( const QString &)),
+ p,
+ SLOT(languageOnButtonChanged(const QString &))
+ );
+
+ LanguageRowData languageRowData;
+ KPushButton *removeButton = NULL;
+
+ if (primaryLanguage == false)
+ {
+ removeButton = new KPushButton(i18n("Remove"), page);
+
+ QObject::connect(
+ removeButton,
+ SIGNAL(clicked()),
+ p,
+ SLOT(removeButtonClicked())
+ );
+ }
+
+ if (primaryLanguage)
+ {
+ QToolTip::add(languageButton, i18n("This is main application language which will be used first before any other languages"));
+ }
+ else
+ {
+ QToolTip::add(languageButton, i18n("This is language which will be used if any previous languages does not contain proper translation"));
+ }
+
+ int numRows = languagesLayout->numRows();
+
+ QLabel *languageLabel = new QLabel(labelText, page);
+ languagesLayout->addWidget( languageLabel, numRows + 1, 1, Qt::AlignAuto );
+ languagesLayout->addWidget( languageButton, numRows + 1, 2, Qt::AlignAuto );
+
+ if (primaryLanguage == false)
+ {
+ languagesLayout->addWidget( removeButton, numRows + 1, 3, Qt::AlignAuto );
+
+ languageRowData.setRowWidgets(
+ languageLabel,
+ languageButton,
+ removeButton
+ );
+ removeButton->show();
+ }
+
+ languageRows.insert(removeButton, languageRowData);
+
+ languageButtons.append(languageButton);
+ languageButton->show();
+ languageLabel->show();
+}
+
+#include "kswitchlanguagedialog.moc"
+
diff --git a/kdeui/kswitchlanguagedialog.h b/kdeui/kswitchlanguagedialog.h
new file mode 100644
index 000000000..0161453c5
--- /dev/null
+++ b/kdeui/kswitchlanguagedialog.h
@@ -0,0 +1,87 @@
+/*
+ * This file is part of the KDE Libraries
+ * Copyright (C) 2007 Krzysztof Lichota (lichota@mimuw.edu.pl)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef _KSWITCHLANGUAGEDIALOG_H_
+#define _KSWITCHLANGUAGEDIALOG_H_
+
+#include <kdialogbase.h>
+
+class KSwitchLanguageDialogPrivate;
+
+/**
+ * @short Standard "switch application language" dialog box.
+ *
+ * This class provides "switch application language" dialog box that is used
+ * in KHelpMenu
+ *
+ * @author Krzysztof Lichota (lichota@mimuw.edu.pl)
+ */
+
+class KDEUI_EXPORT KSwitchLanguageDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Constructor. Creates a fully featured "Switch application language" dialog box.
+ * Note that this dialog is made modeless in the KHelpMenu class so
+ * the users may expect a modeless dialog.
+ *
+ * @param parent The parent of the dialog box. You should use the
+ * toplevel window so that the dialog becomes centered.
+ * @param name Internal name of the widget. This name in not used in the
+ * caption.
+ * @param modal If false, this widget will be modeless and must be
+ * made visible using QWidget::show(). Otherwise it will be
+ * modal and must be made visible using QWidget::exec()
+ */
+ KSwitchLanguageDialog( QWidget *parent=0, const char *name=0, bool modal=true );
+
+ virtual ~KSwitchLanguageDialog();
+
+ protected slots:
+ /**
+ * Activated when the Ok button has been clicked. Overridden from KDialogBase.
+ */
+ virtual void slotOk();
+
+ /**
+ Called when one of language buttons changes state.
+ */
+ virtual void languageOnButtonChanged(const QString & );
+
+ /**
+ Called to add one language button to dialog.
+ */
+ virtual void slotAddLanguageButton();
+
+ /**
+ Called when "Remove" language button is clicked.
+ */
+ virtual void removeButtonClicked();
+
+ protected:
+ KSwitchLanguageDialogPrivate * const d;
+
+ friend class KSwitchLanguageDialogPrivate;
+};
+
+#endif
diff --git a/kdeui/ksyntaxhighlighter.cpp b/kdeui/ksyntaxhighlighter.cpp
new file mode 100644
index 000000000..b60940bb4
--- /dev/null
+++ b/kdeui/ksyntaxhighlighter.cpp
@@ -0,0 +1,677 @@
+/*
+ ksyntaxhighlighter.cpp
+
+ Copyright (c) 2003 Trolltech AS
+ Copyright (c) 2003 Scott Wheeler <wheeler@kde.org>
+
+ This file is part of the KDE libraries
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qcolor.h>
+#include <qregexp.h>
+#include <qsyntaxhighlighter.h>
+#include <qtimer.h>
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kspell.h>
+#include <kapplication.h>
+
+#include "ksyntaxhighlighter.h"
+
+static int dummy, dummy2, dummy3, dummy4;
+static int *Okay = &dummy;
+static int *NotOkay = &dummy2;
+static int *Ignore = &dummy3;
+static int *Unknown = &dummy4;
+static const int tenSeconds = 10*1000;
+
+class KSyntaxHighlighter::KSyntaxHighlighterPrivate
+{
+public:
+ QColor col1, col2, col3, col4, col5;
+ SyntaxMode mode;
+ bool enabled;
+};
+
+class KSpellingHighlighter::KSpellingHighlighterPrivate
+{
+public:
+
+ KSpellingHighlighterPrivate() :
+ alwaysEndsWithSpace( true ),
+ intraWordEditing( false ) {}
+
+ QString currentWord;
+ int currentPos;
+ bool alwaysEndsWithSpace;
+ QColor color;
+ bool intraWordEditing;
+};
+
+class KDictSpellingHighlighter::KDictSpellingHighlighterPrivate
+{
+public:
+ KDictSpellingHighlighterPrivate() :
+ mDict( 0 ),
+ spell( 0 ),
+ mSpellConfig( 0 ),
+ rehighlightRequest( 0 ),
+ wordCount( 0 ),
+ errorCount( 0 ),
+ autoReady( false ),
+ globalConfig( true ),
+ spellReady( false ) {}
+
+ ~KDictSpellingHighlighterPrivate() {
+ delete rehighlightRequest;
+ delete spell;
+ }
+
+ static QDict<int>* sDict()
+ {
+ if (!statDict)
+ statDict = new QDict<int>(50021);
+ return statDict;
+ }
+
+ QDict<int>* mDict;
+ QDict<int> autoDict;
+ QDict<int> autoIgnoreDict;
+ static QObject *sDictionaryMonitor;
+ KSpell *spell;
+ KSpellConfig *mSpellConfig;
+ QTimer *rehighlightRequest, *spellTimeout;
+ QString spellKey;
+ int wordCount, errorCount;
+ int checksRequested, checksDone;
+ int disablePercentage;
+ int disableWordCount;
+ bool completeRehighlightRequired;
+ bool active, automatic, autoReady;
+ bool globalConfig, spellReady;
+private:
+ static QDict<int>* statDict;
+
+};
+
+QDict<int>* KDictSpellingHighlighter::KDictSpellingHighlighterPrivate::statDict = 0;
+
+
+KSyntaxHighlighter::KSyntaxHighlighter( QTextEdit *textEdit,
+ bool colorQuoting,
+ const QColor& depth0,
+ const QColor& depth1,
+ const QColor& depth2,
+ const QColor& depth3,
+ SyntaxMode mode )
+ : QSyntaxHighlighter( textEdit )
+{
+ d = new KSyntaxHighlighterPrivate();
+
+ d->enabled = colorQuoting;
+ d->col1 = depth0;
+ d->col2 = depth1;
+ d->col3 = depth2;
+ d->col4 = depth3;
+ d->col5 = depth0;
+
+ d->mode = mode;
+}
+
+KSyntaxHighlighter::~KSyntaxHighlighter()
+{
+ delete d;
+}
+
+int KSyntaxHighlighter::highlightParagraph( const QString &text, int )
+{
+ if (!d->enabled) {
+ setFormat( 0, text.length(), textEdit()->viewport()->paletteForegroundColor() );
+ return 0;
+ }
+
+ QString simplified = text;
+ simplified = simplified.replace( QRegExp( "\\s" ), QString::null ).replace( '|', QString::fromLatin1(">") );
+ while ( simplified.startsWith( QString::fromLatin1(">>>>") ) )
+ simplified = simplified.mid(3);
+ if ( simplified.startsWith( QString::fromLatin1(">>>") ) || simplified.startsWith( QString::fromLatin1("> > >") ) )
+ setFormat( 0, text.length(), d->col2 );
+ else if ( simplified.startsWith( QString::fromLatin1(">>") ) || simplified.startsWith( QString::fromLatin1("> >") ) )
+ setFormat( 0, text.length(), d->col3 );
+ else if ( simplified.startsWith( QString::fromLatin1(">") ) )
+ setFormat( 0, text.length(), d->col4 );
+ else
+ setFormat( 0, text.length(), d->col5 );
+ return 0;
+}
+
+KSpellingHighlighter::KSpellingHighlighter( QTextEdit *textEdit,
+ const QColor& spellColor,
+ bool colorQuoting,
+ const QColor& depth0,
+ const QColor& depth1,
+ const QColor& depth2,
+ const QColor& depth3 )
+ : KSyntaxHighlighter( textEdit, colorQuoting, depth0, depth1, depth2, depth3 )
+{
+ d = new KSpellingHighlighterPrivate();
+
+ d->color = spellColor;
+}
+
+KSpellingHighlighter::~KSpellingHighlighter()
+{
+ delete d;
+}
+
+int KSpellingHighlighter::highlightParagraph( const QString &text,
+ int paraNo )
+{
+ if ( paraNo == -2 )
+ paraNo = 0;
+ // leave #includes, diffs, and quoted replies alone
+ QString diffAndCo( ">|" );
+
+ bool isCode = diffAndCo.find(text[0]) != -1;
+
+ if ( !text.endsWith(" ") )
+ d->alwaysEndsWithSpace = false;
+
+ KSyntaxHighlighter::highlightParagraph( text, -2 );
+
+ if ( !isCode ) {
+ int para, index;
+ textEdit()->getCursorPosition( &para, &index );
+ int len = text.length();
+ if ( d->alwaysEndsWithSpace )
+ len--;
+
+ d->currentPos = 0;
+ d->currentWord = "";
+ for ( int i = 0; i < len; i++ ) {
+ if ( !text[i].isLetter() && (!(text[i] == '\'')) ) {
+ if ( ( para != paraNo ) ||
+ !intraWordEditing() ||
+ ( i - d->currentWord.length() > (uint)index ) ||
+ ( i < index ) ) {
+ flushCurrentWord();
+ } else {
+ d->currentWord = "";
+ }
+ d->currentPos = i + 1;
+ } else {
+ d->currentWord += text[i];
+ }
+ }
+ if ( !text[len - 1].isLetter() ||
+ (uint)( index + 1 ) != text.length() ||
+ para != paraNo )
+ flushCurrentWord();
+ }
+ return ++paraNo;
+}
+
+QStringList KSpellingHighlighter::personalWords()
+{
+ QStringList l;
+ l.append( "KMail" );
+ l.append( "KOrganizer" );
+ l.append( "KAddressBook" );
+ l.append( "KHTML" );
+ l.append( "KIO" );
+ l.append( "KJS" );
+ l.append( "Konqueror" );
+ l.append( "KSpell" );
+ l.append( "Kontact" );
+ l.append( "Qt" );
+ return l;
+}
+
+void KSpellingHighlighter::flushCurrentWord()
+{
+ while ( d->currentWord[0].isPunct() ) {
+ d->currentWord = d->currentWord.mid( 1 );
+ d->currentPos++;
+ }
+
+ QChar ch;
+ while ( ( ch = d->currentWord[(int) d->currentWord.length() - 1] ).isPunct() &&
+ ch != '(' && ch != '@' )
+ d->currentWord.truncate( d->currentWord.length() - 1 );
+
+ if ( !d->currentWord.isEmpty() ) {
+ if ( isMisspelled( d->currentWord ) ) {
+ setFormat( d->currentPos, d->currentWord.length(), d->color );
+// setMisspelled( d->currentPos, d->currentWord.length(), true );
+ }
+ }
+ d->currentWord = "";
+}
+
+QObject *KDictSpellingHighlighter::KDictSpellingHighlighterPrivate::sDictionaryMonitor = 0;
+
+KDictSpellingHighlighter::KDictSpellingHighlighter( QTextEdit *textEdit,
+ bool spellCheckingActive ,
+ bool autoEnable,
+ const QColor& spellColor,
+ bool colorQuoting,
+ const QColor& depth0,
+ const QColor& depth1,
+ const QColor& depth2,
+ const QColor& depth3,
+ KSpellConfig *spellConfig )
+ : KSpellingHighlighter( textEdit, spellColor,
+ colorQuoting, depth0, depth1, depth2, depth3 )
+{
+ d = new KDictSpellingHighlighterPrivate();
+
+ d->mSpellConfig = spellConfig;
+ d->globalConfig = ( !spellConfig );
+ d->automatic = autoEnable;
+ d->active = spellCheckingActive;
+ d->checksRequested = 0;
+ d->checksDone = 0;
+ d->completeRehighlightRequired = false;
+
+ KConfig *config = KGlobal::config();
+ KConfigGroupSaver cs( config, "KSpell" );
+ d->disablePercentage = config->readNumEntry( "KSpell_AsYouTypeDisablePercentage", 42 );
+ d->disablePercentage = QMIN( d->disablePercentage, 101 );
+ d->disableWordCount = config->readNumEntry( "KSpell_AsYouTypeDisableWordCount", 100 );
+
+ textEdit->installEventFilter( this );
+ textEdit->viewport()->installEventFilter( this );
+
+ d->rehighlightRequest = new QTimer(this);
+ connect( d->rehighlightRequest, SIGNAL( timeout() ),
+ this, SLOT( slotRehighlight() ));
+ d->spellTimeout = new QTimer(this);
+ connect( d->spellTimeout, SIGNAL( timeout() ),
+ this, SLOT( slotKSpellNotResponding() ));
+
+ if ( d->globalConfig ) {
+ d->spellKey = spellKey();
+
+ if ( !d->sDictionaryMonitor )
+ d->sDictionaryMonitor = new QObject();
+ }
+ else {
+ d->mDict = new QDict<int>(4001);
+ connect( d->mSpellConfig, SIGNAL( configChanged() ),
+ this, SLOT( slotLocalSpellConfigChanged() ) );
+ }
+
+ slotDictionaryChanged();
+ // whats this good for?
+ //startTimer( 2 * 1000 );
+}
+
+KDictSpellingHighlighter::~KDictSpellingHighlighter()
+{
+ delete d->spell;
+ d->spell = 0;
+ delete d->mDict;
+ d->mDict = 0;
+ delete d;
+}
+
+void KDictSpellingHighlighter::slotSpellReady( KSpell *spell )
+{
+ kdDebug(0) << "KDictSpellingHighlighter::slotSpellReady( " << spell << " )" << endl;
+ KConfigGroup cg( KGlobal::config(),"KSpell" );
+ if ( cg.readEntry("KSpell_DoSpellChecking") != "0" )
+ {
+ if ( d->globalConfig ) {
+ connect( d->sDictionaryMonitor, SIGNAL( destroyed()),
+ this, SLOT( slotDictionaryChanged() ));
+ }
+ if ( spell != d->spell )
+ {
+ delete d->spell;
+ d->spell = spell;
+ }
+ d->spellReady = true;
+ const QStringList l = KSpellingHighlighter::personalWords();
+ for ( QStringList::ConstIterator it = l.begin(); it != l.end(); ++it ) {
+ d->spell->addPersonal( *it );
+ }
+ connect( spell, SIGNAL( misspelling( const QString &, const QStringList &, unsigned int )),
+ this, SLOT( slotMisspelling( const QString &, const QStringList &, unsigned int )));
+ connect( spell, SIGNAL( corrected( const QString &, const QString &, unsigned int )),
+ this, SLOT( slotCorrected( const QString &, const QString &, unsigned int )));
+ d->checksRequested = 0;
+ d->checksDone = 0;
+ d->completeRehighlightRequired = true;
+ d->rehighlightRequest->start( 0, true );
+ }
+}
+
+bool KDictSpellingHighlighter::isMisspelled( const QString &word )
+{
+ if (!d->spellReady)
+ return false;
+
+ // This debug is expensive, only enable it locally
+ //kdDebug(0) << "KDictSpellingHighlighter::isMisspelled( \"" << word << "\" )" << endl;
+ // Normally isMisspelled would look up a dictionary and return
+ // true or false, but kspell is asynchronous and slow so things
+ // get tricky...
+ // For auto detection ignore signature and reply prefix
+ if ( !d->autoReady )
+ d->autoIgnoreDict.replace( word, Ignore );
+
+ // "dict" is used as a cache to store the results of KSpell
+ QDict<int>* dict = ( d->globalConfig ? d->sDict() : d->mDict );
+ if ( !dict->isEmpty() && (*dict)[word] == NotOkay ) {
+ if ( d->autoReady && ( d->autoDict[word] != NotOkay )) {
+ if ( !d->autoIgnoreDict[word] )
+ ++d->errorCount;
+ d->autoDict.replace( word, NotOkay );
+ }
+
+ return d->active;
+ }
+ if ( !dict->isEmpty() && (*dict)[word] == Okay ) {
+ if ( d->autoReady && !d->autoDict[word] ) {
+ d->autoDict.replace( word, Okay );
+ }
+ return false;
+ }
+
+ if ((dict->isEmpty() || !((*dict)[word])) && d->spell ) {
+ int para, index;
+ textEdit()->getCursorPosition( &para, &index );
+ ++d->wordCount;
+ dict->replace( word, Unknown );
+ ++d->checksRequested;
+ if (currentParagraph() != para)
+ d->completeRehighlightRequired = true;
+ d->spellTimeout->start( tenSeconds, true );
+ d->spell->checkWord( word, false );
+ }
+ return false;
+}
+
+bool KSpellingHighlighter::intraWordEditing() const
+{
+ return d->intraWordEditing;
+}
+
+void KSpellingHighlighter::setIntraWordEditing( bool editing )
+{
+ d->intraWordEditing = editing;
+}
+
+void KDictSpellingHighlighter::slotMisspelling (const QString &originalWord, const QStringList &suggestions,
+ unsigned int pos)
+{
+ Q_UNUSED( suggestions );
+ // kdDebug() << suggestions.join( " " ).latin1() << endl;
+ if ( d->globalConfig )
+ d->sDict()->replace( originalWord, NotOkay );
+ else
+ d->mDict->replace( originalWord, NotOkay );
+
+ //Emit this baby so that apps that want to have suggestions in a popup over
+ //the misspelled word can catch them.
+ emit newSuggestions( originalWord, suggestions, pos );
+}
+
+void KDictSpellingHighlighter::slotCorrected(const QString &word,
+ const QString &,
+ unsigned int)
+
+{
+ QDict<int>* dict = ( d->globalConfig ? d->sDict() : d->mDict );
+ if ( !dict->isEmpty() && (*dict)[word] == Unknown ) {
+ dict->replace( word, Okay );
+ }
+ ++d->checksDone;
+ if (d->checksDone == d->checksRequested) {
+ d->spellTimeout->stop();
+ slotRehighlight();
+ } else {
+ d->spellTimeout->start( tenSeconds, true );
+ }
+}
+
+void KDictSpellingHighlighter::dictionaryChanged()
+{
+ QObject *oldMonitor = KDictSpellingHighlighterPrivate::sDictionaryMonitor;
+ KDictSpellingHighlighterPrivate::sDictionaryMonitor = new QObject();
+ KDictSpellingHighlighterPrivate::sDict()->clear();
+ delete oldMonitor;
+}
+
+void KDictSpellingHighlighter::restartBackgroundSpellCheck()
+{
+ kdDebug(0) << "KDictSpellingHighlighter::restartBackgroundSpellCheck()" << endl;
+ slotDictionaryChanged();
+}
+
+void KDictSpellingHighlighter::setActive( bool active )
+{
+ if ( active == d->active )
+ return;
+
+ d->active = active;
+ rehighlight();
+ if ( d->active )
+ emit activeChanged( i18n("As-you-type spell checking enabled.") );
+ else
+ emit activeChanged( i18n("As-you-type spell checking disabled.") );
+}
+
+bool KDictSpellingHighlighter::isActive() const
+{
+ return d->active;
+}
+
+void KDictSpellingHighlighter::setAutomatic( bool automatic )
+{
+ if ( automatic == d->automatic )
+ return;
+
+ d->automatic = automatic;
+ if ( d->automatic )
+ slotAutoDetection();
+}
+
+bool KDictSpellingHighlighter::automatic() const
+{
+ return d->automatic;
+}
+
+void KDictSpellingHighlighter::slotRehighlight()
+{
+ kdDebug(0) << "KDictSpellingHighlighter::slotRehighlight()" << endl;
+ if (d->completeRehighlightRequired) {
+ rehighlight();
+ } else {
+ int para, index;
+ textEdit()->getCursorPosition( &para, &index );
+ //rehighlight the current para only (undo/redo safe)
+ bool modified = textEdit()->isModified();
+ textEdit()->insertAt( "", para, index );
+ textEdit()->setModified( modified );
+ }
+ if (d->checksDone == d->checksRequested)
+ d->completeRehighlightRequired = false;
+ QTimer::singleShot( 0, this, SLOT( slotAutoDetection() ));
+}
+
+void KDictSpellingHighlighter::slotDictionaryChanged()
+{
+ delete d->spell;
+ d->spellReady = false;
+ d->wordCount = 0;
+ d->errorCount = 0;
+ d->autoDict.clear();
+
+ d->spell = new KSpell( 0, i18n( "Incremental Spellcheck" ), this,
+ SLOT( slotSpellReady( KSpell * ) ), d->mSpellConfig );
+}
+
+void KDictSpellingHighlighter::slotLocalSpellConfigChanged()
+{
+ kdDebug(0) << "KDictSpellingHighlighter::slotSpellConfigChanged()" << endl;
+ // the spell config has been changed, so we have to restart from scratch
+ d->mDict->clear();
+ slotDictionaryChanged();
+}
+
+QString KDictSpellingHighlighter::spellKey()
+{
+ KConfig *config = KGlobal::config();
+ KConfigGroupSaver cs( config, "KSpell" );
+ config->reparseConfiguration();
+ QString key;
+ key += QString::number( config->readNumEntry( "KSpell_NoRootAffix", 0 ));
+ key += '/';
+ key += QString::number( config->readNumEntry( "KSpell_RunTogether", 0 ));
+ key += '/';
+ key += config->readEntry( "KSpell_Dictionary", "" );
+ key += '/';
+ key += QString::number( config->readNumEntry( "KSpell_DictFromList", false ));
+ key += '/';
+ key += QString::number( config->readNumEntry( "KSpell_Encoding", KS_E_ASCII ));
+ key += '/';
+ key += QString::number( config->readNumEntry( "KSpell_Client", KS_CLIENT_ISPELL ));
+ return key;
+}
+
+
+// Automatic spell checking support
+// In auto spell checking mode disable as-you-type spell checking
+// iff more than one third of words are spelt incorrectly.
+//
+// Words in the signature and reply prefix are ignored.
+// Only unique words are counted.
+
+void KDictSpellingHighlighter::slotAutoDetection()
+{
+ if ( !d->autoReady )
+ return;
+
+ bool savedActive = d->active;
+
+ if ( d->automatic ) {
+ // tme = Too many errors
+ bool tme = d->wordCount >= d->disableWordCount && d->errorCount * 100 >= d->disablePercentage * d->wordCount;
+ if ( d->active && tme )
+ d->active = false;
+ else if ( !d->active && !tme )
+ d->active = true;
+ }
+ if ( d->active != savedActive ) {
+ if ( d->wordCount > 1 )
+ if ( d->active )
+ emit activeChanged( i18n("As-you-type spell checking enabled.") );
+ else
+ emit activeChanged( i18n( "Too many misspelled words. "
+ "As-you-type spell checking disabled." ) );
+ d->completeRehighlightRequired = true;
+ d->rehighlightRequest->start( 100, true );
+ }
+}
+
+void KDictSpellingHighlighter::slotKSpellNotResponding()
+{
+ static int retries = 0;
+ if (retries < 10) {
+ if ( d->globalConfig )
+ KDictSpellingHighlighter::dictionaryChanged();
+ else
+ slotLocalSpellConfigChanged();
+ } else {
+ setAutomatic( false );
+ setActive( false );
+ }
+ ++retries;
+}
+
+bool KDictSpellingHighlighter::eventFilter( QObject *o, QEvent *e)
+{
+ if (o == textEdit() && (e->type() == QEvent::FocusIn)) {
+ if ( d->globalConfig ) {
+ QString skey = spellKey();
+ if ( d->spell && d->spellKey != skey ) {
+ d->spellKey = skey;
+ KDictSpellingHighlighter::dictionaryChanged();
+ }
+ }
+ }
+
+ if (o == textEdit() && (e->type() == QEvent::KeyPress)) {
+ QKeyEvent *k = static_cast<QKeyEvent *>(e);
+ d->autoReady = true;
+ if (d->rehighlightRequest->isActive()) // try to stay out of the users way
+ d->rehighlightRequest->changeInterval( 500 );
+ if ( k->key() == Key_Enter ||
+ k->key() == Key_Return ||
+ k->key() == Key_Up ||
+ k->key() == Key_Down ||
+ k->key() == Key_Left ||
+ k->key() == Key_Right ||
+ k->key() == Key_PageUp ||
+ k->key() == Key_PageDown ||
+ k->key() == Key_Home ||
+ k->key() == Key_End ||
+ (( k->state() & ControlButton ) &&
+ ((k->key() == Key_A) ||
+ (k->key() == Key_B) ||
+ (k->key() == Key_E) ||
+ (k->key() == Key_N) ||
+ (k->key() == Key_P))) ) {
+ if ( intraWordEditing() ) {
+ setIntraWordEditing( false );
+ d->completeRehighlightRequired = true;
+ d->rehighlightRequest->start( 500, true );
+ }
+ if (d->checksDone != d->checksRequested) {
+ // Handle possible change of paragraph while
+ // words are pending spell checking
+ d->completeRehighlightRequired = true;
+ d->rehighlightRequest->start( 500, true );
+ }
+ } else {
+ setIntraWordEditing( true );
+ }
+ if ( k->key() == Key_Space ||
+ k->key() == Key_Enter ||
+ k->key() == Key_Return ) {
+ QTimer::singleShot( 0, this, SLOT( slotAutoDetection() ));
+ }
+ }
+
+ else if ( o == textEdit()->viewport() &&
+ ( e->type() == QEvent::MouseButtonPress )) {
+ d->autoReady = true;
+ if ( intraWordEditing() ) {
+ setIntraWordEditing( false );
+ d->completeRehighlightRequired = true;
+ d->rehighlightRequest->start( 0, true );
+ }
+ }
+
+ return false;
+}
+
+#include "ksyntaxhighlighter.moc"
diff --git a/kdeui/ksyntaxhighlighter.h b/kdeui/ksyntaxhighlighter.h
new file mode 100644
index 000000000..ea020afa9
--- /dev/null
+++ b/kdeui/ksyntaxhighlighter.h
@@ -0,0 +1,184 @@
+/*
+ ksyntaxhighlighter.cpp
+
+ Copyright (c) 2003 Trolltech AS
+ Copyright (c) 2003 Scott Wheeler <wheeler@kde.org>
+
+ This file is part of the KDE libraries
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KSYNTAXHIGHLIGHTER_H
+#define KSYNTAXHIGHLIGHTER_H
+
+#include <qtextedit.h>
+#include <qsyntaxhighlighter.h>
+#include <qcolor.h>
+#include <qstringlist.h>
+
+#include <kdelibs_export.h>
+
+class QAccel;
+class QTimer;
+class KSpell;
+class KSpellConfig;
+
+/**
+ * \brief Syntax sensitive text highlighter
+ */
+class KDEUI_EXPORT KSyntaxHighlighter : public QSyntaxHighlighter
+{
+public:
+ enum SyntaxMode {
+ PlainTextMode,
+ RichTextMode
+ };
+ KSyntaxHighlighter( QTextEdit *textEdit,
+ bool colorQuoting = false,
+ const QColor& QuoteColor0 = black,
+ const QColor& QuoteColor1 = QColor( 0x00, 0x80, 0x00 ),
+ const QColor& QuoteColor2 = QColor( 0x00, 0x80, 0x00 ),
+ const QColor& QuoteColor3 = QColor( 0x00, 0x80, 0x00 ),
+ SyntaxMode mode = PlainTextMode );
+ ~KSyntaxHighlighter();
+
+ int highlightParagraph( const QString& text, int endStateOfLastPara );
+
+private:
+ class KSyntaxHighlighterPrivate;
+ KSyntaxHighlighterPrivate *d;
+};
+
+class KDEUI_EXPORT KSpellingHighlighter : public KSyntaxHighlighter
+{
+public:
+ KSpellingHighlighter( QTextEdit *textEdit,
+ const QColor& spellColor = red,
+ bool colorQuoting = false,
+ const QColor& QuoteColor0 = black,
+ const QColor& QuoteColor1 = QColor( 0x00, 0x80, 0x00 ),
+ const QColor& QuoteColor2 = QColor( 0x00, 0x80, 0x00 ),
+ const QColor& QuoteColor3 = QColor( 0x00, 0x80, 0x00 ) );
+ ~KSpellingHighlighter();
+
+ virtual int highlightParagraph( const QString &text,
+ int endStateOfLastPara );
+ virtual bool isMisspelled( const QString& word ) = 0;
+ bool intraWordEditing() const;
+ void setIntraWordEditing( bool editing );
+ static QStringList personalWords();
+
+private:
+ void flushCurrentWord();
+
+ class KSpellingHighlighterPrivate;
+ KSpellingHighlighterPrivate *d;
+};
+
+/**
+ * \brief Dictionary sensitive text highlighter
+ */
+class KDEUI_EXPORT KDictSpellingHighlighter : public QObject, public KSpellingHighlighter
+{
+Q_OBJECT
+
+public:
+ KDictSpellingHighlighter( QTextEdit *textEdit,
+ bool spellCheckingActive = true,
+ bool autoEnable = true,
+ const QColor& spellColor = red,
+ bool colorQuoting = false,
+ const QColor& QuoteColor0 = black,
+ const QColor& QuoteColor1 = QColor( 0x00, 0x80, 0x00 ),
+ const QColor& QuoteColor2 = QColor( 0x00, 0x70, 0x00 ),
+ const QColor& QuoteColor3 = QColor( 0x00, 0x60, 0x00 ),
+ KSpellConfig *spellConfig = 0 );
+ ~KDictSpellingHighlighter();
+
+ virtual bool isMisspelled( const QString &word );
+ static void dictionaryChanged();
+ void restartBackgroundSpellCheck();
+
+ /**
+ * @short Enable/Disable spell checking.
+ *
+ * If @p active is true then spell checking is enabled; otherwise it
+ * is disabled. Note that you have to disable automatic (de)activation
+ * with @ref setAutomatic() before you change the state of spell checking
+ * if you want to persistently enable/disable spell checking.
+ *
+ * @param active if true, then spell checking is enabled
+ *
+ * @see isActive(), setAutomatic()
+ */
+ void setActive( bool active );
+
+ /**
+ * Returns the state of spell checking.
+ *
+ * @return true if spell checking is active
+ *
+ * @see setActive()
+ */
+ bool isActive() const;
+
+ /**
+ * @short En-/Disable automatic (de)activation in case of too many errors.
+ *
+ * If @p automatic is true then spell checking will be deactivated if
+ * too many words were mispelled and spell checking will be activated
+ * again if the amount of mispelled words drop below a certain threshold.
+ *
+ * @param automatic if true, then automatic (de)activation is enabled
+ *
+ * @see automatic()
+ */
+ void setAutomatic( bool automatic );
+
+ /**
+ * Returns the state of automatic (de)activation.
+ *
+ * @return true if automatic (de)activation is enabled
+ *
+ * @see setAutomatic()
+ */
+ bool automatic() const;
+
+signals:
+ void activeChanged(const QString &);
+ void newSuggestions(const QString& originalword, const QStringList& suggestions,
+ unsigned int pos);
+
+protected:
+ QString spellKey();
+ bool eventFilter(QObject *o, QEvent *e);
+
+protected slots:
+ void slotMisspelling( const QString &originalWord, const QStringList &suggestions, unsigned int pos );
+ void slotCorrected( const QString &originalWord, const QString &, unsigned int );
+ void slotRehighlight();
+ void slotDictionaryChanged();
+ void slotSpellReady( KSpell *spell );
+ void slotAutoDetection();
+ void slotLocalSpellConfigChanged();
+ void slotKSpellNotResponding();
+
+private:
+ class KDictSpellingHighlighterPrivate;
+ KDictSpellingHighlighterPrivate *d;
+};
+
+#endif
diff --git a/kdeui/ksystemtray.cpp b/kdeui/ksystemtray.cpp
new file mode 100644
index 000000000..593bc6bc0
--- /dev/null
+++ b/kdeui/ksystemtray.cpp
@@ -0,0 +1,335 @@
+/* This file is part of the KDE libraries
+
+ Copyright (C) 1999 Matthias Ettrich (ettrich@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "kaction.h"
+#include "kmessagebox.h"
+#include "kshortcut.h"
+#include "ksystemtray.h"
+#include "kpopupmenu.h"
+#include "kapplication.h"
+#include "klocale.h"
+#include "kaboutdata.h"
+
+#ifdef Q_WS_X11
+#include <kwin.h>
+#include <kwinmodule.h>
+#include <qxembed.h>
+#endif
+
+#include <kiconloader.h>
+#include <kconfig.h>
+
+#include <qapplication.h>
+
+class KSystemTrayPrivate
+{
+public:
+ KSystemTrayPrivate()
+ {
+ actionCollection = 0;
+ }
+
+ ~KSystemTrayPrivate()
+ {
+ delete actionCollection;
+ }
+
+ KActionCollection* actionCollection;
+ bool on_all_desktops; // valid only when the parent widget was hidden
+};
+
+KSystemTray::KSystemTray( QWidget* parent, const char* name )
+ : QLabel( parent, name, WType_TopLevel )
+{
+#ifdef Q_WS_X11
+ QXEmbed::initialize();
+#endif
+
+ d = new KSystemTrayPrivate;
+ d->actionCollection = new KActionCollection(this);
+
+#ifdef Q_WS_X11
+ KWin::setSystemTrayWindowFor( winId(), parent?parent->topLevelWidget()->winId(): qt_xrootwin() );
+#endif
+ setBackgroundMode(X11ParentRelative);
+ setBackgroundOrigin(WindowOrigin);
+ hasQuit = 0;
+ menu = new KPopupMenu( this );
+ menu->insertTitle( kapp->miniIcon(), kapp->caption() );
+ move( -1000, -1000 );
+ KStdAction::quit(this, SLOT(maybeQuit()), d->actionCollection);
+
+ if (parentWidget())
+ {
+ new KAction(i18n("Minimize"), KShortcut(),
+ this, SLOT( minimizeRestoreAction() ),
+ d->actionCollection, "minimizeRestore");
+#ifdef Q_WS_X11
+ KWin::WindowInfo info = KWin::windowInfo( parentWidget()->winId());
+ d->on_all_desktops = info.onAllDesktops();
+#else
+ d->on_all_desktops = false;
+#endif
+ }
+ else
+ {
+ d->on_all_desktops = false;
+ }
+ setCaption( KGlobal::instance()->aboutData()->programName());
+ setAlignment( alignment() | Qt::AlignVCenter | Qt::AlignHCenter );
+}
+
+KSystemTray::~KSystemTray()
+{
+ delete d;
+}
+
+
+void KSystemTray::showEvent( QShowEvent * )
+{
+ if ( !hasQuit ) {
+ menu->insertSeparator();
+ KAction* action = d->actionCollection->action("minimizeRestore");
+
+ if (action)
+ {
+ action->plug(menu);
+ }
+
+ action = d->actionCollection->action(KStdAction::name(KStdAction::Quit));
+
+ if (action)
+ {
+ action->plug(menu);
+ }
+
+ hasQuit = 1;
+ }
+}
+
+// KDE4 remove
+void KSystemTray::enterEvent( QEvent* e )
+{
+ QLabel::enterEvent( e );
+}
+
+KPopupMenu* KSystemTray::contextMenu() const
+{
+ return menu;
+}
+
+
+void KSystemTray::mousePressEvent( QMouseEvent *e )
+{
+ if ( !rect().contains( e->pos() ) )
+ return;
+
+ switch ( e->button() ) {
+ case LeftButton:
+ toggleActive();
+ break;
+ case MidButton:
+ // fall through
+ case RightButton:
+ if ( parentWidget() ) {
+ KAction* action = d->actionCollection->action("minimizeRestore");
+ if ( parentWidget()->isVisible() )
+ action->setText( i18n("&Minimize") );
+ else
+ action->setText( i18n("&Restore") );
+ }
+ contextMenuAboutToShow( menu );
+ menu->popup( e->globalPos() );
+ break;
+ default:
+ // nothing
+ break;
+ }
+}
+
+void KSystemTray::mouseReleaseEvent( QMouseEvent * )
+{
+}
+
+
+void KSystemTray::contextMenuAboutToShow( KPopupMenu* )
+{
+}
+
+// called from the popup menu - always do what the menu entry says,
+// i.e. if the window is shown, no matter if active or not, the menu
+// entry is "minimize", otherwise it's "restore"
+void KSystemTray::minimizeRestoreAction()
+{
+ if ( parentWidget() ) {
+ bool restore = !( parentWidget()->isVisible() );
+ minimizeRestore( restore );
+ }
+}
+
+void KSystemTray::maybeQuit()
+{
+ QString query = i18n("<qt>Are you sure you want to quit <b>%1</b>?</qt>")
+ .arg(kapp->caption());
+ if (KMessageBox::warningContinueCancel(this, query,
+ i18n("Confirm Quit From System Tray"),
+ KStdGuiItem::quit(),
+ QString("systemtrayquit%1")
+ .arg(kapp->caption())) !=
+ KMessageBox::Continue)
+ {
+ return;
+ }
+
+ emit quitSelected();
+
+ // KDE4: stop closing the parent widget? it results in complex application code
+ // instead make applications connect to the quitSelected() signal
+
+ if (parentWidget())
+ {
+ parentWidget()->close();
+ }
+ else
+ {
+ qApp->closeAllWindows();
+ }
+}
+
+void KSystemTray::toggleActive()
+{
+ activateOrHide();
+}
+
+void KSystemTray::setActive()
+{
+ minimizeRestore( true );
+}
+
+void KSystemTray::setInactive()
+{
+ minimizeRestore( false );
+}
+
+// called when left-clicking the tray icon
+// if the window is not the active one, show it if needed, and activate it
+// (just like taskbar); otherwise hide it
+void KSystemTray::activateOrHide()
+{
+ QWidget *pw = parentWidget();
+
+ if ( !pw )
+ return;
+
+#ifdef Q_WS_X11
+ KWin::WindowInfo info1 = KWin::windowInfo( pw->winId(), NET::XAWMState | NET::WMState );
+ // mapped = visible (but possibly obscured)
+ bool mapped = (info1.mappingState() == NET::Visible) && !info1.isMinimized();
+// - not mapped -> show, raise, focus
+// - mapped
+// - obscured -> raise, focus
+// - not obscured -> hide
+ if( !mapped )
+ minimizeRestore( true );
+ else
+ {
+ KWinModule module;
+ for( QValueList< WId >::ConstIterator it = module.stackingOrder().fromLast();
+ it != module.stackingOrder().end() && (*it) != pw->winId();
+ --it )
+ {
+ KWin::WindowInfo info2 = KWin::windowInfo( *it,
+ NET::WMGeometry | NET::XAWMState | NET::WMState | NET::WMWindowType );
+ if( info2.mappingState() != NET::Visible )
+ continue; // not visible on current desktop -> ignore
+ if( !info2.geometry().intersects( pw->geometry()))
+ continue; // not obscuring the window -> ignore
+ if( !info1.hasState( NET::KeepAbove ) && info2.hasState( NET::KeepAbove ))
+ continue; // obscured by window kept above -> ignore
+ NET::WindowType type = info2.windowType( NET::NormalMask | NET::DesktopMask
+ | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask
+ | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask );
+ if( type == NET::Dock || type == NET::TopMenu )
+ continue; // obscured by dock or topmenu -> ignore
+ pw->raise();
+ KWin::activateWindow( pw->winId());
+ return;
+ }
+ minimizeRestore( false ); // hide
+ }
+#endif
+}
+
+void KSystemTray::minimizeRestore( bool restore )
+{
+ QWidget* pw = parentWidget();
+ if( !pw )
+ return;
+#ifdef Q_WS_X11
+ KWin::WindowInfo info = KWin::windowInfo( pw->winId(), NET::WMGeometry | NET::WMDesktop );
+ if ( restore )
+ {
+ if( d->on_all_desktops )
+ KWin::setOnAllDesktops( pw->winId(), true );
+ else
+ KWin::setCurrentDesktop( info.desktop() );
+ pw->move( info.geometry().topLeft() ); // avoid placement policies
+ pw->show();
+ pw->raise();
+ KWin::activateWindow( pw->winId() );
+ } else {
+ d->on_all_desktops = info.onAllDesktops();
+ pw->hide();
+ }
+#endif
+}
+
+KActionCollection* KSystemTray::actionCollection()
+{
+ return d->actionCollection;
+}
+
+QPixmap KSystemTray::loadIcon( const QString &icon, KInstance *instance )
+{
+ KConfig *appCfg = kapp->config();
+ KConfigGroupSaver configSaver(appCfg, "System Tray");
+ int iconWidth = appCfg->readNumEntry("systrayIconWidth", 22);
+ return instance->iconLoader()->loadIcon( icon, KIcon::Panel, iconWidth );
+}
+
+void KSystemTray::setPixmap( const QPixmap& p )
+{
+ QLabel::setPixmap( p );
+#ifdef Q_WS_X11
+ KWin::setIcons( winId(), p, QPixmap());
+#endif
+}
+
+void KSystemTray::setCaption( const QString& s )
+{
+ QLabel::setCaption( s );
+}
+
+void KSystemTray::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "ksystemtray.moc"
+#include "kdockwindow.moc"
diff --git a/kdeui/ksystemtray.h b/kdeui/ksystemtray.h
new file mode 100644
index 000000000..04dce718a
--- /dev/null
+++ b/kdeui/ksystemtray.h
@@ -0,0 +1,205 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Matthias Ettrich <ettrich@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef KSYSTEMTRAY_H
+#define KSYSTEMTRAY_H
+
+#include <kglobal.h>
+#include <qlabel.h>
+
+class KActionCollection;
+class KPopupMenu;
+class KSystemTrayPrivate;
+
+/**
+ * \brief %KDE System Tray Window class
+ *
+ * This class implements system tray windows.
+ *
+ * A tray window is a small window (typically 24x24 pixel) that docks
+ * into the system tray in the desktop panel. It usually displays an
+ * icon or an animated icon there. The icon represents
+ * the application, similar to a taskbar button, but consumes less
+ * screen space.
+ *
+ * When the user clicks with the left mouse button on the icon, the
+ * main application window is shown/raised and activated. With the
+ * right mouse button, she gets a popupmenu with application specific
+ * commands, including "Minimize/Restore" and "Quit".
+ *
+ * Docking happens magically when calling show(). The window undocks
+ * with either hide() or when it is destroyed.
+ *
+ * KSystemTray inherits methods such as setPixmap() and setMovie() to
+ * specify an icon or movie (animated icon) respectively. It is
+ * designed to be usable "as is", without the need to subclass it. In
+ * case you need to provide something special (such as an additional
+ * popupmenu on a click with the left mouse button), you can subclass
+ * anyway, of course.
+ *
+ * Having an icon on the system tray is a useful technique for
+ * daemon-like applications that may run for some time without user
+ * interaction but have to be there immediately when the user needs
+ * them. Examples are kppp, kisdn, kscd, kmix or knotes. With kppp and
+ * kisdn, the docked icon even provides real-time information about
+ * the network status.
+ *
+ * @author Matthias Ettrich <ettrich@kde.org>
+ **/
+class KDEUI_EXPORT KSystemTray : public QLabel
+{
+ Q_OBJECT
+public:
+
+ /**
+ * Construct a KSystemTray widget just like any other widget.
+ *
+ * The parent widget @p parent has a special meaning:
+ * Besides owning the tray window, the parent widget will
+ * dissappear from taskbars when it is iconified while the tray
+ * window is visible. This is the desired behavior. After all,
+ * the tray window @p is the parent's taskbar icon.
+ *
+ * Furthermore, the parent widget is shown or raised respectively
+ * when the user clicks on the trray window with the left mouse
+ * button.
+ **/
+ KSystemTray( QWidget* parent = 0, const char* name = 0 );
+
+ /*
+ Destructor
+ */
+ ~KSystemTray();
+
+ /**
+ Access to the context menu. This makes it easy to add new items
+ to it.
+ */
+ KPopupMenu* contextMenu() const;
+
+ /**
+ Easy access to the actions in the context menu
+ Currently includes KStdAction::Quit and minimizeRestore
+ @since 3.1
+ */
+ KActionCollection* actionCollection();
+
+ /**
+ * Changes the tray's icon.
+ */
+ virtual void setPixmap( const QPixmap& icon );
+
+ /**
+ * Changes the tray's text description (which can be seen e.g. in the systray
+ * configuration dialog). The default value is KAboutData::programName().
+ */
+ virtual void setCaption( const QString& title );
+
+ /**
+ * Loads an icon @p icon using the icon loader class of the given instance @p instance.
+ * The icon is applied the panel effect as it should only be used to be shown in the
+ * system tray.
+ * It's commonly used in the form : systray->setPixmap( systray->loadIcon( "mysystray" ) );
+ *
+ * @since 3.2
+ */
+ static QPixmap loadIcon( const QString &icon, KInstance *instance=KGlobal::instance() );
+
+signals:
+ /**
+ * Emitted when quit is selected in the menu. If you want to perform any other
+ * action than to close the main application window please connect to this signal.
+ * @since 3.1
+ */
+ void quitSelected();
+
+public slots:
+
+ /**
+ * Toggles the state of the window associated with this system tray icon (hides it,
+ * shows it or activates it depending on the window state). The default implementation
+ * of mousePressEvent() calls toggleActive() when the tray icon is left-clicked, use
+ * it when reimplementing mousePressEvent().
+ * @since 3.3
+ */
+ void toggleActive();
+ /**
+ * Activates the window associated with this system tray icon, regardless of its current state.
+ * @since 3.3
+ */
+ void setActive();
+ /**
+ * Hides the window associated with this system tray icon, regardless of its current state.
+ * @since 3.3
+ */
+ void setInactive();
+
+protected:
+
+ /**
+ Reimplemented to provide the standard show/raise behavior
+ for the parentWidget() and the context menu.
+
+ Feel free to reimplement this if you need something special.
+ */
+ void mousePressEvent( QMouseEvent * );
+
+ /**
+ Reimplemented to provide the standard show/raise behavior
+ for the parentWidget() and the context menu.
+
+ Feel free to reimplement this if you need something special.
+ */
+ void mouseReleaseEvent( QMouseEvent * );
+
+
+
+ /**
+ Makes it easy to adjust some menu items right before the
+ context menu becomes visible.
+ */
+ virtual void contextMenuAboutToShow( KPopupMenu* menu );
+
+ /**
+ Reimplemented for internal reasons.
+ */
+ void showEvent( QShowEvent * );
+
+ /**
+ Reimplemented for internal reasons.
+ */
+ void enterEvent( QEvent* );
+
+private slots:
+ void minimizeRestoreAction();
+ void maybeQuit();
+
+private:
+ void activateOrHide();
+ void minimizeRestore( bool restore );
+ KPopupMenu* menu;
+ // minimizeRestoreId is no longer needed. remove in KDE 4.0
+ int minimizeRestoreId;
+ uint hasQuit :1;
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KSystemTrayPrivate* d;
+};
+
+
+#endif
diff --git a/kdeui/ktabbar.cpp b/kdeui/ktabbar.cpp
new file mode 100644
index 000000000..fcac5a975
--- /dev/null
+++ b/kdeui/ktabbar.cpp
@@ -0,0 +1,427 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2003 Stephan Binner <binner@kde.org>
+ Copyright (C) 2003 Zack Rusin <zack@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qapplication.h>
+#include <qcursor.h>
+#include <qpainter.h>
+#include <qstyle.h>
+#include <qtimer.h>
+#include <qpushbutton.h>
+#include <qtooltip.h>
+
+#include <kglobalsettings.h>
+#include <kiconloader.h>
+#include <klocale.h>
+
+#include "ktabbar.h"
+#include "ktabwidget.h"
+
+KTabBar::KTabBar( QWidget *parent, const char *name )
+ : QTabBar( parent, name ), mReorderStartTab( -1 ), mReorderPreviousTab( -1 ),
+ mHoverCloseButtonTab( 0 ), mDragSwitchTab( 0 ), mHoverCloseButton( 0 ),
+ mHoverCloseButtonEnabled( false ), mHoverCloseButtonDelayed( true ),
+ mTabReorderingEnabled( false ), mTabCloseActivatePrevious( false )
+{
+ setAcceptDrops( true );
+ setMouseTracking( true );
+
+ mEnableCloseButtonTimer = new QTimer( this );
+ connect( mEnableCloseButtonTimer, SIGNAL( timeout() ), SLOT( enableCloseButton() ) );
+
+ mActivateDragSwitchTabTimer = new QTimer( this );
+ connect( mActivateDragSwitchTabTimer, SIGNAL( timeout() ), SLOT( activateDragSwitchTab() ) );
+
+ connect(this, SIGNAL(layoutChanged()), SLOT(onLayoutChange()));
+}
+
+KTabBar::~KTabBar()
+{
+ //For the future
+ //delete d;
+}
+
+void KTabBar::setTabEnabled( int id, bool enabled )
+{
+ QTab * t = tab( id );
+ if ( t ) {
+ if ( t->isEnabled() != enabled ) {
+ t->setEnabled( enabled );
+ QRect r( t->rect() );
+ if ( !enabled && id == currentTab() && count()>1 ) {
+ QPtrList<QTab> *tablist = tabList();
+ if ( mTabCloseActivatePrevious )
+ t = tablist->at( count()-2 );
+ else {
+ int index = indexOf( id );
+ index += ( index+1 == count() ) ? -1 : 1;
+ t = tabAt( index );
+ }
+
+ if ( t->isEnabled() ) {
+ r = r.unite( t->rect() );
+ tablist->append( tablist->take( tablist->findRef( t ) ) );
+ emit selected( t->identifier() );
+ }
+ }
+ repaint( r );
+ }
+ }
+}
+
+void KTabBar::mouseDoubleClickEvent( QMouseEvent *e )
+{
+ if( e->button() != LeftButton )
+ return;
+
+ QTab *tab = selectTab( e->pos() );
+ if( tab ) {
+ emit( mouseDoubleClick( indexOf( tab->identifier() ) ) );
+ return;
+ }
+ QTabBar::mouseDoubleClickEvent( e );
+}
+
+void KTabBar::mousePressEvent( QMouseEvent *e )
+{
+ if( e->button() == LeftButton ) {
+ mEnableCloseButtonTimer->stop();
+ mDragStart = e->pos();
+ }
+ else if( e->button() == RightButton ) {
+ QTab *tab = selectTab( e->pos() );
+ if( tab ) {
+ emit( contextMenu( indexOf( tab->identifier() ), mapToGlobal( e->pos() ) ) );
+ return;
+ }
+ }
+ QTabBar::mousePressEvent( e );
+}
+
+void KTabBar::mouseMoveEvent( QMouseEvent *e )
+{
+ if ( e->state() == LeftButton ) {
+ QTab *tab = selectTab( e->pos() );
+ if ( mDragSwitchTab && tab != mDragSwitchTab ) {
+ mActivateDragSwitchTabTimer->stop();
+ mDragSwitchTab = 0;
+ }
+
+ int delay = KGlobalSettings::dndEventDelay();
+ QPoint newPos = e->pos();
+ if( newPos.x() > mDragStart.x()+delay || newPos.x() < mDragStart.x()-delay ||
+ newPos.y() > mDragStart.y()+delay || newPos.y() < mDragStart.y()-delay )
+ {
+ if( tab ) {
+ emit( initiateDrag( indexOf( tab->identifier() ) ) );
+ return;
+ }
+ }
+ }
+ else if ( e->state() == MidButton ) {
+ if (mReorderStartTab==-1) {
+ int delay = KGlobalSettings::dndEventDelay();
+ QPoint newPos = e->pos();
+ if( newPos.x() > mDragStart.x()+delay || newPos.x() < mDragStart.x()-delay ||
+ newPos.y() > mDragStart.y()+delay || newPos.y() < mDragStart.y()-delay )
+ {
+ QTab *tab = selectTab( e->pos() );
+ if( tab && mTabReorderingEnabled ) {
+ mReorderStartTab = indexOf( tab->identifier() );
+ grabMouse( sizeAllCursor );
+ return;
+ }
+ }
+ }
+ else {
+ QTab *tab = selectTab( e->pos() );
+ if( tab ) {
+ int reorderStopTab = indexOf( tab->identifier() );
+ if ( mReorderStartTab!=reorderStopTab && mReorderPreviousTab!=reorderStopTab ) {
+ emit( moveTab( mReorderStartTab, reorderStopTab ) );
+ mReorderPreviousTab=mReorderStartTab;
+ mReorderStartTab=reorderStopTab;
+ return;
+ }
+ }
+ }
+ }
+
+ if ( mHoverCloseButtonEnabled && mReorderStartTab==-1) {
+ QTab *t = selectTab( e->pos() );
+ if( t && t->iconSet() && t->isEnabled() ) {
+ QPixmap pixmap = t->iconSet()->pixmap( QIconSet::Small, QIconSet::Normal );
+ QRect rect( 0, 0, pixmap.width() + 4, pixmap.height() +4);
+
+ int xoff = 0, yoff = 0;
+ // The additional offsets were found by try and error, TODO: find the rational behind them
+ if ( t == tab( currentTab() ) ) {
+ xoff = style().pixelMetric( QStyle::PM_TabBarTabShiftHorizontal, this ) + 3;
+ yoff = style().pixelMetric( QStyle::PM_TabBarTabShiftVertical, this ) - 4;
+ }
+ else {
+ xoff = 7;
+ yoff = 0;
+ }
+ rect.moveLeft( t->rect().left() + 2 + xoff );
+ rect.moveTop( t->rect().center().y()-pixmap.height()/2 + yoff );
+ if ( rect.contains( e->pos() ) ) {
+ if ( mHoverCloseButton ) {
+ if ( mHoverCloseButtonTab == t )
+ return;
+ mEnableCloseButtonTimer->stop();
+ mHoverCloseButton->deleteLater();
+ mHoverCloseButton = 0;
+ }
+
+ mHoverCloseButton = new QPushButton( this );
+ mHoverCloseButton->setIconSet( KGlobal::iconLoader()->loadIconSet("fileclose", KIcon::Toolbar, KIcon::SizeSmall) );
+ mHoverCloseButton->setGeometry( rect );
+ QToolTip::add(mHoverCloseButton,i18n("Close this tab"));
+ mHoverCloseButton->setFlat(true);
+ mHoverCloseButton->show();
+ if ( mHoverCloseButtonDelayed ) {
+ mHoverCloseButton->setEnabled(false);
+ mEnableCloseButtonTimer->start( QApplication::doubleClickInterval(), true );
+ }
+ mHoverCloseButtonTab = t;
+ connect( mHoverCloseButton, SIGNAL( clicked() ), SLOT( closeButtonClicked() ) );
+ return;
+ }
+ }
+ if ( mHoverCloseButton ) {
+ mEnableCloseButtonTimer->stop();
+ mHoverCloseButton->deleteLater();
+ mHoverCloseButton = 0;
+ }
+ }
+
+ QTabBar::mouseMoveEvent( e );
+}
+
+void KTabBar::enableCloseButton()
+{
+ mHoverCloseButton->setEnabled(true);
+}
+
+void KTabBar::activateDragSwitchTab()
+{
+ QTab *tab = selectTab( mapFromGlobal( QCursor::pos() ) );
+ if ( tab && mDragSwitchTab == tab )
+ setCurrentTab( mDragSwitchTab );
+ mDragSwitchTab = 0;
+}
+
+void KTabBar::mouseReleaseEvent( QMouseEvent *e )
+{
+ if( e->button() == MidButton ) {
+ if ( mReorderStartTab==-1 ) {
+ QTab *tab = selectTab( e->pos() );
+ if( tab ) {
+ emit( mouseMiddleClick( indexOf( tab->identifier() ) ) );
+ return;
+ }
+ }
+ else {
+ releaseMouse();
+ setCursor( arrowCursor );
+ mReorderStartTab=-1;
+ mReorderPreviousTab=-1;
+ }
+ }
+ QTabBar::mouseReleaseEvent( e );
+}
+
+void KTabBar::dragMoveEvent( QDragMoveEvent *e )
+{
+ QTab *tab = selectTab( e->pos() );
+ if( tab ) {
+ bool accept = false;
+ // The receivers of the testCanDecode() signal has to adjust
+ // 'accept' accordingly.
+ emit testCanDecode( e, accept);
+ if ( accept && tab != QTabBar::tab( currentTab() ) ) {
+ mDragSwitchTab = tab;
+ mActivateDragSwitchTabTimer->start( QApplication::doubleClickInterval()*2, true );
+ }
+ e->accept( accept );
+ return;
+ }
+ e->accept( false );
+ QTabBar::dragMoveEvent( e );
+}
+
+void KTabBar::dropEvent( QDropEvent *e )
+{
+ QTab *tab = selectTab( e->pos() );
+ if( tab ) {
+ mActivateDragSwitchTabTimer->stop();
+ mDragSwitchTab = 0;
+ emit( receivedDropEvent( indexOf( tab->identifier() ) , e ) );
+ return;
+ }
+ QTabBar::dropEvent( e );
+}
+
+#ifndef QT_NO_WHEELEVENT
+void KTabBar::wheelEvent( QWheelEvent *e )
+{
+ if ( e->orientation() == Horizontal )
+ return;
+
+ emit( wheelDelta( e->delta() ) );
+}
+#endif
+
+void KTabBar::setTabColor( int id, const QColor& color )
+{
+ QTab *t = tab( id );
+ if ( t ) {
+ mTabColors.insert( id, color );
+ repaint( t->rect(), false );
+ }
+}
+
+const QColor &KTabBar::tabColor( int id ) const
+{
+ if ( mTabColors.contains( id ) )
+ return mTabColors[id];
+
+ return colorGroup().foreground();
+}
+
+int KTabBar::insertTab( QTab *t, int index )
+{
+ int res = QTabBar::insertTab( t, index );
+
+ if ( mTabCloseActivatePrevious && count() > 2 ) {
+ QPtrList<QTab> *tablist = tabList();
+ tablist->insert( count()-2, tablist->take( tablist->findRef( t ) ) );
+ }
+
+ return res;
+}
+
+void KTabBar::removeTab( QTab *t )
+{
+ mTabColors.remove( t->identifier() );
+ QTabBar::removeTab( t );
+}
+
+void KTabBar::paintLabel( QPainter *p, const QRect& br,
+ QTab *t, bool has_focus ) const
+{
+ QRect r = br;
+ bool selected = currentTab() == t->identifier();
+ if ( t->iconSet() ) {
+ // the tab has an iconset, draw it in the right mode
+ QIconSet::Mode mode = ( t->isEnabled() && isEnabled() )
+ ? QIconSet::Normal : QIconSet::Disabled;
+ if ( mode == QIconSet::Normal && has_focus )
+ mode = QIconSet::Active;
+ QPixmap pixmap = t->iconSet()->pixmap( QIconSet::Small, mode );
+ int pixw = pixmap.width();
+ int pixh = pixmap.height();
+ r.setLeft( r.left() + pixw + 4 );
+ r.setRight( r.right() + 2 );
+
+ int inactiveXShift = style().pixelMetric( QStyle::PM_TabBarTabShiftHorizontal, this );
+ int inactiveYShift = style().pixelMetric( QStyle::PM_TabBarTabShiftVertical, this );
+
+ int right = t->text().isEmpty() ? br.right() - pixw : br.left() + 2;
+
+ p->drawPixmap( right + (selected ? 0 : inactiveXShift),
+ br.center().y() - pixh / 2 + (selected ? 0 : inactiveYShift),
+ pixmap );
+ }
+
+ QStyle::SFlags flags = QStyle::Style_Default;
+
+ if ( isEnabled() && t->isEnabled() )
+ flags |= QStyle::Style_Enabled;
+ if ( has_focus )
+ flags |= QStyle::Style_HasFocus;
+
+ QColorGroup cg( colorGroup() );
+ if ( mTabColors.contains( t->identifier() ) )
+ cg.setColor( QColorGroup::Foreground, mTabColors[t->identifier()] );
+
+ style().drawControl( QStyle::CE_TabBarLabel, p, this, r,
+ t->isEnabled() ? cg : palette().disabled(),
+ flags, QStyleOption(t) );
+}
+
+bool KTabBar::isTabReorderingEnabled() const
+{
+ return mTabReorderingEnabled;
+}
+
+void KTabBar::setTabReorderingEnabled( bool on )
+{
+ mTabReorderingEnabled = on;
+}
+
+bool KTabBar::tabCloseActivatePrevious() const
+{
+ return mTabCloseActivatePrevious;
+}
+
+void KTabBar::setTabCloseActivatePrevious( bool on )
+{
+ mTabCloseActivatePrevious = on;
+}
+
+void KTabBar::closeButtonClicked()
+{
+ emit closeRequest( indexOf( mHoverCloseButtonTab->identifier() ) );
+}
+
+void KTabBar::setHoverCloseButton( bool button )
+{
+ mHoverCloseButtonEnabled = button;
+ if ( !button )
+ onLayoutChange();
+}
+
+bool KTabBar::hoverCloseButton() const
+{
+ return mHoverCloseButtonEnabled;
+}
+
+void KTabBar::setHoverCloseButtonDelayed( bool delayed )
+{
+ mHoverCloseButtonDelayed = delayed;
+}
+
+bool KTabBar::hoverCloseButtonDelayed() const
+{
+ return mHoverCloseButtonDelayed;
+}
+
+void KTabBar::onLayoutChange()
+{
+ mEnableCloseButtonTimer->stop();
+ delete mHoverCloseButton;
+ mHoverCloseButton = 0;
+ mHoverCloseButtonTab = 0;
+ mActivateDragSwitchTabTimer->stop();
+ mDragSwitchTab = 0;
+}
+
+#include "ktabbar.moc"
diff --git a/kdeui/ktabbar.h b/kdeui/ktabbar.h
new file mode 100644
index 000000000..2ea300db6
--- /dev/null
+++ b/kdeui/ktabbar.h
@@ -0,0 +1,113 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2003 Stephan Binner <binner@kde.org>
+ Copyright (C) 2003 Zack Rusin <zack@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KTABBAR_H
+#define KTABBAR_H
+
+#include <qtabbar.h>
+
+#include <kdelibs_export.h>
+
+class QTimer;
+class QPushButton;
+class KTabBarPrivate;
+
+/**
+ * @since 3.2
+ */
+class KDEUI_EXPORT KTabBar: public QTabBar
+{
+ Q_OBJECT
+
+public:
+ KTabBar( QWidget* parent=0, const char* name=0 );
+ virtual ~KTabBar();
+
+ virtual void setTabEnabled( int, bool );
+
+ const QColor &tabColor( int ) const;
+ void setTabColor( int, const QColor& );
+
+ virtual int insertTab( QTab *, int index = -1 );
+ virtual void removeTab( QTab * );
+
+ void setTabReorderingEnabled( bool enable );
+ bool isTabReorderingEnabled() const;
+
+ void setHoverCloseButton( bool );
+ bool hoverCloseButton() const;
+
+ void setHoverCloseButtonDelayed( bool );
+ bool hoverCloseButtonDelayed() const;
+
+ void setTabCloseActivatePrevious( bool );
+ bool tabCloseActivatePrevious() const;
+
+signals:
+ void contextMenu( int, const QPoint & );
+ void mouseDoubleClick( int );
+ void mouseMiddleClick( int );
+ void initiateDrag( int );
+ void testCanDecode(const QDragMoveEvent *e, bool &accept /* result */);
+ void receivedDropEvent( int, QDropEvent * );
+ void moveTab( int, int );
+ void closeRequest( int );
+#ifndef QT_NO_WHEELEVENT
+ void wheelDelta( int );
+#endif
+
+protected:
+ virtual void mouseDoubleClickEvent( QMouseEvent *e );
+ virtual void mousePressEvent( QMouseEvent *e );
+ virtual void mouseMoveEvent( QMouseEvent *e );
+ virtual void mouseReleaseEvent( QMouseEvent *e );
+#ifndef QT_NO_WHEELEVENT
+ virtual void wheelEvent( QWheelEvent *e );
+#endif
+
+ virtual void dragMoveEvent( QDragMoveEvent *e );
+ virtual void dropEvent( QDropEvent *e );
+
+ virtual void paintLabel( QPainter*, const QRect&, QTab*, bool ) const;
+
+protected slots:
+ virtual void closeButtonClicked();
+ virtual void onLayoutChange();
+ virtual void enableCloseButton();
+ virtual void activateDragSwitchTab();
+
+private:
+ QPoint mDragStart;
+ int mReorderStartTab;
+ int mReorderPreviousTab;
+ QMap<int, QColor> mTabColors;
+ QTab *mHoverCloseButtonTab, *mDragSwitchTab;
+ QPushButton *mHoverCloseButton;
+ QTimer *mEnableCloseButtonTimer, *mActivateDragSwitchTabTimer;
+
+ bool mHoverCloseButtonEnabled;
+ bool mHoverCloseButtonDelayed;
+ bool mTabReorderingEnabled;
+ bool mTabCloseActivatePrevious;
+
+ KTabBarPrivate * d;
+};
+
+#endif
diff --git a/kdeui/ktabctl.cpp b/kdeui/ktabctl.cpp
new file mode 100644
index 000000000..190dc077e
--- /dev/null
+++ b/kdeui/ktabctl.cpp
@@ -0,0 +1,336 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Alexander Sanda (alex@darkstar.ping.at)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+/**
+ * KTabCtl provides a universal tab control. It is in no ways limited to dialogs and
+ * can be used for whatever you want. It has no buttons or any other stuff.
+ *
+ * However, this is based on the original QTabDialog.
+ */
+
+#include <qtabbar.h>
+#include <qpushbutton.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+
+#include "ktabctl.h"
+
+KTabCtl::KTabCtl(QWidget *parent, const char *name)
+ : QWidget(parent, name)
+{
+ tabs = new QTabBar(this, "_tabbar");
+ connect(tabs, SIGNAL(selected(int)), this, SLOT(showTab(int)));
+ tabs->move(2, 1);
+
+ blBorder = true;
+
+}
+
+KTabCtl::~KTabCtl()
+{
+ delete tabs;
+}
+
+void KTabCtl::resizeEvent(QResizeEvent *)
+{
+ int i;
+ QRect r = getChildRect();
+
+ if (tabs) {
+ for (i=0; i<(int)pages.size(); i++) {
+ pages[i]->setGeometry(r);
+ }
+ if( ( tabs->shape() == QTabBar::RoundedBelow ) ||
+ ( tabs->shape() == QTabBar::TriangularBelow ) ) {
+ tabs->move( 0, height()-tabs->height()-4 );
+ }
+ }
+}
+
+void KTabCtl::setFont(const QFont & font)
+{
+ QFont f(font);
+ f.setWeight(QFont::Light);
+ QWidget::setFont(f);
+
+ setSizes();
+}
+
+void KTabCtl::setTabFont(const QFont & font)
+{
+ QFont f(font);
+// f.setWeight(QFont::Light);
+ tabs->setFont(f);
+
+ setSizes();
+}
+
+void KTabCtl::show()
+{
+ unsigned int i;
+
+ if(isVisible())
+ return;
+
+ setSizes();
+
+ for(i = 0; i < pages.size(); i++)
+ pages[i]->hide();
+
+ QResizeEvent r(size(), size());
+ resizeEvent(&r);
+
+ QWidget::show();
+}
+
+bool KTabCtl::isTabEnabled(const QString& name)
+{
+ unsigned int i;
+
+ for(i = 0; i < pages.size(); i++)
+ if (QString::fromLatin1(pages[i]->name()) == name)
+ return tabs->isTabEnabled(i); /* return the enabled status */
+ return false; /* tab does not exist */
+}
+
+void KTabCtl::setTabEnabled(const QString& name, bool state)
+{
+ unsigned i;
+
+ if (name.isEmpty())
+ return;
+
+ for (i = 0; i < pages.size(); i++)
+ if (QString::fromLatin1(pages[i]->name()) == name)
+ tabs->setTabEnabled(i, state);
+}
+
+void KTabCtl::setSizes()
+{
+ unsigned i;
+
+ QSize min(tabs->sizeHint()); /* the minimum required size for the tabbar */
+ tabs->resize(min); /* make sure that the tabbar does not require more space than actually needed. */
+
+
+ QSize max(QCOORD_MAX,QCOORD_MAX);
+ //int th = min.height(); /* the height of the tabbar itself (without pages and stuff) */
+
+ for (i = 0; i < pages.size(); i++) {
+
+ /*
+ * check the actual minimum and maximum sizes
+ */
+
+ if (pages[i]->maximumSize().height() < max.height())
+ max.setHeight(pages[i]->maximumSize().height());
+ if (pages[i]->maximumSize().width() < max.width())
+ max.setWidth( pages[i]->maximumSize().width());
+ if ( pages[i]->minimumSize().height() > min.height())
+ min.setHeight( pages[i]->minimumSize().height());
+ if ( pages[i]->minimumSize().width() > min.width())
+ min.setWidth( pages[i]->minimumSize().width());
+ }
+
+ // BL: min and max are sizes of children, not tabcontrol
+ // min.setHeight(min.height() + th);
+
+ if (max.width() < min.width())
+ max.setWidth(min.width());
+ if (max.height() < min.height())
+ max.setHeight(min.height());
+
+ /*
+ * now, apply the calculated size values to all of the pages
+ */
+
+ for( i=0; i<(uint)pages.size(); i++ ) {
+ pages[i]->setMinimumSize(min);
+ pages[i]->setMaximumSize(max);
+ }
+
+
+ // BL: set minimum size of tabcontrol
+ setMinimumSize(min.width()+4, min.height()+tabs->height()+4);
+
+ /*
+ * generate a resizeEvent, if we're visible
+ */
+
+ if(isVisible()) {
+ QResizeEvent r(size(), size());
+ resizeEvent(&r);
+ }
+}
+
+void KTabCtl::setBorder( bool state )
+{
+ blBorder = state;
+}
+
+void KTabCtl::setShape( QTabBar::Shape shape )
+{
+ tabs->setShape( shape );
+}
+
+QSize
+KTabCtl::sizeHint() const
+{
+ /* desired size of the tabbar */
+ QSize hint(tabs->sizeHint());
+
+ /* overall desired size of all pages */
+ QSize pageHint;
+ for (unsigned int i = 0; i < pages.size(); i++)
+ {
+ QSize sizeI(pages[i]->sizeHint());
+
+ if (sizeI.isValid())
+ {
+ /* only pages with valid size are used */
+ if (sizeI.width() > pageHint.width())
+ pageHint.setWidth(sizeI.width());
+
+ if (sizeI.height() > pageHint.height())
+ pageHint.setHeight(sizeI.height());
+ }
+ }
+
+ if (pageHint.isValid())
+ {
+ /* use maximum of width of tabbar and pages */
+ if (pageHint.width() > hint.width())
+ hint.setWidth(pageHint.width());
+
+ /* heights must just be added */
+ hint.setHeight(hint.height() + pageHint.height());
+
+ /* 1999-09-18: Espen Sand
+ I cannot get the size to be correct unless the total
+ border size is included: ie 2*2 pixels.
+ */
+ return (hint + QSize(4,4));
+ }
+
+ /*
+ * If not at least a one page has a valid sizeHint we have to return
+ * an invalid size as well.
+ */
+ return (pageHint);
+}
+
+void KTabCtl::paintEvent(QPaintEvent *)
+{
+ if (!tabs)
+ return;
+
+ if( !blBorder )
+ return;
+
+ QPainter p;
+ p.begin(this);
+
+ int y0 = getChildRect().top() - 1;
+ int y1 = getChildRect().bottom() + 2;
+ int x1 = getChildRect().right() + 2;
+ int x0 = getChildRect().left() - 1;
+
+ p.setPen(colorGroup().light());
+ p.drawLine(x0, y0 - 1, x1 - 1, y0 - 1); /* 1st top line */
+ p.setPen(colorGroup().midlight());
+ p.drawLine(x0, y0, x1 - 1, y0); /* 2nd top line */
+ p.setPen(colorGroup().light());
+ p.drawLine(x0, y0 + 1, x0, y1); /* left line */
+ p.setPen(black);
+ p.drawLine(x1, y1, x0, y1); /* bottom line */
+ p.drawLine(x1, y1 - 1, x1, y0);
+ p.setPen(colorGroup().dark());
+ p.drawLine(x0 + 1, y1 - 1, x1 - 1, y1 - 1); /* bottom */
+ p.drawLine(x1 - 1, y1 - 2, x1 - 1, y0 + 1);
+ p.end();
+}
+
+/*
+ * return the client rect. This is the maximum size for any child
+ * widget (page).
+ */
+
+QRect KTabCtl::getChildRect() const
+{
+ if( ( tabs->shape() == QTabBar::RoundedBelow ) ||
+ ( tabs->shape() == QTabBar::TriangularBelow ) ) {
+ return QRect(2, 1, width() - 4,
+ height() - tabs->height() - 4);
+ } else {
+ return QRect(2, tabs->height() + 1, width() - 4,
+ height() - tabs->height() - 4);
+ }
+}
+
+/*
+ * show a single page, depending on the selected tab
+ * emit tabSelected(new_pagenumber) BEFORE the page is shown
+ */
+
+void KTabCtl::showTab(int i)
+{
+ unsigned int j;
+ for (j = 0; j < pages.size(); j++) {
+ if (j != (unsigned)i) {
+ pages[j]->hide();
+ }
+ }
+
+ if((unsigned)i < pages.size()) {
+ emit(tabSelected(i));
+ if( pages.size() >= 2 ) {
+ pages[i]->raise();
+ }
+ tabs->setCurrentTab(i);
+ pages[i]->setGeometry(getChildRect());
+ pages[i]->show();
+ }
+}
+
+/*
+ * add a tab to the control. This tab will manage the given Widget w.
+ * in most cases, w will be a QWidget and will only act as parent for the
+ * actual widgets on this page
+ * NOTE: w is not required to be of class QWidget, but expect strange results with
+ * other types of widgets
+ */
+
+void KTabCtl::addTab(QWidget *w, const QString& name)
+{
+ QTab *t = new QTab();
+ t->setText( name );
+ t->setEnabled( true );
+ int id = tabs->addTab(t); /* add the tab itself to the tabbar */
+ if (id == (int)pages.size()) {
+ pages.resize(id + 1);
+ pages[id] = w; /* remember the widget to manage by this tab */
+ }
+ // BL: compute sizes
+ setSizes();
+}
+
+void KTabCtl::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "ktabctl.moc"
diff --git a/kdeui/ktabctl.h b/kdeui/ktabctl.h
new file mode 100644
index 000000000..c8cb3cf1b
--- /dev/null
+++ b/kdeui/ktabctl.h
@@ -0,0 +1,90 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Alexander Sanda (alex@darkstar.ping.at)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+/*
+ * $Id$
+*/
+
+#ifndef KTABCTL_H
+#define KTABCTL_H
+
+#include <qwidget.h>
+#include <qtabbar.h>
+#include <qmemarray.h>
+
+#include <kdelibs_export.h>
+
+/**
+ * Tabbed dialog with extended features.
+ * KTabCtl is very similar to QTabDialog, with the following differences:
+ *
+ * @li To avoid confusion, the API is almost identical with QTabDialog.
+ * @li Does not create any buttons, therefore KTabCtl is not limited
+ * to dialog boxes. You can use it whereever you want.
+ * @li emits the signal tabSelected(int pagenumber) when the user
+ * selects one of the tabs. This gives you the chance to update the
+ * widget contents of a single page. The signal is emitted _before_ the
+ * page is shown. This is very useful if the contents of some widgets
+ * on page A depend on the contents of some other widgets on page B.
+ *
+ * @author Alexander Sanda (alex@darkstar.ping.at)
+ * @version $Id$
+*/
+class KDEUI_EXPORT KTabCtl : public QWidget
+{
+ Q_OBJECT
+
+public:
+ KTabCtl(QWidget *parent = 0, const char *name = 0);
+ ~KTabCtl();
+
+ void show();
+ void setFont(const QFont & font);
+ void setTabFont( const QFont &font );
+
+ void addTab(QWidget *, const QString&);
+ bool isTabEnabled(const QString& );
+ void setTabEnabled(const QString&, bool);
+ void setBorder(bool);
+ void setShape( QTabBar::Shape shape );
+ virtual QSize sizeHint() const;
+
+protected:
+ void paintEvent(QPaintEvent *);
+ void resizeEvent(QResizeEvent *);
+
+signals:
+ void tabSelected(int);
+
+protected slots:
+ void showTab(int i);
+
+protected:
+ void setSizes();
+ QRect getChildRect() const;
+
+ QTabBar * tabs;
+ QMemArray<QWidget *> pages;
+ int bh;
+ bool blBorder;
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class KTabCtrlPrivate* d;
+};
+#endif
diff --git a/kdeui/ktabwidget.cpp b/kdeui/ktabwidget.cpp
new file mode 100644
index 000000000..42e00c96a
--- /dev/null
+++ b/kdeui/ktabwidget.cpp
@@ -0,0 +1,524 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2003 Stephan Binner <binner@kde.org>
+ Copyright (C) 2003 Zack Rusin <zack@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qapplication.h>
+#include <qstyle.h>
+#include <qstylesheet.h>
+
+#include <kconfig.h>
+#include <kiconloader.h>
+#include <kstringhandler.h>
+
+#include "ktabwidget.h"
+#include "ktabbar.h"
+
+class KTabWidgetPrivate {
+public:
+ bool m_automaticResizeTabs;
+ int m_maxLength;
+ int m_minLength;
+ unsigned int m_CurrentMaxLength;
+
+ //holds the full names of the tab, otherwise all we
+ //know about is the shortened name
+ QStringList m_tabNames;
+
+ KTabWidgetPrivate() {
+ m_automaticResizeTabs = false;
+ KConfigGroupSaver groupsaver(KGlobal::config(), "General");
+ m_maxLength = KGlobal::config()->readNumEntry("MaximumTabLength", 30);
+ m_minLength = KGlobal::config()->readNumEntry("MinimumTabLength", 3);
+ m_CurrentMaxLength = m_minLength;
+ }
+};
+
+KTabWidget::KTabWidget( QWidget *parent, const char *name, WFlags f )
+ : QTabWidget( parent, name, f )
+{
+ d = new KTabWidgetPrivate;
+ setTabBar( new KTabBar(this, "tabbar") );
+ setAcceptDrops( true );
+
+ connect(tabBar(), SIGNAL(contextMenu( int, const QPoint & )), SLOT(contextMenu( int, const QPoint & )));
+ connect(tabBar(), SIGNAL(mouseDoubleClick( int )), SLOT(mouseDoubleClick( int )));
+ connect(tabBar(), SIGNAL(mouseMiddleClick( int )), SLOT(mouseMiddleClick( int )));
+ connect(tabBar(), SIGNAL(initiateDrag( int )), SLOT(initiateDrag( int )));
+ connect(tabBar(), SIGNAL(testCanDecode(const QDragMoveEvent *, bool & )), SIGNAL(testCanDecode(const QDragMoveEvent *, bool & )));
+ connect(tabBar(), SIGNAL(receivedDropEvent( int, QDropEvent * )), SLOT(receivedDropEvent( int, QDropEvent * )));
+ connect(tabBar(), SIGNAL(moveTab( int, int )), SLOT(moveTab( int, int )));
+ connect(tabBar(), SIGNAL(closeRequest( int )), SLOT(closeRequest( int )));
+#ifndef QT_NO_WHEELEVENT
+ connect(tabBar(), SIGNAL(wheelDelta( int )), SLOT(wheelDelta( int )));
+#endif
+}
+
+KTabWidget::~KTabWidget()
+{
+ delete d;
+}
+
+void KTabWidget::insertTab( QWidget *child, const QString &label, int index )
+{
+ QTabWidget::insertTab( child, label, index );
+}
+
+void KTabWidget::insertTab( QWidget *child, const QIconSet& iconset, const QString &label, int index )
+{
+ QTabWidget::insertTab( child, iconset, label, index );
+}
+
+void KTabWidget::insertTab( QWidget *child, QTab *tab, int index )
+{
+ QTabWidget::insertTab( child, tab, index);
+ if ( d->m_automaticResizeTabs ) {
+ if ( index < 0 || index >= count() ) {
+ d->m_tabNames.append( tab->text() );
+ resizeTabs( d->m_tabNames.count()-1 );
+ }
+ else {
+ d->m_tabNames.insert( d->m_tabNames.at( index ), tab->text() );
+ resizeTabs( index );
+ }
+ }
+}
+
+void KTabWidget::setTabBarHidden( bool hide )
+{
+ QWidget *rightcorner = this->cornerWidget( TopRight );
+ QWidget *leftcorner = this->cornerWidget( TopLeft );
+
+ if ( hide ) {
+ if ( leftcorner ) leftcorner->hide();
+ if ( rightcorner ) rightcorner->hide();
+ tabBar()->hide();
+ } else {
+ tabBar()->show();
+ if ( leftcorner ) leftcorner->show();
+ if ( rightcorner ) rightcorner->show();
+ }
+}
+
+bool KTabWidget::isTabBarHidden() const
+{
+ return !( tabBar()->isVisible() );
+}
+
+void KTabWidget::setTabColor( QWidget *w, const QColor& color )
+{
+ QTab *t = tabBar()->tabAt( indexOf( w ) );
+ if (t) {
+ static_cast<KTabBar*>(tabBar())->setTabColor( t->identifier(), color );
+ }
+}
+
+QColor KTabWidget::tabColor( QWidget *w ) const
+{
+ QTab *t = tabBar()->tabAt( indexOf( w ) );
+ if (t) {
+ return static_cast<KTabBar*>(tabBar())->tabColor( t->identifier() );
+ } else {
+ return QColor();
+ }
+}
+
+void KTabWidget::setTabReorderingEnabled( bool on)
+{
+ static_cast<KTabBar*>(tabBar())->setTabReorderingEnabled( on );
+}
+
+bool KTabWidget::isTabReorderingEnabled() const
+{
+ return static_cast<KTabBar*>(tabBar())->isTabReorderingEnabled();
+}
+
+void KTabWidget::setTabCloseActivatePrevious( bool previous)
+{
+ static_cast<KTabBar*>(tabBar())->setTabCloseActivatePrevious( previous );
+}
+
+bool KTabWidget::tabCloseActivatePrevious() const
+{
+ return static_cast<KTabBar*>(tabBar())->tabCloseActivatePrevious();
+}
+
+unsigned int KTabWidget::tabBarWidthForMaxChars( uint maxLength )
+{
+ int hframe, overlap;
+ hframe = tabBar()->style().pixelMetric( QStyle::PM_TabBarTabHSpace, tabBar() );
+ overlap = tabBar()->style().pixelMetric( QStyle::PM_TabBarTabOverlap, tabBar() );
+
+ QFontMetrics fm = tabBar()->fontMetrics();
+ int x = 0;
+ for( int i=0; i < count(); ++i ) {
+ QString newTitle = d->m_tabNames[ i ];
+ newTitle = KStringHandler::rsqueeze( newTitle, maxLength ).leftJustify( d->m_minLength, ' ' );
+
+ QTab* tab = tabBar()->tabAt( i );
+ int lw = fm.width( newTitle );
+ int iw = 0;
+ if ( tab->iconSet() )
+ iw = tab->iconSet()->pixmap( QIconSet::Small, QIconSet::Normal ).width() + 4;
+ x += ( tabBar()->style().sizeFromContents( QStyle::CT_TabBarTab, this,
+ QSize( QMAX( lw + hframe + iw, QApplication::globalStrut().width() ), 0 ),
+ QStyleOption( tab ) ) ).width();
+ }
+ return x;
+}
+
+void KTabWidget::changeTab( QWidget *w, const QString &label )
+{
+ QTabWidget::changeTab( w, label );
+ if ( d->m_automaticResizeTabs ) {
+ int index = indexOf( w );
+ if ( index != -1 ) {
+ d->m_tabNames[ index ] = label;
+ resizeTabs( index );
+ }
+ }
+}
+
+void KTabWidget::changeTab( QWidget *w, const QIconSet &iconset, const QString &label )
+{
+ QTabWidget::changeTab( w, iconset, label );
+ if ( d->m_automaticResizeTabs ) {
+ int index = indexOf( w );
+ if ( index != -1 ) {
+ d->m_tabNames[ index ] = label;
+ resizeTabs( index );
+ }
+ }
+}
+
+QString KTabWidget::label( int index ) const
+{
+ if ( d->m_automaticResizeTabs ) {
+ if ( index >= 0 && index < count() )
+ return d->m_tabNames[ index ];
+ else
+ return QString::null;
+ }
+ else
+ return QTabWidget::label( index );
+}
+
+QString KTabWidget::tabLabel( QWidget * w ) const
+{
+ if ( d->m_automaticResizeTabs ) {
+ int index = indexOf( w );
+ if ( index == -1 )
+ return QString::null;
+ else
+ return d->m_tabNames[ index ];
+ }
+ else
+ return QTabWidget::tabLabel( w );
+}
+
+void KTabWidget::setTabLabel( QWidget *w, const QString &l )
+{
+ QTabWidget::setTabLabel( w, l );
+ if ( d->m_automaticResizeTabs ) {
+ int index = indexOf( w );
+ if ( index != -1 ) {
+ d->m_tabNames[ index ] = l;
+ resizeTabs( index );
+ }
+ }
+}
+
+void KTabWidget::resizeTabs( int changeTabIndex )
+{
+ uint newMaxLength;
+ if ( d->m_automaticResizeTabs ) {
+ // Calculate new max length
+ newMaxLength=d->m_maxLength;
+ uint lcw=0, rcw=0;
+
+ int tabBarHeight = tabBar()->sizeHint().height();
+ if ( cornerWidget( TopLeft ) && cornerWidget( TopLeft )->isVisible() )
+ lcw = QMAX( cornerWidget( TopLeft )->width(), tabBarHeight );
+ if ( cornerWidget( TopRight ) && cornerWidget( TopRight )->isVisible() )
+ rcw = QMAX( cornerWidget( TopRight )->width(), tabBarHeight );
+
+ uint maxTabBarWidth = width() - lcw - rcw;
+
+ for ( ; newMaxLength > (uint)d->m_minLength; newMaxLength-- ) {
+ if ( tabBarWidthForMaxChars( newMaxLength ) < maxTabBarWidth )
+ break;
+ }
+ }
+ else
+ newMaxLength = 4711;
+
+ // Update hinted or all tabs
+ if ( d->m_CurrentMaxLength != newMaxLength ) {
+ d->m_CurrentMaxLength = newMaxLength;
+ for( int i = 0; i < count(); ++i )
+ updateTab( i );
+ }
+ else if ( changeTabIndex != -1 )
+ updateTab( changeTabIndex );
+}
+
+void KTabWidget::updateTab( int index )
+{
+ QString title = d->m_automaticResizeTabs ? d->m_tabNames[ index ] : QTabWidget::label( index );
+ removeTabToolTip( page( index ) );
+ if ( title.length() > d->m_CurrentMaxLength ) {
+ if ( QStyleSheet::mightBeRichText( title ) )
+ setTabToolTip( page( index ), QStyleSheet::escape(title) );
+ else
+ setTabToolTip( page( index ), title );
+ }
+
+ title = KStringHandler::rsqueeze( title, d->m_CurrentMaxLength ).leftJustify( d->m_minLength, ' ' );
+ title.replace( '&', "&&" );
+
+ if ( QTabWidget::label( index ) != title )
+ QTabWidget::setTabLabel( page( index ), title );
+}
+
+void KTabWidget::dragMoveEvent( QDragMoveEvent *e )
+{
+ if ( isEmptyTabbarSpace( e->pos() ) ) {
+ bool accept = false;
+ // The receivers of the testCanDecode() signal has to adjust
+ // 'accept' accordingly.
+ emit testCanDecode( e, accept);
+ e->accept( accept );
+ return;
+ }
+ e->accept( false );
+ QTabWidget::dragMoveEvent( e );
+}
+
+void KTabWidget::dropEvent( QDropEvent *e )
+{
+ if ( isEmptyTabbarSpace( e->pos() ) ) {
+ emit ( receivedDropEvent( e ) );
+ return;
+ }
+ QTabWidget::dropEvent( e );
+}
+
+#ifndef QT_NO_WHEELEVENT
+void KTabWidget::wheelEvent( QWheelEvent *e )
+{
+ if ( e->orientation() == Horizontal )
+ return;
+
+ if ( isEmptyTabbarSpace( e->pos() ) )
+ wheelDelta( e->delta() );
+ else
+ e->ignore();
+}
+
+void KTabWidget::wheelDelta( int delta )
+{
+ if ( count() < 2 )
+ return;
+
+ int page = currentPageIndex();
+ if ( delta < 0 )
+ page = (page + 1) % count();
+ else {
+ page--;
+ if ( page < 0 )
+ page = count() - 1;
+ }
+ setCurrentPage( page );
+}
+#endif
+
+void KTabWidget::mouseDoubleClickEvent( QMouseEvent *e )
+{
+ if( e->button() != LeftButton )
+ return;
+
+ if ( isEmptyTabbarSpace( e->pos() ) ) {
+ emit( mouseDoubleClick() );
+ return;
+ }
+ QTabWidget::mouseDoubleClickEvent( e );
+}
+
+void KTabWidget::mousePressEvent( QMouseEvent *e )
+{
+ if ( e->button() == RightButton ) {
+ if ( isEmptyTabbarSpace( e->pos() ) ) {
+ emit( contextMenu( mapToGlobal( e->pos() ) ) );
+ return;
+ }
+ } else if ( e->button() == MidButton ) {
+ if ( isEmptyTabbarSpace( e->pos() ) ) {
+ emit( mouseMiddleClick() );
+ return;
+ }
+ }
+ QTabWidget::mousePressEvent( e );
+}
+
+void KTabWidget::receivedDropEvent( int index, QDropEvent *e )
+{
+ emit( receivedDropEvent( page( index ), e ) );
+}
+
+void KTabWidget::initiateDrag( int index )
+{
+ emit( initiateDrag( page( index ) ) );
+}
+
+void KTabWidget::contextMenu( int index, const QPoint &p )
+{
+ emit( contextMenu( page( index ), p ) );
+}
+
+void KTabWidget::mouseDoubleClick( int index )
+{
+ emit( mouseDoubleClick( page( index ) ) );
+}
+
+void KTabWidget::mouseMiddleClick( int index )
+{
+ emit( mouseMiddleClick( page( index ) ) );
+}
+
+void KTabWidget::moveTab( int from, int to )
+{
+ QString tablabel = label( from );
+ QWidget *w = page( from );
+ QColor color = tabColor( w );
+ QIconSet tabiconset = tabIconSet( w );
+ QString tabtooltip = tabToolTip( w );
+ bool current = ( w == currentPage() );
+ bool enabled = isTabEnabled( w );
+ blockSignals(true);
+ removePage( w );
+
+ // Work-around kmdi brain damage which calls showPage() in insertTab()
+ QTab * t = new QTab();
+ t->setText(tablabel);
+ QTabWidget::insertTab( w, t, to );
+ if ( d->m_automaticResizeTabs ) {
+ if ( to < 0 || to >= count() )
+ d->m_tabNames.append( QString::null );
+ else
+ d->m_tabNames.insert( d->m_tabNames.at( to ), QString::null );
+ }
+
+ w = page( to );
+ changeTab( w, tabiconset, tablabel );
+ setTabToolTip( w, tabtooltip );
+ setTabColor( w, color );
+ if ( current )
+ showPage( w );
+ setTabEnabled( w, enabled );
+ blockSignals(false);
+
+ emit ( movedTab( from, to ) );
+}
+
+void KTabWidget::removePage( QWidget * w ) {
+ if ( d->m_automaticResizeTabs ) {
+ int index = indexOf( w );
+ if ( index != -1 )
+ d->m_tabNames.remove( d->m_tabNames.at( index ) );
+ }
+ QTabWidget::removePage( w );
+ if ( d->m_automaticResizeTabs )
+ resizeTabs();
+}
+
+
+bool KTabWidget::isEmptyTabbarSpace( const QPoint &point ) const
+{
+ QSize size( tabBar()->sizeHint() );
+ if ( ( tabPosition()==Top && point.y()< size.height() ) || ( tabPosition()==Bottom && point.y()>(height()-size.height() ) ) ) {
+ QWidget *rightcorner = cornerWidget( TopRight );
+ if ( rightcorner ) {
+ if ( point.x()>=width()-rightcorner->width() )
+ return false;
+ }
+ QWidget *leftcorner = cornerWidget( TopLeft );
+ if ( leftcorner ) {
+ if ( point.x()<=leftcorner->width() )
+ return false;
+ }
+ QTab *tab = tabBar()->selectTab( tabBar()->mapFromParent( point ) );
+ if( !tab )
+ return true;
+ }
+ return false;
+}
+
+void KTabWidget::setHoverCloseButton( bool button )
+{
+ static_cast<KTabBar*>(tabBar())->setHoverCloseButton( button );
+}
+
+bool KTabWidget::hoverCloseButton() const
+{
+ return static_cast<KTabBar*>(tabBar())->hoverCloseButton();
+}
+
+void KTabWidget::setHoverCloseButtonDelayed( bool delayed )
+{
+ static_cast<KTabBar*>(tabBar())->setHoverCloseButtonDelayed( delayed );
+}
+
+bool KTabWidget::hoverCloseButtonDelayed() const
+{
+ return static_cast<KTabBar*>(tabBar())->hoverCloseButtonDelayed();
+}
+
+void KTabWidget::setAutomaticResizeTabs( bool enabled )
+{
+ if ( d->m_automaticResizeTabs==enabled )
+ return;
+
+ d->m_automaticResizeTabs = enabled;
+ if ( enabled ) {
+ d->m_tabNames.clear();
+ for( int i = 0; i < count(); ++i )
+ d->m_tabNames.append( tabBar()->tabAt( i )->text() );
+ }
+ else
+ for( int i = 0; i < count(); ++i )
+ tabBar()->tabAt( i )->setText( d->m_tabNames[ i ] );
+ resizeTabs();
+}
+
+bool KTabWidget::automaticResizeTabs() const
+{
+ return d->m_automaticResizeTabs;
+}
+
+void KTabWidget::closeRequest( int index )
+{
+ emit( closeRequest( page( index ) ) );
+}
+
+void KTabWidget::resizeEvent( QResizeEvent *e )
+{
+ QTabWidget::resizeEvent( e );
+ resizeTabs();
+}
+
+#include "ktabwidget.moc"
diff --git a/kdeui/ktabwidget.h b/kdeui/ktabwidget.h
new file mode 100644
index 000000000..971c4af1d
--- /dev/null
+++ b/kdeui/ktabwidget.h
@@ -0,0 +1,294 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2003 Stephan Binner <binner@kde.org>
+ Copyright (C) 2003 Zack Rusin <zack@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KTABWIDGET_H
+#define KTABWIDGET_H
+
+#include <qtabwidget.h>
+#include <qstringlist.h>
+
+#include <kdelibs_export.h>
+
+class KTabWidgetPrivate;
+
+/**
+ * \brief A widget containing multiple tabs
+ *
+ * @since 3.2
+ */
+class KDEUI_EXPORT KTabWidget : public QTabWidget
+{
+ Q_OBJECT
+ Q_PROPERTY( bool tabReorderingEnabled READ isTabReorderingEnabled WRITE setTabReorderingEnabled )
+ Q_PROPERTY( bool hoverCloseButton READ hoverCloseButton WRITE setHoverCloseButton )
+ Q_PROPERTY( bool hoverCloseButtonDelayed READ hoverCloseButtonDelayed WRITE setHoverCloseButtonDelayed )
+ Q_PROPERTY( bool tabCloseActivatePrevious READ tabCloseActivatePrevious WRITE setTabCloseActivatePrevious )
+ Q_PROPERTY( bool automaticResizeTabs READ automaticResizeTabs WRITE setAutomaticResizeTabs )
+
+public:
+ KTabWidget( QWidget *parent = 0, const char *name = 0, WFlags f = 0 );
+ /**
+ * Destructor.
+ */
+ virtual ~KTabWidget();
+ /*!
+ Set the tab of the given widget to \a color.
+ */
+ void setTabColor( QWidget *, const QColor& color );
+ /*!
+ Returns the tab color for the given widget.
+ */
+ QColor tabColor( QWidget * ) const;
+
+ /*!
+ Returns true if tab ordering with the middle mouse button
+ has been enabled.
+ */
+ bool isTabReorderingEnabled() const;
+
+ /*!
+ Returns true if the close button is shown on tabs
+ when mouse is hovering over them.
+ */
+ bool hoverCloseButton() const;
+
+ /*!
+ Returns true if the close button is shown on tabs
+ after a delay.
+ */
+ bool hoverCloseButtonDelayed() const;
+
+ /*!
+ Returns true if closing the current tab activates the previous
+ actice tab instead of the one to the right.
+ @since 3.3
+ */
+ bool tabCloseActivatePrevious() const;
+
+ /*!
+ Returns true if calling setTitle() will resize tabs
+ to the width of the tab bar.
+ @since 3.4
+ */
+ bool automaticResizeTabs() const;
+
+ /*!
+ If \a hide is true, the tabbar is hidden along with any corner
+ widgets.
+ @since 3.4
+ */
+ void setTabBarHidden( bool hide );
+
+ /*!
+ Returns true if the tabbar is hidden.
+ @since 3.4
+ */
+ bool isTabBarHidden() const;
+
+ /*!
+ Reimplemented for internal reasons.
+ */
+ virtual void insertTab( QWidget *, const QString &, int index = -1 );
+
+ /*!
+ Reimplemented for internal reasons.
+ */
+ virtual void insertTab( QWidget *child, const QIconSet& iconset,
+ const QString &label, int index = -1 );
+ /*!
+ Reimplemented for internal reasons.
+ */
+ virtual void insertTab( QWidget *, QTab *, int index = -1 );
+
+ /*!
+ Reimplemented for internal reasons.
+ */
+ void changeTab( QWidget *, const QString & );
+
+ /*!
+ Reimplemented for internal reasons.
+ */
+ void changeTab( QWidget *child, const QIconSet& iconset, const QString &label );
+
+ /*!
+ Reimplemented for internal reasons.
+ */
+ QString label( int ) const;
+
+ /*!
+ Reimplemented for internal reasons.
+ */
+ QString tabLabel( QWidget * ) const;
+
+ /*!
+ Reimplemented for internal reasons.
+ */
+ void setTabLabel( QWidget *, const QString & );
+
+public slots:
+ /*!
+ Move a widget's tab from first to second specified index and emit
+ signal movedTab( int, int ) afterwards.
+ */
+ virtual void moveTab( int, int );
+
+ /*!
+ Removes the widget, reimplemented for
+ internal reasons (keeping labels in sync).
+ */
+ virtual void removePage ( QWidget * w );
+
+ /*!
+ If \a enable is true, tab reordering with middle button will be enabled.
+
+ Note that once enabled you shouldn't rely on previously queried
+ currentPageIndex() or indexOf( QWidget * ) values anymore.
+
+ You can connect to signal movedTab(int, int) which will notify
+ you from which index to which index a tab has been moved.
+ */
+ void setTabReorderingEnabled( bool enable );
+
+ /*!
+ If \a enable is true, a close button will be shown on mouse hover
+ over tab icons which will emit signal closeRequest( QWidget * )
+ when pressed.
+ */
+ void setHoverCloseButton( bool enable );
+
+ /*!
+ If \a delayed is true, a close button will be shown on mouse hover
+ over tab icons after mouse double click delay else immediately.
+ */
+ void setHoverCloseButtonDelayed( bool delayed );
+
+ /*!
+ If \a previous is true, closing the current tab activates the
+ previous active tab instead of the one to the right.
+ @since 3.3
+ */
+ void setTabCloseActivatePrevious( bool previous );
+
+ /*!
+ If \a enable is true, tabs will be resized to the width of the tab bar.
+
+ Does not work reliable with "QTabWidget* foo=new KTabWidget()" and if
+ you change tabs via the tabbar or by accessing tabs directly.
+ @since 3.4
+ */
+ void setAutomaticResizeTabs( bool enable );
+
+signals:
+ /*!
+ Connect to this and set accept to true if you can and want to decode the event.
+ */
+ void testCanDecode(const QDragMoveEvent *e, bool &accept /* result */);
+
+ /*!
+ Received an event in the empty space beside tabbar. Usually creates a new tab.
+ This signal is only possible after testCanDecode and positive accept result.
+ */
+ void receivedDropEvent( QDropEvent * );
+
+ /*!
+ Received an drop event on given widget's tab.
+ This signal is only possible after testCanDecode and positive accept result.
+ */
+ void receivedDropEvent( QWidget *, QDropEvent * );
+
+ /*!
+ Request to start a drag operation on the given tab.
+ */
+ void initiateDrag( QWidget * );
+
+ /*!
+ The right mouse button was pressed over empty space besides tabbar.
+ */
+ void contextMenu( const QPoint & );
+
+ /*!
+ The right mouse button was pressed over a widget.
+ */
+ void contextMenu( QWidget *, const QPoint & );
+
+ /*!
+ A tab was moved from first to second index. This signal is only
+ possible after you have called setTabReorderingEnabled( true ).
+ */
+ void movedTab( int, int );
+
+ /*!
+ A double left mouse button click was performed over empty space besides tabbar.
+ @since 3.3
+ */
+ void mouseDoubleClick();
+
+ /*!
+ A double left mouse button click was performed over the widget.
+ */
+ void mouseDoubleClick( QWidget * );
+
+ /*!
+ A middle mouse button click was performed over empty space besides tabbar.
+ */
+ void mouseMiddleClick();
+
+ /*!
+ A middle mouse button click was performed over the widget.
+ */
+ void mouseMiddleClick( QWidget * );
+
+ /*!
+ The close button of a widget's tab was clicked. This signal is
+ only possible after you have called setHoverCloseButton( true ).
+ */
+ void closeRequest( QWidget * );
+
+protected:
+ virtual void mouseDoubleClickEvent( QMouseEvent *e );
+ virtual void mousePressEvent( QMouseEvent * );
+ virtual void dragMoveEvent( QDragMoveEvent * );
+ virtual void dropEvent( QDropEvent * );
+ unsigned int tabBarWidthForMaxChars( uint maxLength );
+#ifndef QT_NO_WHEELEVENT
+ virtual void wheelEvent( QWheelEvent *e );
+#endif
+ virtual void resizeEvent( QResizeEvent * );
+
+protected slots:
+ virtual void receivedDropEvent( int, QDropEvent * );
+ virtual void initiateDrag( int );
+ virtual void contextMenu( int, const QPoint & );
+ virtual void mouseDoubleClick( int );
+ virtual void mouseMiddleClick( int );
+ virtual void closeRequest( int );
+#ifndef QT_NO_WHEELEVENT
+ virtual void wheelDelta( int );
+#endif
+
+private:
+ bool isEmptyTabbarSpace( const QPoint & ) const;
+ void resizeTabs( int changedTabIndex = -1 );
+ void updateTab( int index );
+
+ KTabWidgetPrivate *d;
+};
+
+#endif
diff --git a/kdeui/ktextbrowser.cpp b/kdeui/ktextbrowser.cpp
new file mode 100644
index 000000000..4abc268d2
--- /dev/null
+++ b/kdeui/ktextbrowser.cpp
@@ -0,0 +1,145 @@
+/* This file is part of the KDE Libraries
+ * Copyright (C) 1999-2000 Espen Sand (espen@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#include <qpopupmenu.h>
+#include <kapplication.h>
+#include <kglobalsettings.h>
+#include <ktextbrowser.h>
+#include <kcursor.h>
+#include <kurl.h>
+#include <kiconloader.h>
+
+KTextBrowser::KTextBrowser( QWidget *parent, const char *name,
+ bool notifyClick )
+ : QTextBrowser( parent, name ), mNotifyClick(notifyClick)
+{
+ //
+ //1999-10-04 Espen Sand: Not required anymore ?
+ //connect( this, SIGNAL(highlighted(const QString &)),
+ // this, SLOT(refChanged(const QString &)));
+}
+
+KTextBrowser::~KTextBrowser( void )
+{
+}
+
+
+void KTextBrowser::setNotifyClick( bool notifyClick )
+{
+ mNotifyClick = notifyClick;
+}
+
+
+bool KTextBrowser::isNotifyClick() const
+{
+ return mNotifyClick;
+}
+
+
+void KTextBrowser::setSource( const QString& name )
+{
+ if( name.isNull() )
+ {
+ return;
+ }
+
+ if( name.find('@') > -1 )
+ {
+ if( !mNotifyClick )
+ {
+ kapp->invokeMailer( KURL( name ) );
+ }
+ else
+ {
+ emit mailClick( QString::null, name );
+ }
+ }
+ else
+ {
+ if( !mNotifyClick )
+ {
+ kapp->invokeBrowser( name );
+ }
+ else
+ {
+ emit urlClick( name );
+ }
+ }
+}
+
+
+void KTextBrowser::keyPressEvent(QKeyEvent *e)
+{
+ if( e->key() == Key_Escape )
+ {
+ e->ignore();
+ }
+ else if( e->key() == Key_F1 )
+ {
+ e->ignore();
+ }
+ else
+ {
+ QTextBrowser::keyPressEvent(e);
+ }
+}
+
+void KTextBrowser::viewportMouseMoveEvent( QMouseEvent* e)
+{
+ // do this first so we get the right type of cursor
+ QTextBrowser::viewportMouseMoveEvent(e);
+
+ if ( viewport()->cursor().shape() == PointingHandCursor )
+ viewport()->setCursor( KCursor::handCursor() );
+}
+
+void KTextBrowser::contentsWheelEvent( QWheelEvent *e )
+{
+ if ( KGlobalSettings::wheelMouseZooms() )
+ QTextBrowser::contentsWheelEvent( e );
+ else // thanks, we don't want to zoom, so skip QTextEdit's impl.
+ QScrollView::contentsWheelEvent( e );
+}
+
+QPopupMenu *KTextBrowser::createPopupMenu( const QPoint & pos )
+{
+ enum { IdUndo, IdRedo, IdSep1, IdCut, IdCopy, IdPaste, IdClear, IdSep2, IdSelectAll };
+
+ QPopupMenu *popup = QTextBrowser::createPopupMenu( pos );
+
+ if ( isReadOnly() )
+ popup->changeItem( popup->idAt(0), SmallIconSet("editcopy"), popup->text( popup->idAt(0) ) );
+ else {
+ int id = popup->idAt(0);
+ popup->changeItem( id - IdUndo, SmallIconSet("undo"), popup->text( id - IdUndo) );
+ popup->changeItem( id - IdRedo, SmallIconSet("redo"), popup->text( id - IdRedo) );
+ popup->changeItem( id - IdCut, SmallIconSet("editcut"), popup->text( id - IdCut) );
+ popup->changeItem( id - IdCopy, SmallIconSet("editcopy"), popup->text( id - IdCopy) );
+ popup->changeItem( id - IdPaste, SmallIconSet("editpaste"), popup->text( id - IdPaste) );
+ popup->changeItem( id - IdClear, SmallIconSet("editclear"), popup->text( id - IdClear) );
+ }
+
+ return popup;
+}
+
+void KTextBrowser::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "ktextbrowser.moc"
diff --git a/kdeui/ktextbrowser.h b/kdeui/ktextbrowser.h
new file mode 100644
index 000000000..68fa7f18e
--- /dev/null
+++ b/kdeui/ktextbrowser.h
@@ -0,0 +1,133 @@
+/* This file is part of the KDE Libraries
+ * Copyright (C) 1999 Espen Sand (espensa@online.no)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _KTEXT_BROWSER_H_
+#define _KTEXT_BROWSER_H_
+
+#include <qtextbrowser.h>
+
+#include <kdelibs_export.h>
+
+/**
+ * @short Extended QTextBrowser.
+ *
+ * An extended QTextBrowser.
+ *
+ * By default it will
+ * invoke the system mailer or the system browser when a link is
+ * activated, or it can emit the signal urlClick() or mailClick()
+ * when a link is activated.
+ *
+ * \image html ktextbrowser.png "KDE Text Browser"
+ *
+ * @author Espen Sand (espensa@online.no)
+ */
+
+class KDEUI_EXPORT KTextBrowser : public QTextBrowser
+{
+ Q_OBJECT
+ Q_PROPERTY( bool notifyClick READ isNotifyClick WRITE setNotifyClick )
+
+ public:
+ /**
+ * Constructor.
+ *
+ * @param parent Parent of the widget.
+ * @param name Widget name.
+ * @param notifyClick @p true causes signals to be emitted.
+ */
+ KTextBrowser( QWidget *parent=0, const char *name=0,
+ bool notifyClick=false );
+
+ /**
+ * Destructor.
+ */
+ ~KTextBrowser( void );
+
+ /**
+ * Decide whether a click on a link should be handled internally
+ * or if a signal should be emitted.
+ *
+ * @param notifyClick @p true causes signals to be emitted.
+ */
+ void setNotifyClick( bool notifyClick );
+ /**
+ * Returns whether a click on a link should be handled internally
+ * or if a signal should be emitted.
+ */
+ bool isNotifyClick() const;
+
+ protected:
+ /**
+ Reimplemented to NOT set the source but to do the special handling.
+ Do not call.
+ */
+ void setSource(const QString& name);
+
+ /**
+ * Makes sure Key_Escape is ignored
+ */
+ virtual void keyPressEvent(QKeyEvent *e);
+
+ /**
+ * Make sure we use our own hand cursor
+ */
+ virtual void viewportMouseMoveEvent( QMouseEvent* e);
+
+ /**
+ * Reimplemented to support Qt2 behavior (Ctrl-Wheel = fast scroll)
+ */
+ virtual void contentsWheelEvent( QWheelEvent *e );
+
+ /**
+ * Re-implemented for internal reasons. API not affected.
+ *
+ * See QLineEdit::createPopupMenu().
+ */
+ virtual QPopupMenu *createPopupMenu( const QPoint &pos );
+
+ signals:
+ /**
+ * Emitted when a mail link has been activated and the widget has
+ * been configured to emit the signal.
+ *
+ * @param name The destination name. It is QString::null at the moment.
+ * @param address The destination address.
+ */
+ void mailClick( const QString &name, const QString &address );
+
+ /**
+ * Emitted if mailClick() is not emitted and the widget has been
+ * configured to emit the signal.
+ *
+ * @param url The destination address.
+ */
+ void urlClick( const QString &url );
+
+ private:
+ bool mNotifyClick;
+
+ protected:
+ virtual void virtual_hook( int id, void* data );
+ private:
+ class KTextBrowserPrivate;
+ KTextBrowserPrivate *d;
+};
+
+#endif
diff --git a/kdeui/ktextedit.cpp b/kdeui/ktextedit.cpp
new file mode 100644
index 000000000..a368a56d0
--- /dev/null
+++ b/kdeui/ktextedit.cpp
@@ -0,0 +1,419 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "ktextedit.h"
+
+#include <qapplication.h>
+#include <qclipboard.h>
+#include <qpopupmenu.h>
+
+#include <ksyntaxhighlighter.h>
+#include <kspell.h>
+#include <kcursor.h>
+#include <kglobalsettings.h>
+#include <kstdaccel.h>
+#include <kiconloader.h>
+#include <klocale.h>
+
+class KTextEdit::KTextEditPrivate
+{
+public:
+ KTextEditPrivate()
+ : customPalette( false ),
+ checkSpellingEnabled( false ),
+ highlighter( 0 ),
+ spell( 0 )
+ {}
+ ~KTextEditPrivate() {
+ delete highlighter;
+ delete spell;
+ }
+
+ bool customPalette;
+ bool checkSpellingEnabled;
+ KDictSpellingHighlighter *highlighter;
+ KSpell *spell;
+};
+
+KTextEdit::KTextEdit( const QString& text, const QString& context,
+ QWidget *parent, const char *name )
+ : QTextEdit ( text, context, parent, name )
+{
+ d = new KTextEditPrivate();
+ KCursor::setAutoHideCursor( this, true, false );
+}
+
+KTextEdit::KTextEdit( QWidget *parent, const char *name )
+ : QTextEdit ( parent, name )
+{
+ d = new KTextEditPrivate();
+ KCursor::setAutoHideCursor( this, true, false );
+}
+
+KTextEdit::~KTextEdit()
+{
+ delete d;
+}
+
+void KTextEdit::keyPressEvent( QKeyEvent *e )
+{
+ KKey key( e );
+
+ if ( KStdAccel::copy().contains( key ) ) {
+ copy();
+ e->accept();
+ return;
+ }
+ else if ( KStdAccel::paste().contains( key ) ) {
+ paste();
+ e->accept();
+ return;
+ }
+ else if ( KStdAccel::cut().contains( key ) ) {
+ cut();
+ e->accept();
+ return;
+ }
+ else if ( KStdAccel::undo().contains( key ) ) {
+ undo();
+ e->accept();
+ return;
+ }
+ else if ( KStdAccel::redo().contains( key ) ) {
+ redo();
+ e->accept();
+ return;
+ }
+ else if ( KStdAccel::deleteWordBack().contains( key ) )
+ {
+ deleteWordBack();
+ e->accept();
+ return;
+ }
+ else if ( KStdAccel::deleteWordForward().contains( key ) )
+ {
+ deleteWordForward();
+ e->accept();
+ return;
+ }
+ else if ( KStdAccel::backwardWord().contains( key ) )
+ {
+ CursorAction action = MoveWordBackward;
+ int para, index;
+ getCursorPosition( &para, & index );
+ if (text(para).isRightToLeft())
+ action = MoveWordForward;
+ moveCursor(action, false );
+ e->accept();
+ return;
+ }
+ else if ( KStdAccel::forwardWord().contains( key ) )
+ {
+ CursorAction action = MoveWordForward;
+ int para, index;
+ getCursorPosition( &para, & index );
+ if (text(para).isRightToLeft())
+ action = MoveWordBackward;
+ moveCursor( action, false );
+ e->accept();
+ return;
+ }
+ else if ( KStdAccel::next().contains( key ) )
+ {
+ moveCursor( MovePgDown, false );
+ e->accept();
+ return;
+ }
+ else if ( KStdAccel::prior().contains( key ) )
+ {
+ moveCursor( MovePgUp, false );
+ e->accept();
+ return;
+ }
+ else if ( KStdAccel::home().contains( key ) )
+ {
+ moveCursor( MoveHome, false );
+ e->accept();
+ return;
+ }
+ else if ( KStdAccel::end().contains( key ) )
+ {
+ moveCursor( MoveEnd, false );
+ e->accept();
+ return;
+ }
+ else if ( KStdAccel::beginningOfLine().contains( key ) )
+ {
+ moveCursor( MoveLineStart, false );
+ e->accept();
+ return;
+ }
+ else if ( KStdAccel::endOfLine().contains( key ) )
+ {
+ moveCursor(MoveLineEnd, false);
+ e->accept();
+ return;
+ }
+ else if ( KStdAccel::pasteSelection().contains( key ) )
+ {
+ QString text = QApplication::clipboard()->text( QClipboard::Selection);
+ if ( !text.isEmpty() )
+ insert( text );
+ e->accept();
+ return;
+ }
+
+ // ignore Ctrl-Return so that KDialogs can close the dialog
+ else if ( e->state() == ControlButton &&
+ (e->key() == Key_Return || e->key() == Key_Enter) &&
+ topLevelWidget()->inherits( "KDialog" ) )
+ {
+ e->ignore();
+ return;
+ }
+
+ QTextEdit::keyPressEvent( e );
+}
+
+void KTextEdit::deleteWordBack()
+{
+ removeSelection();
+ moveCursor( MoveWordBackward, true );
+ removeSelectedText();
+}
+
+void KTextEdit::deleteWordForward()
+{
+ removeSelection();
+ moveCursor( MoveWordForward, true );
+ removeSelectedText();
+}
+
+void KTextEdit::slotAllowTab()
+{
+setTabChangesFocus(!tabChangesFocus());
+}
+
+QPopupMenu *KTextEdit::createPopupMenu( const QPoint &pos )
+{
+ enum { IdUndo, IdRedo, IdSep1, IdCut, IdCopy, IdPaste, IdClear, IdSep2, IdSelectAll };
+
+ QPopupMenu *menu = QTextEdit::createPopupMenu( pos );
+
+ if ( isReadOnly() )
+ menu->changeItem( menu->idAt(0), SmallIconSet("editcopy"), menu->text( menu->idAt(0) ) );
+ else {
+ int id = menu->idAt(0);
+ menu->changeItem( id - IdUndo, SmallIconSet("undo"), menu->text( id - IdUndo) );
+ menu->changeItem( id - IdRedo, SmallIconSet("redo"), menu->text( id - IdRedo) );
+ menu->changeItem( id - IdCut, SmallIconSet("editcut"), menu->text( id - IdCut) );
+ menu->changeItem( id - IdCopy, SmallIconSet("editcopy"), menu->text( id - IdCopy) );
+ menu->changeItem( id - IdPaste, SmallIconSet("editpaste"), menu->text( id - IdPaste) );
+ menu->changeItem( id - IdClear, SmallIconSet("editclear"), menu->text( id - IdClear) );
+
+ menu->insertSeparator();
+ id = menu->insertItem( SmallIconSet( "spellcheck" ), i18n( "Check Spelling..." ),
+ this, SLOT( checkSpelling() ) );
+
+ if( text().isEmpty() )
+ menu->setItemEnabled( id, false );
+
+ id = menu->insertItem( i18n( "Auto Spell Check" ),
+ this, SLOT( toggleAutoSpellCheck() ) );
+ menu->setItemChecked(id, d->checkSpellingEnabled);
+ menu->insertSeparator();
+ id=menu->insertItem(i18n("Allow Tabulations"),this,SLOT(slotAllowTab()));
+ menu->setItemChecked(id, !tabChangesFocus());
+ }
+
+ return menu;
+}
+
+QPopupMenu *KTextEdit::createPopupMenu()
+{
+ return QTextEdit::createPopupMenu();
+}
+
+void KTextEdit::contentsWheelEvent( QWheelEvent *e )
+{
+ if ( KGlobalSettings::wheelMouseZooms() )
+ QTextEdit::contentsWheelEvent( e );
+ else // thanks, we don't want to zoom, so skip QTextEdit's impl.
+ QScrollView::contentsWheelEvent( e );
+}
+
+void KTextEdit::setPalette( const QPalette& palette )
+{
+ QTextEdit::setPalette( palette );
+ // unsetPalette() is not virtual and calls setPalette() as well
+ // so we can use ownPalette() to find out about unsetting
+ d->customPalette = ownPalette();
+}
+
+void KTextEdit::toggleAutoSpellCheck()
+{
+ setCheckSpellingEnabled( !d->checkSpellingEnabled );
+}
+
+void KTextEdit::setCheckSpellingEnabled( bool check )
+{
+ if ( check == d->checkSpellingEnabled )
+ return;
+
+ // From the above statment we know know that if we're turning checking
+ // on that we need to create a new highlighter and if we're turning it
+ // off we should remove the old one.
+
+ d->checkSpellingEnabled = check;
+ if ( check )
+ {
+ if (hasFocus())
+ d->highlighter = new KDictSpellingHighlighter( this );
+ }
+ else
+ {
+ delete d->highlighter;
+ d->highlighter = 0;
+ }
+}
+
+void KTextEdit::focusInEvent( QFocusEvent *e )
+{
+ if ( d->checkSpellingEnabled && !isReadOnly() && !d->highlighter )
+ d->highlighter = new KDictSpellingHighlighter( this );
+
+ QTextEdit::focusInEvent( e );
+}
+
+bool KTextEdit::checkSpellingEnabled() const
+{
+ return d->checkSpellingEnabled;
+}
+
+void KTextEdit::setReadOnly(bool readOnly)
+{
+ if ( !readOnly && hasFocus() && d->checkSpellingEnabled && !d->highlighter )
+ d->highlighter = new KDictSpellingHighlighter( this );
+
+ if ( readOnly == isReadOnly() )
+ return;
+
+ if (readOnly)
+ {
+ delete d->highlighter;
+ d->highlighter = 0;
+
+ bool custom = ownPalette();
+ QPalette p = palette();
+ QColor color = p.color(QPalette::Disabled, QColorGroup::Background);
+ p.setColor(QColorGroup::Base, color);
+ p.setColor(QColorGroup::Background, color);
+ setPalette(p);
+ d->customPalette = custom;
+ }
+ else
+ {
+ if ( d->customPalette )
+ {
+ QPalette p = palette();
+ QColor color = p.color(QPalette::Normal, QColorGroup::Base);
+ p.setColor(QColorGroup::Base, color);
+ p.setColor(QColorGroup::Background, color);
+ setPalette( p );
+ }
+ else
+ unsetPalette();
+ }
+
+ QTextEdit::setReadOnly (readOnly);
+}
+
+void KTextEdit::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void KTextEdit::checkSpelling()
+{
+ delete d->spell;
+ d->spell = new KSpell( this, i18n( "Spell Checking" ),
+ this, SLOT( slotSpellCheckReady( KSpell *) ), 0, true, true);
+
+ connect( d->spell, SIGNAL( death() ),
+ this, SLOT( spellCheckerFinished() ) );
+
+ connect( d->spell, SIGNAL( misspelling( const QString &, const QStringList &, unsigned int ) ),
+ this, SLOT( spellCheckerMisspelling( const QString &, const QStringList &, unsigned int ) ) );
+
+ connect( d->spell, SIGNAL( corrected( const QString &, const QString &, unsigned int ) ),
+ this, SLOT( spellCheckerCorrected( const QString &, const QString &, unsigned int ) ) );
+}
+
+void KTextEdit::spellCheckerMisspelling( const QString &text, const QStringList &, unsigned int pos )
+{
+ highLightWord( text.length(), pos );
+}
+
+void KTextEdit::spellCheckerCorrected( const QString &oldWord, const QString &newWord, unsigned int pos )
+{
+ unsigned int l = 0;
+ unsigned int cnt = 0;
+ if ( oldWord != newWord ) {
+ posToRowCol( pos, l, cnt );
+ setSelection( l, cnt, l, cnt + oldWord.length() );
+ removeSelectedText();
+ insert( newWord );
+ }
+}
+
+void KTextEdit::posToRowCol(unsigned int pos, unsigned int &line, unsigned int &col)
+{
+ for ( line = 0; line < static_cast<uint>( lines() ) && col <= pos; line++ )
+ col += paragraphLength( line ) + 1;
+
+ line--;
+ col = pos - col + paragraphLength( line ) + 1;
+}
+
+void KTextEdit::spellCheckerFinished()
+{
+ delete d->spell;
+ d->spell = 0L;
+}
+
+void KTextEdit::slotSpellCheckReady( KSpell *s )
+{
+ s->check( text() );
+ connect( s, SIGNAL( done( const QString & ) ), this, SLOT( slotSpellCheckDone( const QString & ) ) );
+}
+
+void KTextEdit::slotSpellCheckDone( const QString &s )
+{
+ if ( s != text() )
+ setText( s );
+}
+
+
+void KTextEdit::highLightWord( unsigned int length, unsigned int pos )
+{
+ unsigned int l = 0;
+ unsigned int cnt = 0;
+ posToRowCol( pos, l, cnt );
+ setSelection( l, cnt, l, cnt + length );
+}
+
+#include "ktextedit.moc"
diff --git a/kdeui/ktextedit.h b/kdeui/ktextedit.h
new file mode 100644
index 000000000..df08ddc9a
--- /dev/null
+++ b/kdeui/ktextedit.h
@@ -0,0 +1,174 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KTEXTEDIT_H
+#define KTEXTEDIT_H
+
+#include <qtextedit.h>
+
+#include <kdelibs_export.h>
+
+class KSpell;
+
+/**
+ * @short A KDE'ified QTextEdit
+ *
+ * This is just a little subclass of QTextEdit, implementing
+ * some standard KDE features, like Cursor auto-hiding, configurable
+ * wheelscrolling (fast-scroll or zoom) and deleting of entire
+ * words with Ctrl-Backspace or Ctrl-Delete.
+ *
+ * Basic rule: whenever you want to use QTextEdit, use KTextEdit!
+ *
+ * @see QTextEdit
+ * @author Carsten Pfeiffer <pfeiffer@kde.org>
+ * @since 3.1
+ */
+class KDEUI_EXPORT KTextEdit : public QTextEdit
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Constructs a KTextEdit object. See QTextEdit::QTextEdit
+ * for details.
+ */
+ KTextEdit( const QString& text,
+ const QString& context = QString::null,
+ QWidget * parent = 0, const char *name = 0 );
+ /**
+ * Constructs a KTextEdit object. See QTextEdit::QTextEdit
+ * for details.
+ */
+
+ KTextEdit( QWidget *parent = 0L, const char *name = 0 );
+ /**
+ * Destroys the KTextEdit object.
+ */
+ ~KTextEdit();
+
+ /**
+ * Reimplemented to set a proper "deactivated" background color.
+ */
+ virtual void setReadOnly (bool readOnly);
+
+ /**
+ * Reimplemented for tracking custom palettes.
+ */
+ virtual void setPalette( const QPalette& palette );
+
+ /**
+ * Turns spell checking for this text edit on or off. Note that spell
+ * checking is only available in read-writable KTextEdits.
+ *
+ * @see checkSpellingEnabled()
+ * @see isReadOnly()
+ * @see setReadOnly()
+ * @since 3.2
+ */
+ void setCheckSpellingEnabled( bool check );
+
+ /**
+ * Returns true if spell checking is enabled for this text edit.
+ * Note that it even returns true if this is a read-only KTextEdit,
+ * where spell checking is actually disabled.
+ *
+ @ see setCheckSpellingEnabled()
+ * @since 3.2
+ */
+ bool checkSpellingEnabled() const;
+
+ void highLightWord( unsigned int length, unsigned int pos );
+
+
+public slots:
+ /**
+ * Create a modal dialog to check the spelling. This slot will not return
+ * until spell checking has been completed.
+ *
+ * @since 3.2
+ */
+ void checkSpelling();
+
+protected:
+ /**
+ * Reimplemented to catch "delete word" key events.
+ */
+ virtual void keyPressEvent( QKeyEvent * );
+
+ /**
+ * Reimplemented to instantiate a KDictSpellingHighlighter, if
+ * spellchecking is enabled.
+ */
+ virtual void focusInEvent( QFocusEvent * );
+
+ /**
+ * Reimplemented to allow fast-wheelscrolling with Ctrl-Wheel
+ * or zoom.
+ */
+ virtual void contentsWheelEvent( QWheelEvent * );
+
+ /**
+ * Deletes a word backwards from the current cursor position,
+ * if available.
+ */
+ virtual void deleteWordBack();
+
+ /**
+ * Deletes a word forwards from the current cursor position,
+ * if available.
+ */
+ virtual void deleteWordForward();
+
+ /**
+ * Reimplemented from QTextEdit to add spelling related items
+ * when appropriate.
+ */
+ virtual QPopupMenu *createPopupMenu( const QPoint &pos );
+
+ /**
+ * This is just a reimplementation of a deprecated method from QTextEdit and
+ * is just here to keep source compatibility. This should not be used in
+ * new code. Specifically reimplementing this method will probably not do
+ * what you expect. See the method above.
+ *
+ * @deprecated
+ */
+ virtual QPopupMenu *createPopupMenu();
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+
+private slots:
+ void slotSpellCheckReady( KSpell *s );
+ void slotSpellCheckDone( const QString &s );
+ void spellCheckerMisspelling( const QString &text, const QStringList &, unsigned int pos);
+ void spellCheckerCorrected( const QString &, const QString &, unsigned int );
+ void spellCheckerFinished();
+ void toggleAutoSpellCheck();
+ void slotAllowTab();
+
+private:
+ void posToRowCol( unsigned int pos, unsigned int &line, unsigned int &col );
+
+ class KTextEditPrivate;
+ KTextEditPrivate *d;
+};
+
+#endif // KTEXTEDIT_H
diff --git a/kdeui/ktimewidget.cpp b/kdeui/ktimewidget.cpp
new file mode 100644
index 000000000..6a3ec4bb3
--- /dev/null
+++ b/kdeui/ktimewidget.cpp
@@ -0,0 +1,58 @@
+#include <qdatetimeedit.h>
+#include <qlayout.h>
+
+#include "kdebug.h"
+#include "kdialog.h"
+
+#include "ktimewidget.h"
+
+class KTimeWidget::KTimeWidgetPrivate
+{
+public:
+ QTimeEdit * timeWidget;
+};
+
+KTimeWidget::KTimeWidget(QWidget * parent, const char * name)
+ : QWidget(parent, name)
+{
+ init();
+}
+
+KTimeWidget::KTimeWidget(const QTime & time,
+ QWidget * parent, const char * name)
+ : QWidget(parent, name)
+{
+ init();
+
+ setTime(time);
+}
+
+KTimeWidget::~KTimeWidget()
+{
+ delete d;
+}
+
+void KTimeWidget::init()
+{
+ d = new KTimeWidgetPrivate;
+
+ QHBoxLayout *layout = new QHBoxLayout(this, 0, KDialog::spacingHint());
+ layout->setAutoAdd(true);
+
+ d->timeWidget = new QTimeEdit(this);
+
+ connect(d->timeWidget, SIGNAL(valueChanged(const QTime &)),
+ SIGNAL(valueChanged(const QTime &)));
+}
+
+void KTimeWidget::setTime(const QTime & time)
+{
+ d->timeWidget->setTime(time);
+}
+
+QTime KTimeWidget::time() const
+{
+ return d->timeWidget->time();
+}
+
+#include "ktimewidget.moc"
diff --git a/kdeui/ktimewidget.h b/kdeui/ktimewidget.h
new file mode 100644
index 000000000..1e263dafd
--- /dev/null
+++ b/kdeui/ktimewidget.h
@@ -0,0 +1,86 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2002 Hans Petter bieker <bieker@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __KTIMEWIDGET__
+#define __KTIMEWIDGET__
+
+#include <qwidget.h>
+#include <qdatetime.h>
+
+#include <kdelibs_export.h>
+
+/**
+ * @short A time selection widget.
+ *
+ * This widget can be used to display or allow user selection of time.
+ *
+ * \image html ktimewidget.png "KDE Time Widget"
+ *
+ * @author Hans Petter Bieker <bieker@kde.org>
+ * @since 3.2
+ */
+class KDEUI_EXPORT KTimeWidget : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY( QTime time READ time WRITE setTime )
+
+public:
+ /**
+ * Constructs a time selection widget.
+ */
+ KTimeWidget(QWidget * parent = 0, const char * name = 0);
+
+ /**
+ * Constructs a time selection widget with the initial time set to
+ * @p time.
+ */
+ KTimeWidget(const QTime & time,
+ QWidget * parent = 0, const char * name = 0 );
+
+ /**
+ * Destructs the time selection widget.
+ */
+ virtual ~KTimeWidget();
+
+ /**
+ * Returns the currently selected time.
+ */
+ QTime time() const;
+
+public slots:
+ /**
+ * Changes the selected time to @p time.
+ */
+ void setTime(const QTime & time);
+
+signals:
+ /**
+ * Emitted whenever the time of the widget
+ * is changed, either with setTime() or via user selection.
+ */
+ void valueChanged(const QTime & time);
+
+private:
+ void init();
+
+private:
+ class KTimeWidgetPrivate;
+ KTimeWidgetPrivate *d;
+};
+
+#endif
diff --git a/kdeui/ktimezonewidget.cpp b/kdeui/ktimezonewidget.cpp
new file mode 100644
index 000000000..879b26176
--- /dev/null
+++ b/kdeui/ktimezonewidget.cpp
@@ -0,0 +1,133 @@
+/*
+ Copyright (C) 2005, S.R.Haque <srhaque@iee.org>.
+ This file is part of the KDE project
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2, as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <kdialog.h>
+#include <kdebug.h>
+#include <kfile.h>
+#include <klistview.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <ktimezones.h>
+#include <ktimezonewidget.h>
+#include <qpixmap.h>
+#include <time.h>
+
+#define COLUMN_CITY 0
+#define COLUMN_REGION 1
+#define COLUMN_COMMENT 2
+#define COLUMN_ZONE 3
+
+KTimezoneWidget::KTimezoneWidget(QWidget *parent, const char *name, KTimezones *db) :
+ KListView(parent, name),
+ d(0)
+{
+ // If the user did not provide a timezone database, we'll use the system default.
+ bool userDb = (db != 0);
+ if (!userDb)
+ db = new KTimezones();
+
+ addColumn(i18n("Area"));
+ addColumn(i18n("Region"));
+ addColumn(i18n("Comment"));
+
+ const KTimezones::ZoneMap zones = db->allZones();
+ for (KTimezones::ZoneMap::ConstIterator it = zones.begin(); it != zones.end(); ++it)
+ {
+ const KTimezone *zone = it.data();
+ QString tzName = zone->name();
+ QString comment = zone->comment();
+ if (!comment.isEmpty())
+ comment = i18n(comment.utf8());
+
+ // Convert:
+ //
+ // "Europe/London", "GB" -> "London", "Europe/GB".
+ // "UTC", "" -> "UTC", "".
+ QStringList continentCity = QStringList::split("/", displayName(zone));
+ QListViewItem *listItem = new QListViewItem(this, continentCity[continentCity.count() - 1]);
+ continentCity[continentCity.count() - 1] = zone->countryCode();
+ listItem->setText(COLUMN_REGION, continentCity.join("/"));
+ listItem->setText(COLUMN_COMMENT, comment);
+ listItem->setText(COLUMN_ZONE, tzName); /* store complete path in ListView */
+
+ // Locate the flag from /l10n/%1/flag.png.
+ QString flag = locate("locale", QString("l10n/%1/flag.png").arg(zone->countryCode().lower()));
+ if (QFile::exists(flag))
+ listItem->setPixmap(COLUMN_REGION, QPixmap(flag));
+ }
+
+ if (!userDb)
+ delete db;
+
+}
+
+KTimezoneWidget::~KTimezoneWidget()
+{
+ // FIXME when needed:
+ // delete d;
+}
+
+QString KTimezoneWidget::displayName(const KTimezone *zone)
+{
+ return i18n(zone->name().utf8()).replace("_", " ");
+}
+
+QStringList KTimezoneWidget::selection() const
+{
+ QStringList selection;
+
+ // Loop through all entries.
+ QListViewItem *listItem = firstChild();
+ while (listItem)
+ {
+ if (listItem->isSelected())
+ {
+ selection.append(listItem->text(COLUMN_ZONE));
+ }
+ listItem = listItem->nextSibling();
+ }
+ return selection;
+}
+
+void KTimezoneWidget::setSelected(const QString &zone, bool selected)
+{
+ bool found = false;
+
+ // Loop through all entries.
+ QListViewItem *listItem = firstChild();
+ while (listItem)
+ {
+ if (listItem->text(COLUMN_ZONE) == zone)
+ {
+ KListView::setSelected(listItem, selected);
+
+ // Ensure the selected item is visible as appropriate.
+ listItem = selectedItem();
+ if (listItem)
+ ensureItemVisible(listItem);
+ found = true;
+ break;
+ }
+ listItem = listItem->nextSibling();
+ }
+ if (!found)
+ kdDebug() << "No such zone: " << zone << endl;
+}
+
+#include "ktimezonewidget.moc"
diff --git a/kdeui/ktimezonewidget.h b/kdeui/ktimezonewidget.h
new file mode 100644
index 000000000..9241b14a3
--- /dev/null
+++ b/kdeui/ktimezonewidget.h
@@ -0,0 +1,112 @@
+/*
+ Copyright (C) 2005, S.R.Haque <srhaque@iee.org>.
+ This file is part of the KDE project
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2, as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KTIMEZONEWIDGET_H
+#define KTIMEZONEWIDGET_H
+
+#include <kdelibs_export.h>
+#include <klistview.h>
+#include <qstring.h>
+
+class KTimezone;
+class KTimezones;
+class KTimezoneWidgetPrivate;
+
+/**
+ * @brief A timezone selection widget.
+ *
+ * \b Detail:
+ *
+ * This class provides for selection of one or more timezones.
+ *
+ * \b Example:
+ *
+ * To use the class to implement a system timezone selection feature:
+ * \code
+ *
+ * // This adds a timezone widget to a dialog.
+ * m_timezones = new KTimezoneWidget(this, "Timezones");
+ * ...
+ * \endcode
+ *
+ * To use the class to implement a multiple-choice custom timezone selector:
+ * \code
+ *
+ * m_timezones = new KTimezoneWidget(this, "Timezones", vcalendarTimezones);
+ * m_timezones->setSelectionModeExt(KListView::Multi);
+ * ...
+ * \endcode
+ *
+ * @author S.R.Haque <srhaque@iee.org>
+ * @since 3.5
+ */
+class KDEUI_EXPORT KTimezoneWidget :
+ public KListView
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Constructs a timezone selection widget.
+ *
+ * @param parent The parent widget.
+ * @param name The name of this widget.
+ * @param db The timezone database to use. If 0, the system timezone
+ * database is used.
+ */
+ KTimezoneWidget(QWidget *parent = 0, const char *name = 0, KTimezones *db = 0);
+
+ /**
+ * Destroys the timezone selection widget.
+ */
+ virtual ~KTimezoneWidget();
+
+ /**
+ * Returns the currently selected timezones. See QListView::selectionChanged().
+ *
+ * @return a list of timezone names, in the format used by the database
+ * supplied to the {@link KTimezoneWidget() } constructor.
+ */
+ QStringList selection() const;
+
+ /**
+ * Select/deselect the named timezone.
+ *
+ * @param zone The timezone name to be selected. Ignored if not recognised!
+ * @param selected The new selection state.
+ */
+ void setSelected(const QString &zone, bool selected);
+
+ /**
+ * Format a timezone name in a standardised manner. The returned value is
+ * transformed via an i18n lookup, so the caller should previously have
+ * set the timezone catalogue:
+ * \code
+ * KGlobal::locale()->insertCatalogue("timezones");
+ * \endcode
+ *
+ * @return formatted timezone name.
+ */
+ static QString displayName(const KTimezone *zone);
+
+private:
+ KTimezoneWidgetPrivate *d;
+};
+
+#endif
diff --git a/kdeui/ktip-background.png b/kdeui/ktip-background.png
new file mode 100644
index 000000000..be6876e57
--- /dev/null
+++ b/kdeui/ktip-background.png
Binary files differ
diff --git a/kdeui/ktip-bulb.png b/kdeui/ktip-bulb.png
new file mode 100644
index 000000000..c621def06
--- /dev/null
+++ b/kdeui/ktip-bulb.png
Binary files differ
diff --git a/kdeui/ktip.cpp b/kdeui/ktip.cpp
new file mode 100644
index 000000000..b74862ced
--- /dev/null
+++ b/kdeui/ktip.cpp
@@ -0,0 +1,424 @@
+/*****************************************************************
+
+Copyright (c) 2000-2003 Matthias Hoelzer-Kluepfel <mhk@kde.org>
+ Tobias Koenig <tokoe@kde.org>
+ Daniel Molkentin <molkentin@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qcheckbox.h>
+#include <qfile.h>
+#include <qhbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qregexp.h>
+#include <qtextstream.h>
+#include <qimage.h>
+
+#include <kaboutdata.h>
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kpushbutton.h>
+#include <kseparator.h>
+#include <kstandarddirs.h>
+#include <kstdguiitem.h>
+#include <ktextbrowser.h>
+#include <kiconeffect.h>
+#include <kglobalsettings.h>
+
+#ifdef Q_WS_X11
+#include <kwin.h>
+#endif
+
+#include "ktip.h"
+
+
+KTipDatabase::KTipDatabase(const QString &_tipFile)
+{
+ QString tipFile = _tipFile;
+ if (tipFile.isEmpty())
+ tipFile = QString::fromLatin1(KGlobal::instance()->aboutData()->appName()) + "/tips";
+
+ loadTips(tipFile);
+
+ if (!mTips.isEmpty())
+ mCurrent = kapp->random() % mTips.count();
+}
+
+
+KTipDatabase::KTipDatabase( const QStringList& tipsFiles )
+{
+ if ( tipsFiles.isEmpty() || ( ( tipsFiles.count() == 1 ) && tipsFiles.first().isEmpty() ) )
+ {
+ addTips(QString::fromLatin1(KGlobal::instance()->aboutData()->appName()) + "/tips");
+ }
+ else
+ {
+ for (QStringList::ConstIterator it = tipsFiles.begin(); it != tipsFiles.end(); ++it)
+ addTips( *it );
+ }
+ if (!mTips.isEmpty())
+ mCurrent = kapp->random() % mTips.count();
+
+}
+
+void KTipDatabase::loadTips(const QString &tipFile)
+{
+ mTips.clear();
+ addTips(tipFile);
+}
+
+// if you change something here, please update the script
+// preparetips, which depends on extracting exactly the same
+// text as done here.
+void KTipDatabase::addTips(const QString& tipFile )
+{
+ QString fileName = locate("data", tipFile);
+
+ if (fileName.isEmpty())
+ {
+ kdDebug() << "KTipDatabase::addTips: can't find '" << tipFile << "' in standard dirs" << endl;
+ return;
+ }
+
+ QFile file(fileName);
+ if (!file.open(IO_ReadOnly))
+ {
+ kdDebug() << "KTipDatabase::addTips: can't open '" << fileName << "' for reading" << endl;
+ return;
+ }
+
+ QByteArray data = file.readAll();
+ QString content = QString::fromUtf8(data.data(), data.size());
+ const QRegExp rx("\\n+");
+
+ int pos = -1;
+ while ((pos = content.find("<html>", pos + 1, false)) != -1)
+ {
+ // to make translations work, tip extraction here must exactly
+ // match what is done by the preparetips script
+ QString tip = content
+ .mid(pos + 6, content.find("</html>", pos, false) - pos - 6)
+ .replace(rx, "\n");
+ if (!tip.endsWith("\n"))
+ tip += "\n";
+ if (tip.startsWith("\n"))
+ tip = tip.mid(1);
+ if (tip.isEmpty())
+ {
+ kdDebug() << "Empty tip found! Skipping! " << pos << endl;
+ continue;
+ }
+ mTips.append(tip);
+ }
+
+ file.close();
+
+}
+
+void KTipDatabase::nextTip()
+{
+ if (mTips.isEmpty())
+ return ;
+ mCurrent += 1;
+ if (mCurrent >= (int) mTips.count())
+ mCurrent = 0;
+}
+
+
+void KTipDatabase::prevTip()
+{
+ if (mTips.isEmpty())
+ return ;
+ mCurrent -= 1;
+ if (mCurrent < 0)
+ mCurrent = mTips.count() - 1;
+}
+
+
+QString KTipDatabase::tip() const
+{
+ if (mTips.isEmpty())
+ return QString::null;
+ return mTips[mCurrent];
+}
+
+KTipDialog *KTipDialog::mInstance = 0;
+
+
+KTipDialog::KTipDialog(KTipDatabase *db, QWidget *parent, const char *name)
+ : KDialog(parent, name)
+{
+ /**
+ * Parent is 0L when TipDialog is used as a mainWidget. This should
+ * be the case only in ktip, so let's use the ktip layout.
+ */
+ bool isTipDialog = (parent);
+
+ QImage img;
+ int h,s,v;
+
+ mBlendedColor = KGlobalSettings::activeTitleColor();
+ mBlendedColor.hsv(&h,&s,&v);
+ mBlendedColor.setHsv(h, int(s*(71/76.0)), int(v*(67/93.0)));
+
+ if (!isTipDialog)
+ {
+ img = QImage(locate("data", "kdewizard/pics/wizard_small.png"));
+ // colorize and check to figure the correct color
+ KIconEffect::colorize(img, mBlendedColor, 1.0);
+ QRgb colPixel( img.pixel(0,0) );
+
+ mBlendedColor = QColor(qRed(colPixel),qGreen(colPixel),qBlue(colPixel));
+ }
+
+ mBaseColor = KGlobalSettings::alternateBackgroundColor();
+ mBaseColor.hsv(&h,&s,&v);
+ mBaseColor.setHsv(h, int(s*(10/6.0)), int(v*(93/99.0)));
+
+ mTextColor = KGlobalSettings::textColor();
+
+
+ mDatabase = db;
+
+ setCaption(i18n("Tip of the Day"));
+#ifdef Q_WS_X11
+ KWin::setIcons( winId(),
+ KGlobal::iconLoader()->loadIcon( "idea", KIcon::NoGroup, 32 ),
+ KGlobal::iconLoader()->loadIcon( "idea", KIcon::NoGroup, 16 ) );
+#endif
+ QVBoxLayout *vbox = new QVBoxLayout(this, marginHint(), spacingHint());
+
+ if (isTipDialog)
+ {
+ QHBoxLayout *pl = new QHBoxLayout(vbox, 0, 0);
+
+ QLabel *bulb = new QLabel(this);
+ bulb->setPixmap(locate("data", "kdeui/pics/ktip-bulb.png"));
+ pl->addWidget(bulb);
+
+ QLabel *titlePane = new QLabel(this);
+ titlePane->setBackgroundPixmap(locate("data", "kdeui/pics/ktip-background.png"));
+ titlePane->setText(i18n("Did you know...?\n"));
+ titlePane->setFont(QFont(KGlobalSettings::generalFont().family(), 20, QFont::Bold));
+ titlePane->setAlignment(QLabel::AlignCenter);
+ pl->addWidget(titlePane, 100);
+ }
+
+ QHBox *hbox = new QHBox(this);
+ hbox->setSpacing(0);
+ hbox->setFrameStyle(QFrame::Panel | QFrame::Sunken);
+ vbox->addWidget(hbox);
+
+ QHBox *tl = new QHBox(hbox);
+ tl->setMargin(7);
+ tl->setBackgroundColor(mBlendedColor);
+
+ QHBox *topLeft = new QHBox(tl);
+ topLeft->setMargin(15);
+ topLeft->setBackgroundColor(mBaseColor);
+
+ mTipText = new KTextBrowser(topLeft);
+
+ mTipText->setWrapPolicy( QTextEdit::AtWordOrDocumentBoundary );
+ mTipText->mimeSourceFactory()->addFilePath(
+ KGlobal::dirs()->findResourceDir("data", "kdewizard/pics")+"kdewizard/pics/");
+ mTipText->setFrameStyle(QFrame::NoFrame | QFrame::Plain);
+ mTipText->setHScrollBarMode(QScrollView::AlwaysOff);
+ mTipText->setLinkUnderline(false);
+
+ QStyleSheet *sheet = mTipText->styleSheet();
+ QStyleSheetItem *item = sheet->item("a");
+ item->setFontWeight(QFont::Bold);
+ mTipText->setStyleSheet(sheet);
+ QPalette pal = mTipText->palette();
+ pal.setColor( QPalette::Active, QColorGroup::Link, mBlendedColor );
+ pal.setColor( QPalette::Inactive, QColorGroup::Link, mBlendedColor );
+ mTipText->setPalette(pal);
+
+ QStringList icons = KGlobal::dirs()->resourceDirs("icon");
+ QStringList::Iterator it;
+ for (it = icons.begin(); it != icons.end(); ++it)
+ mTipText->mimeSourceFactory()->addFilePath(*it);
+
+ if (!isTipDialog)
+ {
+ QLabel *l = new QLabel(hbox);
+ l->setPixmap(img);
+ l->setBackgroundColor(mBlendedColor);
+ l->setAlignment(Qt::AlignRight | Qt::AlignBottom);
+
+ resize(550, 230);
+ QSize sh = size();
+
+ QRect rect = KGlobalSettings::splashScreenDesktopGeometry();
+
+ move(rect.x() + (rect.width() - sh.width())/2,
+ rect.y() + (rect.height() - sh.height())/2);
+ }
+
+ KSeparator* sep = new KSeparator( KSeparator::HLine, this);
+ vbox->addWidget(sep);
+
+ QHBoxLayout *hbox2 = new QHBoxLayout(vbox, 4);
+
+ mTipOnStart = new QCheckBox(i18n("&Show tips on startup"), this);
+ hbox2->addWidget(mTipOnStart, 1);
+
+ KPushButton *prev = new KPushButton( KStdGuiItem::back(
+ KStdGuiItem::UseRTL ), this );
+ prev->setText( i18n("&Previous") );
+ hbox2->addWidget(prev);
+
+ KPushButton *next = new KPushButton( KStdGuiItem::forward(
+ KStdGuiItem::UseRTL ), this );
+ next->setText( i18n("Opposite to Previous","&Next") );
+ hbox2->addWidget(next);
+
+ KPushButton *ok = new KPushButton(KStdGuiItem::close(), this);
+ ok->setDefault(true);
+ hbox2->addWidget(ok);
+
+ KConfigGroup config(kapp->config(), "TipOfDay");
+ mTipOnStart->setChecked(config.readBoolEntry("RunOnStart", true));
+
+ connect(next, SIGNAL(clicked()), this, SLOT(nextTip()));
+ connect(prev, SIGNAL(clicked()), this, SLOT(prevTip()));
+ connect(ok, SIGNAL(clicked()), this, SLOT(accept()));
+ connect(mTipOnStart, SIGNAL(toggled(bool)), this, SLOT(showOnStart(bool)));
+
+ ok->setFocus();
+
+ nextTip();
+}
+
+KTipDialog::~KTipDialog()
+{
+ if( mInstance==this )
+ mInstance = 0L;
+}
+
+void KTipDialog::showTip(const QString &tipFile, bool force)
+{
+ showTip(kapp->mainWidget(), tipFile, force);
+}
+
+void KTipDialog::showTip(QWidget *parent, const QString &tipFile, bool force)
+{
+ showMultiTip( parent, QStringList(tipFile), force );
+}
+
+void KTipDialog::showMultiTip(QWidget *parent, const QStringList &tipFiles, bool force)
+{
+ KConfigGroup configGroup(kapp->config(), "TipOfDay");
+
+ const bool runOnStart = configGroup.readBoolEntry("RunOnStart", true);
+
+ if (!force)
+ {
+ if (!runOnStart)
+ return;
+
+ bool hasLastShown = configGroup.hasKey("TipLastShown");
+ if (hasLastShown)
+ {
+ const int oneDay = 24*60*60;
+ QDateTime lastShown = configGroup.readDateTimeEntry("TipLastShown");
+ // Show tip roughly once a week
+ if (lastShown.secsTo(QDateTime::currentDateTime()) < (oneDay + (kapp->random() % (10*oneDay))))
+ return;
+ }
+ configGroup.writeEntry("TipLastShown", QDateTime::currentDateTime());
+ kapp->config()->sync();
+ if (!hasLastShown)
+ return; // Don't show tip on first start
+ }
+
+ if (!mInstance)
+ mInstance = new KTipDialog(new KTipDatabase(tipFiles), parent);
+ else
+ // The application might have changed the RunOnStart option in its own
+ // configuration dialog, so we should update the checkbox.
+ mInstance->mTipOnStart->setChecked(runOnStart);
+
+ mInstance->show();
+ mInstance->raise();
+ }
+
+ void KTipDialog::prevTip()
+ {
+ mDatabase->prevTip();
+ mTipText->setText(QString::fromLatin1(
+ "<qt text=\"%1\" bgcolor=\"%2\">%3</qt>")
+ .arg(mTextColor.name())
+ .arg(mBaseColor.name())
+ .arg(i18n(mDatabase->tip().utf8())));
+ mTipText->setContentsPos(0, 0);
+ }
+
+ void KTipDialog::nextTip()
+ {
+ mDatabase->nextTip();
+ mTipText->setText(QString::fromLatin1("<qt text=\"%1\" bgcolor=\"%2\">%3</qt>")
+ .arg(mTextColor.name())
+ .arg(mBaseColor.name())
+ .arg(i18n(mDatabase->tip().utf8())));
+ mTipText->setContentsPos(0, 0);
+ }
+
+ void KTipDialog::showOnStart(bool on)
+ {
+ setShowOnStart(on);
+ }
+
+ void KTipDialog::setShowOnStart(bool on)
+ {
+ KConfigGroup config(kapp->config(), "TipOfDay");
+ config.writeEntry("RunOnStart", on);
+ config.sync();
+ }
+
+ bool KTipDialog::eventFilter(QObject *o, QEvent *e)
+ {
+ if (o == mTipText && e->type()== QEvent::KeyPress &&
+ (((QKeyEvent *)e)->key() == Key_Return ||
+ ((QKeyEvent *)e)->key() == Key_Space ))
+ accept();
+
+ // If the user presses Return or Space, we close the dialog as if the
+ // default button was pressed even if the KTextBrowser has the keyboard
+ // focus. This could have the bad side-effect that the user cannot use the
+ // keyboard to open urls in the KTextBrowser, so we just let it handle
+ // the key event _additionally_. (Antonio)
+
+ return QWidget::eventFilter( o, e );
+}
+
+void KTipDialog::virtual_hook( int id, void* data )
+{
+ KDialog::virtual_hook( id, data );
+}
+
+#include "ktip.moc"
diff --git a/kdeui/ktip.h b/kdeui/ktip.h
new file mode 100644
index 000000000..f11978343
--- /dev/null
+++ b/kdeui/ktip.h
@@ -0,0 +1,192 @@
+/*****************************************************************
+
+Copyright (c) 2000-2003 Matthias Hoelzer-Kluepfel <mhk@kde.org>
+ Tobias Koenig <tokoe@kde.org>
+ Daniel Molkentin <molkentin@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __K_TIP_H__
+#define __K_TIP_H__
+
+#include <qstringlist.h>
+
+#include <kdialog.h>
+
+class QCheckBox;
+
+class KTextBrowser;
+
+/**
+ * A database for tips-of-the-day.
+ *
+ * This class provides convenient access to a database containing
+ * tips of the day. The database is stored in a XML file and parsed
+ * when a KTipDatabase object is created.
+ *
+ * Once the file is read in, you can access the tips to display
+ * them in the tip of the day dialog.
+ *
+ * The state of the tipdialog is saved to the applications's config file
+ * in the group "TipOfDay" with a bool entry "RunOnStart". Check this value
+ * if you want to allow the user to enable/disable the tipdialog in the
+ * application's configuration dialog.
+ *
+ * @author Matthias Hoelzer-Kluepfel <mhk@kde.org>
+ *
+ */
+class KDEUI_EXPORT KTipDatabase
+{
+public:
+ /**
+ * This constructor reads in the tips from a file with the given name. If
+ * no name is given, a file called 'application-name/tips' will be loaded.
+ *
+ * @param tipFile The absolute path to the tips file.
+ */
+ KTipDatabase(const QString &tipFile = QString::null);
+
+ /**
+ * This constructor takes a list of files that will be merged. This constructor
+ * essentially behaves like the one above. It returns when tipFiles is empty.
+ *
+ * @param tipFiles A list of absolute paths to the tips file
+ */
+ KTipDatabase(const QStringList &tipFiles);
+
+ /**
+ * Returns the current tip.
+ */
+ QString tip() const;
+
+ /**
+ * The next tip will become the current one.
+ */
+ void nextTip();
+
+ /**
+ * The previous tip will become the current one.
+ */
+ void prevTip();
+
+private:
+ void loadTips(const QString &tipFile);
+
+ void addTips(const QString &tipFile);
+
+ QStringList mTips;
+
+ int mCurrent;
+ class KTipDatabasePrivate;
+ KTipDatabasePrivate *d;
+};
+
+/**
+ * A Tip-of-the-Day dialog.
+ *
+ * This dialog class presents a tip-of-the-day.
+ *
+ * @author Matthias Hoelzer-Kluepfel <mhk@caldera.de>
+ */
+class KDEUI_EXPORT KTipDialog : public KDialog
+{
+ Q_OBJECT
+public:
+ /**
+ * Construct a tip dialog.
+ *
+ * @param db TipDatabase that should be used by the TipDialog.
+ * @param parent Parent widget of TipDialog.
+ * @param name The object name.
+ */
+ KTipDialog(KTipDatabase *db, QWidget *parent = 0, const char *name = 0);
+ ~KTipDialog();
+
+ /**
+ * Shows a tip.
+ *
+ * This static method is all that is needed to add a tip-of-the-day
+ * dialog to an application. It will pop up the dialog, unless the
+ * user has asked that the dialog does not pop up on startup.
+ *
+ * Note that you probably want an item in the help menu calling
+ * this method with force=true.
+ *
+ * @param parent Parent widget of TipDialog.
+ * @param tipFile The name of the tip file. It has be relative to the "data"
+ * resource of KStandardDirs
+ * @param force If true, the dialog is show, even when the users
+ * disabled it.
+ */
+ static void showTip(QWidget *parent, const QString &tipFile = QString::null, bool force=false);
+
+ /**
+ * Shows a tip
+ *
+ * This method behaves essentially as the one above, but expects a list of tips
+ *
+ * @param parent Parent widget of TipDialog.
+ * @param tipFiles A List of tip files. Each has be relative to the "data"
+ * resource of KStandardDirs
+ * @param force If true, the dialog is show, even when the users
+ * disabled it.
+ */
+ static void showMultiTip(QWidget *parent, const QStringList &tipFiles, bool force=false);
+
+ /**
+ * Shows a tip.
+ *
+ * This methods calls showTip() with the applications main window as parent.
+ *
+ */
+ static void showTip(const QString &tipFile = QString::null, bool force = false);
+
+ /**
+ * Toggles the start behavior.
+ *
+ * Normally, the user can disable the display of the tip in the dialog.
+ * This is just a way to change this setting from outside.
+ */
+ static void setShowOnStart(bool show);
+
+protected:
+ bool eventFilter(QObject *, QEvent *);
+ virtual void virtual_hook( int id, void* data );
+
+private slots:
+ void nextTip();
+ void prevTip();
+ void showOnStart(bool);
+
+private:
+ KTipDatabase *mDatabase;
+
+ QCheckBox *mTipOnStart;
+ KTextBrowser *mTipText;
+
+ class KTipDialogPrivate;
+ KTipDialogPrivate *d;
+
+ static KTipDialog *mInstance;
+
+ QColor mBaseColor, mBlendedColor, mTextColor;
+};
+
+#endif
diff --git a/kdeui/ktoolbar.cpp b/kdeui/ktoolbar.cpp
new file mode 100644
index 000000000..4d7acd5b1
--- /dev/null
+++ b/kdeui/ktoolbar.cpp
@@ -0,0 +1,2259 @@
+/* This file is part of the KDE libraries
+ Copyright
+ (C) 2000 Reginald Stadlbauer (reggie@kde.org)
+ (C) 1997, 1998 Stephan Kulow (coolo@kde.org)
+ (C) 1997, 1998 Mark Donohoe (donohoe@kde.org)
+ (C) 1997, 1998 Sven Radej (radej@kde.org)
+ (C) 1997, 1998 Matthias Ettrich (ettrich@kde.org)
+ (C) 1999 Chris Schlaeger (cs@kde.org)
+ (C) 1999 Kurt Granroth (granroth@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config.h>
+
+#ifdef KDE_USE_FINAL
+#undef Always
+#include <qdockwindow.h>
+#endif
+
+#include <string.h>
+
+#include <qpainter.h>
+#include <qtooltip.h>
+#include <qdrawutil.h>
+#include <qstring.h>
+#include <qrect.h>
+#include <qobjectlist.h>
+#include <qtimer.h>
+#include <qstyle.h>
+#include <qlayout.h>
+
+#include <ktoolbar.h>
+#include <kmainwindow.h>
+#include <klineedit.h>
+#include <kseparator.h>
+#include <klocale.h>
+#include <kapplication.h>
+#include <kaction.h>
+#include <kstdaction.h>
+#include <kglobal.h>
+#include <kconfig.h>
+#include <kiconloader.h>
+#include <kcombobox.h>
+#include <kpopupmenu.h>
+#include <kanimwidget.h>
+#include <kedittoolbar.h>
+#include <kipc.h>
+#include <kwin.h>
+#include <kdebug.h>
+#include <ktoolbarbutton.h>
+
+enum {
+ CONTEXT_TOP = 0,
+ CONTEXT_LEFT = 1,
+ CONTEXT_RIGHT = 2,
+ CONTEXT_BOTTOM = 3,
+ CONTEXT_FLOAT = 4,
+ CONTEXT_FLAT = 5,
+ CONTEXT_ICONS = 6,
+ CONTEXT_TEXT = 7,
+ CONTEXT_TEXTRIGHT = 8,
+ CONTEXT_TEXTUNDER = 9,
+ CONTEXT_ICONSIZES = 50 // starting point for the icon size list, put everything else before
+};
+
+class KToolBarPrivate
+{
+public:
+ KToolBarPrivate() {
+ m_iconSize = 0;
+ m_iconText = KToolBar::IconOnly;
+ m_highlight = true;
+ m_transparent = true;
+ m_honorStyle = false;
+
+ m_enableContext = true;
+
+ m_xmlguiClient = 0;
+
+ oldPos = Qt::DockUnmanaged;
+
+ modified = m_isHorizontal = positioned = false;
+
+ IconSizeDefault = 0;
+ IconTextDefault = "IconOnly";
+
+ NewLineDefault = false;
+ OffsetDefault = 0;
+ PositionDefault = "Top";
+ HiddenDefault = false;
+ idleButtons.setAutoDelete(true);
+ }
+
+ int m_iconSize;
+ KToolBar::IconText m_iconText;
+ bool m_highlight : 1;
+ bool m_transparent : 1;
+ bool m_honorStyle : 1;
+ bool m_isHorizontal : 1;
+ bool m_enableContext : 1;
+ bool modified : 1;
+ bool positioned : 1;
+
+ QWidget *m_parent;
+
+ QMainWindow::ToolBarDock oldPos;
+
+ KXMLGUIClient *m_xmlguiClient;
+
+ struct ToolBarInfo
+ {
+ ToolBarInfo() : index( -1 ), offset( -1 ), newline( false ), dock( Qt::DockTop ) {}
+ ToolBarInfo( Qt::Dock d, int i, bool n, int o ) : index( i ), offset( o ), newline( n ), dock( d ) {}
+ int index, offset;
+ bool newline;
+ Qt::Dock dock;
+ };
+
+ ToolBarInfo toolBarInfo;
+ QValueList<int> iconSizes;
+ QTimer repaintTimer;
+
+ // Default Values.
+ bool HiddenDefault;
+ int IconSizeDefault;
+ QString IconTextDefault;
+ bool NewLineDefault;
+ int OffsetDefault;
+ QString PositionDefault;
+
+ QPtrList<QWidget> idleButtons;
+};
+
+KToolBarSeparator::KToolBarSeparator(Orientation o , bool l, QToolBar *parent,
+ const char* name )
+ :QFrame( parent, name ), line( l )
+{
+ connect( parent, SIGNAL(orientationChanged(Orientation)),
+ this, SLOT(setOrientation(Orientation)) );
+ setOrientation( o );
+ setBackgroundMode( parent->backgroundMode() );
+ setBackgroundOrigin( ParentOrigin );
+}
+
+void KToolBarSeparator::setOrientation( Orientation o )
+{
+ orient = o;
+ setFrameStyle( NoFrame );
+}
+
+void KToolBarSeparator::drawContents( QPainter* p )
+{
+ if ( line ) {
+ QStyle::SFlags flags = QStyle::Style_Default;
+
+ if ( orientation() == Horizontal )
+ flags = flags | QStyle::Style_Horizontal;
+
+ style().drawPrimitive(QStyle::PE_DockWindowSeparator, p,
+ contentsRect(), colorGroup(), flags);
+ } else {
+ QFrame::drawContents(p);
+ }
+}
+
+void KToolBarSeparator::styleChange( QStyle& )
+{
+ setOrientation( orient );
+}
+
+QSize KToolBarSeparator::sizeHint() const
+{
+ int dim = style().pixelMetric( QStyle::PM_DockWindowSeparatorExtent, this );
+ return orientation() == Vertical ? QSize( 0, dim ) : QSize( dim, 0 );
+}
+
+QSizePolicy KToolBarSeparator::sizePolicy() const
+{
+ return QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
+}
+
+KToolBar::KToolBar( QWidget *parent, const char *name, bool honorStyle, bool readConfig )
+ : QToolBar( QString::fromLatin1( name ),
+ dynamic_cast<QMainWindow*>(parent),
+ parent, false,
+ name ? name : "mainToolBar")
+{
+ init( readConfig, honorStyle );
+}
+
+KToolBar::KToolBar( QMainWindow *parentWindow, QMainWindow::ToolBarDock dock, bool newLine, const char *name, bool honorStyle, bool readConfig )
+ : QToolBar( QString::fromLatin1( name ),
+ parentWindow, dock, newLine,
+ name ? name : "mainToolBar")
+{
+ init( readConfig, honorStyle );
+}
+
+KToolBar::KToolBar( QMainWindow *parentWindow, QWidget *dock, bool newLine, const char *name, bool honorStyle, bool readConfig )
+ : QToolBar( QString::fromLatin1( name ),
+ parentWindow, dock, newLine,
+ name ? name : "mainToolBar")
+{
+ init( readConfig, honorStyle );
+}
+
+KToolBar::~KToolBar()
+{
+ emit toolbarDestroyed();
+ delete d;
+}
+
+void KToolBar::init( bool readConfig, bool honorStyle )
+{
+ d = new KToolBarPrivate;
+ setFullSize( true );
+ d->m_honorStyle = honorStyle;
+ context = 0;
+ layoutTimer = new QTimer( this );
+ connect( layoutTimer, SIGNAL( timeout() ),
+ this, SLOT( rebuildLayout() ) );
+ connect( &(d->repaintTimer), SIGNAL( timeout() ),
+ this, SLOT( slotRepaint() ) );
+
+ if ( kapp ) { // may be null when started inside designer
+ connect(kapp, SIGNAL(toolbarAppearanceChanged(int)), this, SLOT(slotAppearanceChanged()));
+ // request notification of changes in icon style
+ kapp->addKipcEventMask(KIPC::IconChanged);
+ connect(kapp, SIGNAL(iconChanged(int)), this, SLOT(slotIconChanged(int)));
+ }
+
+ // finally, read in our configurable settings
+ if ( readConfig )
+ slotReadConfig();
+
+ if ( mainWindow() )
+ connect( mainWindow(), SIGNAL( toolBarPositionChanged( QToolBar * ) ),
+ this, SLOT( toolBarPosChanged( QToolBar * ) ) );
+
+ // Hack to make sure we recalculate our size when we dock.
+ connect( this, SIGNAL(placeChanged(QDockWindow::Place)), SLOT(rebuildLayout()) );
+}
+
+int KToolBar::insertButton(const QString& icon, int id, bool enabled,
+ const QString& text, int index, KInstance *_instance )
+{
+ KToolBarButton *button = new KToolBarButton( icon, id, this, 0, text, _instance );
+
+ insertWidgetInternal( button, index, id );
+ button->setEnabled( enabled );
+ doConnections( button );
+ return index;
+}
+
+
+int KToolBar::insertButton(const QString& icon, int id, const char *signal,
+ const QObject *receiver, const char *slot,
+ bool enabled, const QString& text, int index, KInstance *_instance )
+{
+ KToolBarButton *button = new KToolBarButton( icon, id, this, 0, text, _instance);
+ insertWidgetInternal( button, index, id );
+ button->setEnabled( enabled );
+ connect( button, signal, receiver, slot );
+ doConnections( button );
+ return index;
+}
+
+
+int KToolBar::insertButton(const QPixmap& pixmap, int id, bool enabled,
+ const QString& text, int index )
+{
+ KToolBarButton *button = new KToolBarButton( pixmap, id, this, 0, text);
+ insertWidgetInternal( button, index, id );
+ button->setEnabled( enabled );
+ doConnections( button );
+ return index;
+}
+
+
+int KToolBar::insertButton(const QPixmap& pixmap, int id, const char *signal,
+ const QObject *receiver, const char *slot,
+ bool enabled, const QString& text,
+ int index )
+{
+ KToolBarButton *button = new KToolBarButton( pixmap, id, this, 0, text);
+ insertWidgetInternal( button, index, id );
+ button->setEnabled( enabled );
+ connect( button, signal, receiver, slot );
+ doConnections( button );
+ return index;
+}
+
+
+int KToolBar::insertButton(const QString& icon, int id, QPopupMenu *popup,
+ bool enabled, const QString &text, int index )
+{
+ KToolBarButton *button = new KToolBarButton( icon, id, this, 0, text );
+ insertWidgetInternal( button, index, id );
+ button->setEnabled( enabled );
+ button->setPopup( popup );
+ doConnections( button );
+ return index;
+}
+
+
+int KToolBar::insertButton(const QPixmap& pixmap, int id, QPopupMenu *popup,
+ bool enabled, const QString &text, int index )
+{
+ KToolBarButton *button = new KToolBarButton( pixmap, id, this, 0, text );
+ insertWidgetInternal( button, index, id );
+ button->setEnabled( enabled );
+ button->setPopup( popup );
+ doConnections( button );
+ return index;
+}
+
+
+int KToolBar::insertLined (const QString& text, int id,
+ const char *signal,
+ const QObject *receiver, const char *slot,
+ bool enabled ,
+ const QString& toolTipText,
+ int size, int index )
+{
+ KLineEdit *lined = new KLineEdit ( this, 0 );
+ if ( !toolTipText.isEmpty() )
+ QToolTip::add( lined, toolTipText );
+ if ( size > 0 )
+ lined->setMinimumWidth( size );
+ insertWidgetInternal( lined, index, id );
+ connect( lined, signal, receiver, slot );
+ lined->setText(text);
+ lined->setEnabled( enabled );
+ return index;
+}
+
+int KToolBar::insertCombo (const QStringList &list, int id, bool writable,
+ const char *signal, const QObject *receiver,
+ const char *slot, bool enabled,
+ const QString& tooltiptext,
+ int size, int index,
+ QComboBox::Policy policy )
+{
+ KComboBox *combo = new KComboBox ( writable, this );
+
+ insertWidgetInternal( combo, index, id );
+ combo->insertStringList (list);
+ combo->setInsertionPolicy(policy);
+ combo->setEnabled( enabled );
+ if ( size > 0 )
+ combo->setMinimumWidth( size );
+ if (!tooltiptext.isNull())
+ QToolTip::add( combo, tooltiptext );
+
+ if ( signal && receiver && slot )
+ connect ( combo, signal, receiver, slot );
+ return index;
+}
+
+
+int KToolBar::insertCombo (const QString& text, int id, bool writable,
+ const char *signal, QObject *receiver,
+ const char *slot, bool enabled,
+ const QString& tooltiptext,
+ int size, int index,
+ QComboBox::Policy policy )
+{
+ KComboBox *combo = new KComboBox ( writable, this );
+ insertWidgetInternal( combo, index, id );
+ combo->insertItem (text);
+ combo->setInsertionPolicy(policy);
+ combo->setEnabled( enabled );
+ if ( size > 0 )
+ combo->setMinimumWidth( size );
+ if (!tooltiptext.isNull())
+ QToolTip::add( combo, tooltiptext );
+ connect (combo, signal, receiver, slot);
+ return index;
+}
+
+int KToolBar::insertSeparator(int index, int id)
+{
+ QWidget *w = new KToolBarSeparator( orientation(), false, this, "tool bar separator" );
+ insertWidgetInternal( w, index, id );
+ return index;
+}
+
+int KToolBar::insertLineSeparator(int index, int id)
+{
+ QWidget *w = new KToolBarSeparator( orientation(), true, this, "tool bar separator" );
+ insertWidgetInternal( w, index, id );
+ return index;
+}
+
+
+int KToolBar::insertWidget(int id, int /*width*/, QWidget *widget, int index)
+{
+ removeWidgetInternal( widget ); // in case we already have it ?
+ insertWidgetInternal( widget, index, id );
+ return index;
+}
+
+int KToolBar::insertAnimatedWidget(int id, QObject *receiver, const char *slot,
+ const QString& icons, int index )
+{
+ KAnimWidget *anim = new KAnimWidget( icons, d->m_iconSize, this );
+ insertWidgetInternal( anim, index, id );
+
+ if ( receiver )
+ connect( anim, SIGNAL(clicked()), receiver, slot);
+
+ return index;
+}
+
+KAnimWidget *KToolBar::animatedWidget( int id )
+{
+ Id2WidgetMap::Iterator it = id2widget.find( id );
+ if ( it == id2widget.end() )
+ return 0;
+ KAnimWidget *aw = dynamic_cast<KAnimWidget *>(*it);
+ if ( aw )
+ return aw;
+ QObjectList *l = queryList( "KAnimWidget" );
+ if ( !l || !l->first() ) {
+ delete l;
+ return 0;
+ }
+
+ for ( QObject *o = l->first(); o; o = l->next() ) {
+ KAnimWidget *aw = dynamic_cast<KAnimWidget *>(o);
+ if ( aw )
+ {
+ delete l;
+ return aw;
+ }
+ }
+
+ delete l;
+ return 0;
+}
+
+
+void KToolBar::addConnection (int id, const char *signal,
+ const QObject *receiver, const char *slot)
+{
+ QWidget* w = getWidget( id );
+ if ( w )
+ connect( w, signal, receiver, slot );
+}
+
+void KToolBar::setItemEnabled( int id, bool enabled )
+{
+ QWidget* w = getWidget( id );
+ if ( w )
+ w->setEnabled( enabled );
+}
+
+
+void KToolBar::setButtonPixmap( int id, const QPixmap& _pixmap )
+{
+ KToolBarButton * button = getButton( id );
+ if ( button )
+ button->setPixmap( _pixmap );
+}
+
+
+void KToolBar::setButtonIcon( int id, const QString& _icon )
+{
+ KToolBarButton * button = getButton( id );
+ if ( button )
+ button->setIcon( _icon );
+}
+
+void KToolBar::setButtonIconSet( int id, const QIconSet& iconset )
+{
+ KToolBarButton * button = getButton( id );
+ if ( button )
+ button->setIconSet( iconset );
+}
+
+
+void KToolBar::setDelayedPopup (int id , QPopupMenu *_popup, bool toggle )
+{
+ KToolBarButton * button = getButton( id );
+ if ( button )
+ button->setDelayedPopup( _popup, toggle );
+}
+
+
+void KToolBar::setAutoRepeat (int id, bool flag)
+{
+ KToolBarButton * button = getButton( id );
+ if ( button )
+ button->setAutoRepeat( flag );
+}
+
+
+void KToolBar::setToggle (int id, bool flag )
+{
+ KToolBarButton * button = getButton( id );
+ if ( button )
+ button->setToggle( flag );
+}
+
+
+void KToolBar::toggleButton (int id)
+{
+ KToolBarButton * button = getButton( id );
+ if ( button )
+ button->toggle();
+}
+
+
+void KToolBar::setButton (int id, bool flag)
+{
+ KToolBarButton * button = getButton( id );
+ if ( button )
+ button->on( flag );
+}
+
+
+bool KToolBar::isButtonOn (int id) const
+{
+ KToolBarButton * button = const_cast<KToolBar*>( this )->getButton( id );
+ return button ? button->isOn() : false;
+}
+
+
+void KToolBar::setLinedText (int id, const QString& text)
+{
+ KLineEdit * lineEdit = getLined( id );
+ if ( lineEdit )
+ lineEdit->setText( text );
+}
+
+
+QString KToolBar::getLinedText (int id) const
+{
+ KLineEdit * lineEdit = const_cast<KToolBar*>( this )->getLined( id );
+ return lineEdit ? lineEdit->text() : QString::null;
+}
+
+
+void KToolBar::insertComboItem (int id, const QString& text, int index)
+{
+ KComboBox * comboBox = getCombo( id );
+ if (comboBox)
+ comboBox->insertItem( text, index );
+}
+
+void KToolBar::insertComboList (int id, const QStringList &list, int index)
+{
+ KComboBox * comboBox = getCombo( id );
+ if (comboBox)
+ comboBox->insertStringList( list, index );
+}
+
+
+void KToolBar::removeComboItem (int id, int index)
+{
+ KComboBox * comboBox = getCombo( id );
+ if (comboBox)
+ comboBox->removeItem( index );
+}
+
+
+void KToolBar::setCurrentComboItem (int id, int index)
+{
+ KComboBox * comboBox = getCombo( id );
+ if (comboBox)
+ comboBox->setCurrentItem( index );
+}
+
+
+void KToolBar::changeComboItem (int id, const QString& text, int index)
+{
+ KComboBox * comboBox = getCombo( id );
+ if (comboBox)
+ comboBox->changeItem( text, index );
+}
+
+
+void KToolBar::clearCombo (int id)
+{
+ KComboBox * comboBox = getCombo( id );
+ if (comboBox)
+ comboBox->clear();
+}
+
+
+QString KToolBar::getComboItem (int id, int index) const
+{
+ KComboBox * comboBox = const_cast<KToolBar*>( this )->getCombo( id );
+ return comboBox ? comboBox->text( index ) : QString::null;
+}
+
+
+KComboBox * KToolBar::getCombo(int id)
+{
+ Id2WidgetMap::Iterator it = id2widget.find( id );
+ if ( it == id2widget.end() )
+ return 0;
+ return dynamic_cast<KComboBox *>( *it );
+}
+
+
+KLineEdit * KToolBar::getLined (int id)
+{
+ Id2WidgetMap::Iterator it = id2widget.find( id );
+ if ( it == id2widget.end() )
+ return 0;
+ return dynamic_cast<KLineEdit *>( *it );
+}
+
+
+KToolBarButton * KToolBar::getButton (int id)
+{
+ Id2WidgetMap::Iterator it = id2widget.find( id );
+ if ( it == id2widget.end() )
+ return 0;
+ return dynamic_cast<KToolBarButton *>( *it );
+}
+
+
+void KToolBar::alignItemRight (int id, bool right )
+{
+ Id2WidgetMap::Iterator it = id2widget.find( id );
+ if ( it == id2widget.end() )
+ return;
+ if ( rightAligned && !right && (*it) == rightAligned )
+ rightAligned = 0;
+ if ( (*it) && right )
+ rightAligned = (*it);
+}
+
+
+QWidget *KToolBar::getWidget (int id)
+{
+ Id2WidgetMap::Iterator it = id2widget.find( id );
+ return ( it == id2widget.end() ) ? 0 : (*it);
+}
+
+
+void KToolBar::setItemAutoSized (int id, bool yes )
+{
+ QWidget *w = getWidget(id);
+ if ( w && yes )
+ setStretchableWidget( w );
+}
+
+
+void KToolBar::clear ()
+{
+ /* Delete any idle buttons, so QToolBar doesn't delete them itself, making a mess */
+ for(QWidget *w=d->idleButtons.first(); w; w=d->idleButtons.next())
+ w->blockSignals(false);
+ d->idleButtons.clear();
+
+ QToolBar::clear();
+ widget2id.clear();
+ id2widget.clear();
+}
+
+
+void KToolBar::removeItem(int id)
+{
+ Id2WidgetMap::Iterator it = id2widget.find( id );
+ if ( it == id2widget.end() )
+ {
+ kdDebug(220) << name() << " KToolBar::removeItem item " << id << " not found" << endl;
+ return;
+ }
+ QWidget * w = (*it);
+ id2widget.remove( id );
+ widget2id.remove( w );
+ widgets.removeRef( w );
+ delete w;
+}
+
+
+void KToolBar::removeItemDelayed(int id)
+{
+ Id2WidgetMap::Iterator it = id2widget.find( id );
+ if ( it == id2widget.end() )
+ {
+ kdDebug(220) << name() << " KToolBar::removeItem item " << id << " not found" << endl;
+ return;
+ }
+ QWidget * w = (*it);
+ id2widget.remove( id );
+ widget2id.remove( w );
+ widgets.removeRef( w );
+
+ w->blockSignals(true);
+ d->idleButtons.append(w);
+ layoutTimer->start( 50, true );
+}
+
+
+void KToolBar::hideItem (int id)
+{
+ QWidget *w = getWidget(id);
+ if ( w )
+ w->hide();
+}
+
+
+void KToolBar::showItem (int id)
+{
+ QWidget *w = getWidget(id);
+ if ( w )
+ w->show();
+}
+
+
+int KToolBar::itemIndex (int id)
+{
+ QWidget *w = getWidget(id);
+ return w ? widgets.findRef(w) : -1;
+}
+
+int KToolBar::idAt (int index)
+{
+ QWidget *w = widgets.at(index);
+ return widget2id[w];
+}
+
+void KToolBar::setFullSize(bool flag )
+{
+ setHorizontalStretchable( flag );
+ setVerticalStretchable( flag );
+}
+
+
+bool KToolBar::fullSize() const
+{
+ return isHorizontalStretchable() || isVerticalStretchable();
+}
+
+
+void KToolBar::enableMoving(bool flag )
+{
+ setMovingEnabled(flag);
+}
+
+
+void KToolBar::setBarPos (BarPosition bpos)
+{
+ if ( !mainWindow() )
+ return;
+ mainWindow()->moveDockWindow( this, (Dock)bpos );
+ //kdDebug(220) << name() << " setBarPos dockWindowIndex=" << dockWindowIndex() << endl;
+}
+
+
+KToolBar::BarPosition KToolBar::barPos() const
+{
+ if ( !this->mainWindow() )
+ return place() == QDockWindow::InDock ? KToolBar::Top : KToolBar::Floating;
+ Dock dock;
+ int dm1, dm2;
+ bool dm3;
+ this->mainWindow()->getLocation( (QToolBar*)this, dock, dm1, dm3, dm2 );
+ if ( dock == DockUnmanaged ) {
+ return (KToolBar::BarPosition)DockTop;
+ }
+ return (BarPosition)dock;
+}
+
+
+bool KToolBar::enable(BarStatus stat)
+{
+ bool mystat = isVisible();
+
+ if ( (stat == Toggle && mystat) || stat == Hide )
+ hide();
+ else
+ show();
+
+ return isVisible() == mystat;
+}
+
+
+void KToolBar::setMaxHeight ( int h )
+{
+ setMaximumHeight( h );
+}
+
+int KToolBar::maxHeight()
+{
+ return maximumHeight();
+}
+
+
+void KToolBar::setMaxWidth (int dw)
+{
+ setMaximumWidth( dw );
+}
+
+
+int KToolBar::maxWidth()
+{
+ return maximumWidth();
+}
+
+
+void KToolBar::setTitle (const QString& _title)
+{
+ setLabel( _title );
+}
+
+
+void KToolBar::enableFloating (bool )
+{
+}
+
+
+void KToolBar::setIconText(IconText it)
+{
+ setIconText( it, true );
+}
+
+
+void KToolBar::setIconText(IconText icontext, bool update)
+{
+ bool doUpdate=false;
+
+ if (icontext != d->m_iconText) {
+ d->m_iconText = icontext;
+ doUpdate=true;
+ //kdDebug(220) << name() << " icontext has changed, doUpdate=true" << endl;
+ }
+ else {
+ //kdDebug(220) << name() << " icontext hasn't changed, doUpdate=false" << endl;
+ }
+
+ if (!update)
+ return;
+
+ if (doUpdate)
+ doModeChange(); // tell buttons what happened
+
+ // ugly hack to force a QMainWindow::triggerLayout( true )
+ QMainWindow *mw = mainWindow();
+ if ( mw ) {
+ mw->setUpdatesEnabled( false );
+ mw->setToolBarsMovable( !mw->toolBarsMovable() );
+ mw->setToolBarsMovable( !mw->toolBarsMovable() );
+ mw->setUpdatesEnabled( true );
+ }
+}
+
+
+KToolBar::IconText KToolBar::iconText() const
+{
+ return d->m_iconText;
+}
+
+
+void KToolBar::setIconSize(int size)
+{
+ setIconSize( size, true );
+}
+
+void KToolBar::setIconSize(int size, bool update)
+{
+ bool doUpdate=false;
+
+ if ( size != d->m_iconSize ) {
+ d->m_iconSize = size;
+ doUpdate=true;
+ }
+
+ if (!update)
+ return;
+
+ if (doUpdate)
+ doModeChange(); // tell buttons what happened
+
+ // ugly hack to force a QMainWindow::triggerLayout( true )
+ if ( mainWindow() ) {
+ QMainWindow *mw = mainWindow();
+ mw->setUpdatesEnabled( false );
+ mw->setToolBarsMovable( !mw->toolBarsMovable() );
+ mw->setToolBarsMovable( !mw->toolBarsMovable() );
+ mw->setUpdatesEnabled( true );
+ }
+}
+
+
+int KToolBar::iconSize() const
+{
+ if ( !d->m_iconSize ) // default value?
+ return iconSizeDefault();
+
+ return d->m_iconSize;
+}
+
+int KToolBar::iconSizeDefault() const
+{
+ if (!::qstrcmp(QObject::name(), "mainToolBar"))
+ return KGlobal::iconLoader()->currentSize(KIcon::MainToolbar);
+
+ return KGlobal::iconLoader()->currentSize(KIcon::Toolbar);
+}
+
+void KToolBar::setEnableContextMenu(bool enable )
+{
+ d->m_enableContext = enable;
+}
+
+
+bool KToolBar::contextMenuEnabled() const
+{
+ return d->m_enableContext;
+}
+
+
+void KToolBar::setItemNoStyle(int id, bool no_style )
+{
+ KToolBarButton * button = getButton( id );
+ if (button)
+ button->setNoStyle( no_style );
+}
+
+
+void KToolBar::setFlat (bool flag)
+{
+ if ( !mainWindow() )
+ return;
+ if ( flag )
+ mainWindow()->moveDockWindow( this, DockMinimized );
+ else
+ mainWindow()->moveDockWindow( this, DockTop );
+ // And remember to save the new look later
+ KMainWindow *kmw = dynamic_cast<KMainWindow *>(mainWindow());
+ if ( kmw )
+ kmw->setSettingsDirty();
+}
+
+
+int KToolBar::count() const
+{
+ return id2widget.count();
+}
+
+
+void KToolBar::saveState()
+{
+ // first, try to save to the xml file
+ if ( d->m_xmlguiClient && !d->m_xmlguiClient->xmlFile().isEmpty() ) {
+ //kdDebug(220) << name() << " saveState: saving to " << d->m_xmlguiClient->xmlFile() << endl;
+ QString barname(!::qstrcmp(name(), "unnamed") ? "mainToolBar" : name());
+ // try to find our toolbar
+ d->modified = false;
+ // go down one level to get to the right tags
+ QDomElement current;
+ for( QDomNode n = d->m_xmlguiClient->domDocument().documentElement().firstChild();
+ !n.isNull(); n = n.nextSibling()) {
+ current = n.toElement();
+
+ if ( current.tagName().lower() != "toolbar" )
+ continue;
+
+ QString curname(current.attribute( "name" ));
+
+ if ( curname == barname ) {
+ saveState( current );
+ break;
+ }
+ }
+ // if we didn't make changes, then just return
+ if ( !d->modified )
+ return;
+
+ // now we load in the (non-merged) local file
+ QString local_xml(KXMLGUIFactory::readConfigFile(d->m_xmlguiClient->xmlFile(), true, d->m_xmlguiClient->instance()));
+ QDomDocument local;
+ local.setContent(local_xml);
+
+ // make sure we don't append if this toolbar already exists locally
+ bool just_append = true;
+
+ for( QDomNode n = local.documentElement().firstChild();
+ !n.isNull(); n = n.nextSibling()) {
+ QDomElement elem = n.toElement();
+
+ if ( elem.tagName().lower() != "toolbar" )
+ continue;
+
+ QString curname(elem.attribute( "name" ));
+
+ if ( curname == barname ) {
+ just_append = false;
+ local.documentElement().replaceChild( current, elem );
+ break;
+ }
+ }
+
+ if (just_append)
+ local.documentElement().appendChild( current );
+
+ KXMLGUIFactory::saveConfigFile(local, d->m_xmlguiClient->localXMLFile(), d->m_xmlguiClient->instance() );
+
+ return;
+ }
+
+ // if that didn't work, we save to the config file
+ KConfig *config = KGlobal::config();
+ saveSettings(config, QString::null);
+ config->sync();
+}
+
+QString KToolBar::settingsGroup() const
+{
+ QString configGroup;
+ if (!::qstrcmp(name(), "unnamed") || !::qstrcmp(name(), "mainToolBar"))
+ configGroup = "Toolbar style";
+ else
+ configGroup = QString(name()) + " Toolbar style";
+ if ( this->mainWindow() )
+ {
+ configGroup.prepend(" ");
+ configGroup.prepend( this->mainWindow()->name() );
+ }
+ return configGroup;
+}
+
+void KToolBar::saveSettings(KConfig *config, const QString &_configGroup)
+{
+ QString configGroup = _configGroup;
+ if (configGroup.isEmpty())
+ configGroup = settingsGroup();
+ //kdDebug(220) << name() << " saveSettings() group=" << _configGroup << " -> " << configGroup << endl;
+
+ QString position, icontext;
+ int index;
+ getAttributes( position, icontext, index );
+
+ //kdDebug(220) << name() << " position=" << position << " index=" << index << " offset=" << offset() << " newLine=" << newLine() << endl;
+
+ KConfigGroupSaver saver(config, configGroup);
+
+ if(!config->hasDefault("Position") && position == d->PositionDefault )
+ config->revertToDefault("Position");
+ else
+ config->writeEntry("Position", position);
+
+ //kdDebug(220) << name() << " icontext=" << icontext << " hasDefault:" << config->hasDefault( "IconText" ) << " d->IconTextDefault=" << d->IconTextDefault << endl;
+
+ if(d->m_honorStyle && icontext == d->IconTextDefault && !config->hasDefault("IconText") )
+ {
+ //kdDebug(220) << name() << " reverting icontext to default" << endl;
+ config->revertToDefault("IconText");
+ }
+ else
+ {
+ //kdDebug(220) << name() << " writing icontext " << icontext << endl;
+ config->writeEntry("IconText", icontext);
+ }
+
+ if(!config->hasDefault("IconSize") && iconSize() == iconSizeDefault() )
+ config->revertToDefault("IconSize");
+ else
+ config->writeEntry("IconSize", iconSize());
+
+ if(!config->hasDefault("Hidden") && isHidden() == d->HiddenDefault )
+ config->revertToDefault("Hidden");
+ else
+ config->writeEntry("Hidden", isHidden());
+
+ // Note that index, unlike the other settings, depends on the other toolbars
+ // So on the first run with a clean local config file, even the usual
+ // hasDefault/==IndexDefault test would save the toolbar indexes
+ // (IndexDefault was 0, whereas index is the real index in the GUI)
+ //
+ // Saving the whole set of indexes is necessary though. When moving only
+ // one toolbar, if we only saved the changed indexes, the toolbars wouldn't
+ // reappear at the same position the next time.
+ // The whole set of indexes has to be saved.
+ //kdDebug(220) << name() << " writing index " << index << endl;
+ KMainWindow *kmw = dynamic_cast<KMainWindow *>(mainWindow());
+ // don't save if there's only one toolbar
+
+ // Don't use kmw->toolBarIterator() because you might
+ // mess up someone else's iterator. Make the list on your own
+ QPtrList<KToolBar> toolbarList;
+ QPtrList<QToolBar> lst;
+ for ( int i = (int)QMainWindow::DockUnmanaged; i <= (int)DockMinimized; ++i ) {
+ lst = kmw->toolBars( (ToolBarDock)i );
+ for ( QToolBar *tb = lst.first(); tb; tb = lst.next() ) {
+ if ( !tb->inherits( "KToolBar" ) )
+ continue;
+ toolbarList.append( (KToolBar*)tb );
+ }
+ }
+ QPtrListIterator<KToolBar> toolbarIterator( toolbarList );
+ if ( !kmw || toolbarIterator.count() > 1 )
+ config->writeEntry("Index", index);
+ else
+ config->revertToDefault("Index");
+
+ if(!config->hasDefault("Offset") && offset() == d->OffsetDefault )
+ config->revertToDefault("Offset");
+ else
+ config->writeEntry("Offset", offset());
+
+ if(!config->hasDefault("NewLine") && newLine() == d->NewLineDefault )
+ config->revertToDefault("NewLine");
+ else
+ config->writeEntry("NewLine", newLine());
+}
+
+
+void KToolBar::setXMLGUIClient( KXMLGUIClient *client )
+{
+ d->m_xmlguiClient = client;
+}
+
+void KToolBar::setText( const QString & txt )
+{
+ setLabel( txt + " (" + kapp->caption() + ") " );
+}
+
+
+QString KToolBar::text() const
+{
+ return label();
+}
+
+
+void KToolBar::doConnections( KToolBarButton *button )
+{
+ connect(button, SIGNAL(clicked(int)), this, SIGNAL( clicked( int ) ) );
+ connect(button, SIGNAL(doubleClicked(int)), this, SIGNAL( doubleClicked( int ) ) );
+ connect(button, SIGNAL(released(int)), this, SIGNAL( released( int ) ) );
+ connect(button, SIGNAL(pressed(int)), this, SIGNAL( pressed( int ) ) );
+ connect(button, SIGNAL(toggled(int)), this, SIGNAL( toggled( int ) ) );
+ connect(button, SIGNAL(highlighted(int, bool)), this, SIGNAL( highlighted( int, bool ) ) );
+}
+
+void KToolBar::mousePressEvent ( QMouseEvent *m )
+{
+ if ( !mainWindow() )
+ return;
+ QMainWindow *mw = mainWindow();
+ if ( mw->toolBarsMovable() && d->m_enableContext ) {
+ if ( m->button() == RightButton ) {
+ QGuardedPtr<KToolBar> guard( this );
+ int i = contextMenu()->exec( m->globalPos(), 0 );
+ // "Configure Toolbars" recreates toolbars, so we might not exist anymore.
+ if ( guard )
+ slotContextAboutToHide();
+ switch ( i ) {
+ case -1:
+ return; // popup canceled
+ case CONTEXT_LEFT:
+ mw->moveDockWindow( this, DockLeft );
+ break;
+ case CONTEXT_RIGHT:
+ mw->moveDockWindow( this, DockRight );
+ break;
+ case CONTEXT_TOP:
+ mw->moveDockWindow( this, DockTop );
+ break;
+ case CONTEXT_BOTTOM:
+ mw->moveDockWindow( this, DockBottom );
+ break;
+ case CONTEXT_FLOAT:
+ mw->moveDockWindow( this, DockTornOff );
+ break;
+ case CONTEXT_FLAT:
+ mw->moveDockWindow( this, DockMinimized );
+ break;
+ case CONTEXT_ICONS:
+ setIconText( IconOnly );
+ break;
+ case CONTEXT_TEXTRIGHT:
+ setIconText( IconTextRight );
+ break;
+ case CONTEXT_TEXT:
+ setIconText( TextOnly );
+ break;
+ case CONTEXT_TEXTUNDER:
+ setIconText( IconTextBottom );
+ break;
+ default:
+ if ( i >= CONTEXT_ICONSIZES )
+ setIconSize( i - CONTEXT_ICONSIZES );
+ else
+ return; // assume this was an action handled elsewhere, no need for setSettingsDirty()
+ }
+ KMainWindow *kmw = dynamic_cast<KMainWindow *>(mw);
+ if ( kmw )
+ kmw->setSettingsDirty();
+ }
+ }
+}
+
+void KToolBar::doModeChange()
+{
+ for(QWidget *w=d->idleButtons.first(); w; w=d->idleButtons.next())
+ w->blockSignals(false);
+ d->idleButtons.clear();
+
+ emit modechange();
+}
+
+void KToolBar::rebuildLayout()
+{
+ for(QWidget *w=d->idleButtons.first(); w; w=d->idleButtons.next())
+ w->blockSignals(false);
+ d->idleButtons.clear();
+
+ layoutTimer->stop();
+ QApplication::sendPostedEvents( this, QEvent::ChildInserted );
+ QBoxLayout *l = boxLayout();
+
+ // clear the old layout
+ QLayoutIterator it = l->iterator();
+ while ( it.current() )
+ it.deleteCurrent();
+
+ for ( QWidget *w = widgets.first(); w; w = widgets.next() ) {
+ if ( w == rightAligned )
+ continue;
+ KToolBarSeparator *ktbs = dynamic_cast<KToolBarSeparator *>(w);
+ if ( ktbs && !ktbs->showLine() ) {
+ l->addSpacing( orientation() == Vertical ? w->sizeHint().height() : w->sizeHint().width() );
+ w->hide();
+ continue;
+ }
+ if ( dynamic_cast<QPopupMenu *>(w) ) // w is a QPopupMenu?
+ continue;
+ l->addWidget( w );
+ w->show();
+ if ((orientation() == Horizontal) && dynamic_cast<QLineEdit *>(w)) // w is QLineEdit ?
+ l->addSpacing(2); // A little bit extra spacing behind it.
+ }
+ if ( rightAligned ) {
+ l->addStretch();
+ l->addWidget( rightAligned );
+ rightAligned->show();
+ }
+
+ if ( fullSize() ) {
+ if ( !rightAligned )
+ l->addStretch();
+ if ( stretchableWidget )
+ l->setStretchFactor( stretchableWidget, 10 );
+ }
+ l->invalidate();
+ QApplication::postEvent( this, new QEvent( QEvent::LayoutHint ) );
+}
+
+void KToolBar::childEvent( QChildEvent *e )
+{
+ if ( e->child()->isWidgetType() ) {
+ QWidget * w = dynamic_cast<QWidget *>(e->child());
+ if (!w || !(::qstrcmp( "qt_dockwidget_internal", w->name())))
+ {
+ QToolBar::childEvent( e );
+ return;
+ }
+ if ( e->type() == QEvent::ChildInserted ) {
+ if ( !dynamic_cast<QPopupMenu *>(w)) { // e->child() is not a QPopupMenu
+ // prevent items that have been explicitly inserted by insert*() from
+ // being inserted again
+ if ( !widget2id.contains( w ) )
+ {
+ int dummy = -1;
+ insertWidgetInternal( w, dummy, -1 );
+ }
+ }
+ } else {
+ removeWidgetInternal( w );
+ }
+ if ( isVisibleTo( 0 ) )
+ {
+ layoutTimer->start( 50, true );
+ QBoxLayout *l = boxLayout();
+
+ // clear the old layout so that we don't get unnecassery layout
+ // changes till we have rebuild the thing
+ QLayoutIterator it = l->iterator();
+ while ( it.current() )
+ it.deleteCurrent();
+ }
+ }
+ QToolBar::childEvent( e );
+}
+
+void KToolBar::insertWidgetInternal( QWidget *w, int &index, int id )
+{
+ // we can't have it in widgets, or something is really wrong
+ //widgets.removeRef( w );
+
+ connect( w, SIGNAL( destroyed() ),
+ this, SLOT( widgetDestroyed() ) );
+ if ( index == -1 || index > (int)widgets.count() ) {
+ index = (int)widgets.count();
+ widgets.append( w );
+ }
+ else
+ widgets.insert( index, w );
+ if ( id == -1 )
+ id = id2widget.count();
+ id2widget.insert( id, w );
+ widget2id.insert( w, id );
+}
+
+void KToolBar::showEvent( QShowEvent *e )
+{
+ QToolBar::showEvent( e );
+ rebuildLayout();
+}
+
+void KToolBar::setStretchableWidget( QWidget *w )
+{
+ QToolBar::setStretchableWidget( w );
+ stretchableWidget = w;
+}
+
+QSizePolicy KToolBar::sizePolicy() const
+{
+ if ( orientation() == Horizontal )
+ return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
+ else
+ return QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Expanding );
+}
+
+QSize KToolBar::sizeHint() const
+{
+ QSize minSize(0,0);
+ KToolBar *ncThis = const_cast<KToolBar *>(this);
+
+ ncThis->polish();
+
+ int margin = static_cast<QWidget*>(ncThis)->layout()->margin() + frameWidth();
+ switch( barPos() )
+ {
+ case KToolBar::Top:
+ case KToolBar::Bottom:
+ for ( QWidget *w = ncThis->widgets.first(); w; w = ncThis->widgets.next() )
+ {
+ QSize sh = w->sizeHint();
+ if ( w->sizePolicy().horData() == QSizePolicy::Ignored )
+ sh.setWidth( 1 );
+ if ( w->sizePolicy().verData() == QSizePolicy::Ignored )
+ sh.setHeight( 1 );
+ sh = sh.boundedTo( w->maximumSize() )
+ .expandedTo( w->minimumSize() ).expandedTo( QSize(1, 1) );
+
+ minSize = minSize.expandedTo(QSize(0, sh.height()));
+ minSize += QSize(sh.width()+1, 0);
+ if (dynamic_cast<QLineEdit *>(w)) // w is a QLineEdit ?
+ minSize += QSize(2, 0); // A little bit extra spacing behind it.
+ }
+
+ minSize += QSize(QApplication::style().pixelMetric( QStyle::PM_DockWindowHandleExtent ), 0);
+ minSize += QSize(margin*2, margin*2);
+ break;
+
+ case KToolBar::Left:
+ case KToolBar::Right:
+ for ( QWidget *w = ncThis->widgets.first(); w; w = ncThis->widgets.next() )
+ {
+ QSize sh = w->sizeHint();
+ if ( w->sizePolicy().horData() == QSizePolicy::Ignored )
+ sh.setWidth( 1 );
+ if ( w->sizePolicy().verData() == QSizePolicy::Ignored )
+ sh.setHeight( 1 );
+ sh = sh.boundedTo( w->maximumSize() )
+ .expandedTo( w->minimumSize() ).expandedTo( QSize(1, 1) );
+
+ minSize = minSize.expandedTo(QSize(sh.width(), 0));
+ minSize += QSize(0, sh.height()+1);
+ }
+ minSize += QSize(0, QApplication::style().pixelMetric( QStyle::PM_DockWindowHandleExtent ));
+ minSize += QSize(margin*2, margin*2);
+ break;
+
+ default:
+ minSize = QToolBar::sizeHint();
+ break;
+ }
+ return minSize;
+}
+
+QSize KToolBar::minimumSize() const
+{
+ return minimumSizeHint();
+}
+
+QSize KToolBar::minimumSizeHint() const
+{
+ return sizeHint();
+}
+
+bool KToolBar::highlight() const
+{
+ return d->m_highlight;
+}
+
+void KToolBar::hide()
+{
+ QToolBar::hide();
+}
+
+void KToolBar::show()
+{
+ QToolBar::show();
+}
+
+void KToolBar::resizeEvent( QResizeEvent *e )
+{
+ bool b = isUpdatesEnabled();
+ setUpdatesEnabled( false );
+ QToolBar::resizeEvent( e );
+ if (b)
+ {
+ if (layoutTimer->isActive())
+ {
+ // Wait with repainting till layout is complete.
+ d->repaintTimer.start( 100, true );
+ }
+ else
+ {
+ // Repaint now
+ slotRepaint();
+ }
+ }
+}
+
+void KToolBar::slotIconChanged(int group)
+{
+ if ((group != KIcon::Toolbar) && (group != KIcon::MainToolbar))
+ return;
+ if ((group == KIcon::MainToolbar) != !::qstrcmp(name(), "mainToolBar"))
+ return;
+
+ doModeChange();
+
+ if (isVisible())
+ updateGeometry();
+}
+
+void KToolBar::slotReadConfig()
+{
+ //kdDebug(220) << name() << " slotReadConfig" << endl;
+ // Read appearance settings (hmm, we used to do both here,
+ // but a well behaved application will call applyMainWindowSettings
+ // anyway, right ?)
+ applyAppearanceSettings(KGlobal::config(), QString::null );
+}
+
+void KToolBar::slotAppearanceChanged()
+{
+ // Read appearance settings from global file.
+ applyAppearanceSettings(KGlobal::config(), QString::null, true /* lose local settings */ );
+
+ // And remember to save the new look later
+ KMainWindow *kmw = dynamic_cast<KMainWindow *>(mainWindow());
+ if ( kmw )
+ kmw->setSettingsDirty();
+}
+
+//static
+bool KToolBar::highlightSetting()
+{
+ QString grpToolbar(QString::fromLatin1("Toolbar style"));
+ KConfigGroupSaver saver(KGlobal::config(), grpToolbar);
+ return KGlobal::config()->readBoolEntry(QString::fromLatin1("Highlighting"),true);
+}
+
+//static
+bool KToolBar::transparentSetting()
+{
+ QString grpToolbar(QString::fromLatin1("Toolbar style"));
+ KConfigGroupSaver saver(KGlobal::config(), grpToolbar);
+ return KGlobal::config()->readBoolEntry(QString::fromLatin1("TransparentMoving"),true);
+}
+
+//static
+KToolBar::IconText KToolBar::iconTextSetting()
+{
+ QString grpToolbar(QString::fromLatin1("Toolbar style"));
+ KConfigGroupSaver saver(KGlobal::config(), grpToolbar);
+ QString icontext = KGlobal::config()->readEntry(QString::fromLatin1("IconText"),QString::fromLatin1("IconOnly"));
+ if ( icontext == "IconTextRight" )
+ return IconTextRight;
+ else if ( icontext == "IconTextBottom" )
+ return IconTextBottom;
+ else if ( icontext == "TextOnly" )
+ return TextOnly;
+ else
+ return IconOnly;
+}
+
+void KToolBar::applyAppearanceSettings(KConfig *config, const QString &_configGroup, bool forceGlobal)
+{
+ QString configGroup = _configGroup.isEmpty() ? settingsGroup() : _configGroup;
+ //kdDebug(220) << name() << " applyAppearanceSettings: configGroup=" << configGroup << " forceGlobal=" << forceGlobal << endl;
+
+ // If we have application-specific settings in the XML file,
+ // and nothing in the application's config file, then
+ // we don't apply the global defaults, the XML ones are preferred
+ // (see applySettings for a full explanation)
+ // This is the reason for the xmlgui tests below.
+ bool xmlgui = d->m_xmlguiClient && !d->m_xmlguiClient->xmlFile().isEmpty();
+
+ KConfig *gconfig = KGlobal::config();
+
+ static const QString &attrIconText = KGlobal::staticQString("IconText");
+ static const QString &attrHighlight = KGlobal::staticQString("Highlighting");
+ static const QString &attrTrans = KGlobal::staticQString("TransparentMoving");
+ static const QString &attrIconSize = KGlobal::staticQString("IconSize");
+
+ // we actually do this in two steps.
+ // First, we read in the global styles [Toolbar style] (from the KControl module).
+ // Then, if the toolbar is NOT 'mainToolBar', we will also try to read in [barname Toolbar style]
+ bool highlight;
+ int transparent;
+ bool applyIconText = !xmlgui; // if xmlgui is used, global defaults won't apply
+ bool applyIconSize = !xmlgui;
+
+ int iconSize = d->IconSizeDefault;
+ QString iconText = d->IconTextDefault;
+
+ // this is the first iteration
+ QString grpToolbar(QString::fromLatin1("Toolbar style"));
+ { // start block for KConfigGroupSaver
+ KConfigGroupSaver saver(gconfig, grpToolbar);
+
+ // first, get the generic settings
+ highlight = gconfig->readBoolEntry(attrHighlight, true);
+ transparent = gconfig->readBoolEntry(attrTrans, true);
+
+ // we read in the IconText property *only* if we intend on actually
+ // honoring it
+ if (d->m_honorStyle)
+ d->IconTextDefault = gconfig->readEntry(attrIconText, d->IconTextDefault);
+ else
+ d->IconTextDefault = "IconOnly";
+
+ // Use the default icon size for toolbar icons.
+ d->IconSizeDefault = gconfig->readNumEntry(attrIconSize, d->IconSizeDefault);
+
+ iconSize = d->IconSizeDefault;
+ iconText = d->IconTextDefault;
+
+ if ( !forceGlobal && config->hasGroup(configGroup) )
+ {
+ config->setGroup(configGroup);
+
+ // first, get the generic settings
+ highlight = config->readBoolEntry(attrHighlight, highlight);
+ transparent = config->readBoolEntry(attrTrans, transparent);
+
+ // read in the IconText property
+ if ( config->hasKey( attrIconText ) ) {
+ iconText = config->readEntry(attrIconText);
+ applyIconText = true;
+ //kdDebug(220) << name() << " read icontext=" << d->IconTextDefault << ", that will be the default" << endl;
+ }
+
+ // now get the size
+ if ( config->hasKey( attrIconSize ) ) {
+ iconSize = config->readNumEntry(attrIconSize);
+ applyIconSize = true;
+ }
+ }
+
+ // revert back to the old group
+ } // end block for KConfigGroupSaver
+
+ bool doUpdate = false;
+
+ IconText icon_text;
+ if ( iconText == "IconTextRight" )
+ icon_text = IconTextRight;
+ else if ( iconText == "IconTextBottom" )
+ icon_text = IconTextBottom;
+ else if ( iconText == "TextOnly" )
+ icon_text = TextOnly;
+ else
+ icon_text = IconOnly;
+
+ // check if the icon/text has changed
+ if (icon_text != d->m_iconText && applyIconText) {
+ //kdDebug(220) << name() << " applyAppearanceSettings setIconText " << icon_text << endl;
+ setIconText(icon_text, false);
+ doUpdate = true;
+ }
+
+ // ...and check if the icon size has changed
+ if (iconSize != d->m_iconSize && applyIconSize) {
+ setIconSize(iconSize, false);
+ doUpdate = true;
+ }
+
+ QMainWindow *mw = mainWindow();
+
+ // ...and if we should highlight
+ if ( highlight != d->m_highlight ) {
+ d->m_highlight = highlight;
+ doUpdate = true;
+ }
+
+ // ...and if we should move transparently
+ if ( mw && transparent != (!mw->opaqueMoving()) ) {
+ mw->setOpaqueMoving( !transparent );
+ }
+
+ if (doUpdate)
+ doModeChange(); // tell buttons what happened
+
+ if (isVisible ())
+ updateGeometry();
+}
+
+void KToolBar::applySettings(KConfig *config, const QString &_configGroup)
+{
+ return applySettings(config,_configGroup,false);
+}
+
+void KToolBar::applySettings(KConfig *config, const QString &_configGroup, bool force)
+{
+ //kdDebug(220) << name() << " applySettings group=" << _configGroup << endl;
+
+ QString configGroup = _configGroup.isEmpty() ? settingsGroup() : _configGroup;
+
+ /*
+ Let's explain this a bit more in details.
+ The order in which we apply settings is :
+ Global config / <appnamerc> user settings if no XMLGUI is used
+ Global config / App-XML attributes / <appnamerc> user settings if XMLGUI is used
+
+ So in the first case, we simply read everything from KConfig as below,
+ but in the second case we don't do anything here if there is no app-specific config,
+ and the XMLGUI-related code (loadState()) uses the static methods of this class
+ to get the global defaults.
+
+ Global config doesn't include position (index, offset, newline and hidden/shown).
+ */
+
+ // First the appearance stuff - the one which has a global config
+ applyAppearanceSettings( config, configGroup );
+
+ // ...and now the position stuff
+ if ( config->hasGroup(configGroup) || force )
+ {
+ KConfigGroupSaver cgs(config, configGroup);
+
+ static const QString &attrPosition = KGlobal::staticQString("Position");
+ static const QString &attrIndex = KGlobal::staticQString("Index");
+ static const QString &attrOffset = KGlobal::staticQString("Offset");
+ static const QString &attrNewLine = KGlobal::staticQString("NewLine");
+ static const QString &attrHidden = KGlobal::staticQString("Hidden");
+
+ QString position = config->readEntry(attrPosition, d->PositionDefault);
+ int index = config->readNumEntry(attrIndex, -1);
+ int offset = config->readNumEntry(attrOffset, d->OffsetDefault);
+ bool newLine = config->readBoolEntry(attrNewLine, d->NewLineDefault);
+ bool hidden = config->readBoolEntry(attrHidden, d->HiddenDefault);
+
+ Dock pos(DockTop);
+ if ( position == "Top" )
+ pos = DockTop;
+ else if ( position == "Bottom" )
+ pos = DockBottom;
+ else if ( position == "Left" )
+ pos = DockLeft;
+ else if ( position == "Right" )
+ pos = DockRight;
+ else if ( position == "Floating" )
+ pos = DockTornOff;
+ else if ( position == "Flat" )
+ pos = DockMinimized;
+
+ //kdDebug(220) << name() << " applySettings hidden=" << hidden << endl;
+ if (hidden)
+ hide();
+ else
+ show();
+
+ if ( mainWindow() )
+ {
+ //kdDebug(220) << name() << " applySettings updating ToolbarInfo" << endl;
+ d->toolBarInfo = KToolBarPrivate::ToolBarInfo( pos, index, newLine, offset );
+ positionYourself( true );
+ }
+ if (isVisible ())
+ updateGeometry();
+ }
+}
+
+bool KToolBar::event( QEvent *e )
+{
+ if ( (e->type() == QEvent::LayoutHint) && isUpdatesEnabled() )
+ d->repaintTimer.start( 100, true );
+
+ if (e->type() == QEvent::ChildInserted )
+ {
+ // Bypass QToolBar::event,
+ // it will show() the inserted child and we don't want to
+ // do that until we have rebuilt the layout.
+ childEvent((QChildEvent *)e);
+ return true;
+ }
+
+ return QToolBar::event( e );
+}
+
+void KToolBar::slotRepaint()
+{
+ setUpdatesEnabled( false );
+ // Send a resizeEvent to update the "toolbar extension arrow"
+ // (The button you get when your toolbar-items don't fit in
+ // the available space)
+ QResizeEvent ev(size(), size());
+ resizeEvent(&ev);
+ QApplication::sendPostedEvents( this, QEvent::LayoutHint );
+ setUpdatesEnabled( true );
+ repaint( true );
+}
+
+void KToolBar::toolBarPosChanged( QToolBar *tb )
+{
+ if ( tb != this )
+ return;
+ if ( d->oldPos == DockMinimized )
+ rebuildLayout();
+ d->oldPos = (QMainWindow::ToolBarDock)barPos();
+ KMainWindow *kmw = dynamic_cast<KMainWindow *>(mainWindow());
+ if ( kmw )
+ kmw->setSettingsDirty();
+}
+
+static KToolBar::Dock stringToDock( const QString& attrPosition )
+{
+ KToolBar::Dock dock = KToolBar::DockTop;
+ if ( !attrPosition.isEmpty() ) {
+ if ( attrPosition == "top" )
+ dock = KToolBar::DockTop;
+ else if ( attrPosition == "left" )
+ dock = KToolBar::DockLeft;
+ else if ( attrPosition == "right" )
+ dock = KToolBar::DockRight;
+ else if ( attrPosition == "bottom" )
+ dock = KToolBar::DockBottom;
+ else if ( attrPosition == "floating" )
+ dock = KToolBar::DockTornOff;
+ else if ( attrPosition == "flat" )
+ dock = KToolBar::DockMinimized;
+ }
+ return dock;
+}
+
+
+void KToolBar::loadState( const QDomElement &element )
+{
+ QMainWindow *mw = mainWindow();
+
+ if ( !mw )
+ return;
+
+ {
+ QCString text = element.namedItem( "text" ).toElement().text().utf8();
+ if ( text.isEmpty() )
+ text = element.namedItem( "Text" ).toElement().text().utf8();
+ if ( !text.isEmpty() )
+ setText( i18n( text ) );
+ }
+
+ {
+ QCString attrFullWidth = element.attribute( "fullWidth" ).lower().latin1();
+ if ( !attrFullWidth.isEmpty() )
+ setFullSize( attrFullWidth == "true" );
+ }
+
+ /*
+ This method is called in order to load toolbar settings from XML.
+ However this can be used in two rather different cases:
+ - for the initial loading of the app's XML. In that case the settings
+ are only the defaults, the user's KConfig settings will override them
+ (KDE4 TODO: how about saving those user settings into the local XML file instead?
+ Then this whole thing would be simpler, no KConfig settings to apply afterwards.
+ OTOH we'd have to migrate those settings when the .rc version increases,
+ like we do for shortcuts)
+
+ - for later re-loading when switching between parts in KXMLGUIFactory.
+ In that case the XML contains the final settings, not the defaults.
+ We do need the defaults, and the toolbar might have been completely
+ deleted and recreated meanwhile. So we store the app-default settings
+ into the XML.
+ */
+ bool loadingAppDefaults = true;
+ if ( element.hasAttribute( "offsetDefault" ) )
+ {
+ // this isn't the first time, so the defaults have been saved into the (in-memory) XML
+ loadingAppDefaults = false;
+ d->OffsetDefault = element.attribute( "offsetDefault" ).toInt();
+ d->NewLineDefault = element.attribute( "newlineDefault" ) == "true";
+ d->HiddenDefault = element.attribute( "hiddenDefault" ) == "true";
+ d->IconSizeDefault = element.attribute( "iconSizeDefault" ).toInt();
+ d->PositionDefault = element.attribute( "positionDefault" );
+ d->IconTextDefault = element.attribute( "iconTextDefault" );
+ }
+ //kdDebug(220) << name() << " loadState loadingAppDefaults=" << loadingAppDefaults << endl;
+
+ Dock dock = stringToDock( element.attribute( "position" ).lower() );
+
+ {
+ QCString attrIconText = element.attribute( "iconText" ).lower().latin1();
+ if ( !attrIconText.isEmpty() ) {
+ //kdDebug(220) << name() << " loadState attrIconText=" << attrIconText << endl;
+ if ( attrIconText == "icontextright" )
+ setIconText( KToolBar::IconTextRight );
+ else if ( attrIconText == "textonly" )
+ setIconText( KToolBar::TextOnly );
+ else if ( attrIconText == "icontextbottom" )
+ setIconText( KToolBar::IconTextBottom );
+ else if ( attrIconText == "icononly" )
+ setIconText( KToolBar::IconOnly );
+ } else
+ {
+ //kdDebug(220) << name() << " loadState no iconText attribute in XML, using iconTextSetting=" << iconTextSetting() << endl;
+ // Use global setting
+ if (d->m_honorStyle)
+ setIconText( iconTextSetting() );
+ else
+ setIconText( d->IconTextDefault );
+ }
+ }
+
+ QString attrIconSize = element.attribute( "iconSize" ).lower();
+ int iconSize = d->IconSizeDefault;
+ if ( !attrIconSize.isEmpty() )
+ iconSize = attrIconSize.toInt();
+ setIconSize( iconSize );
+
+ int index = -1; // append by default. This is very important, otherwise
+ // with all 0 indexes, we keep reversing the toolbars.
+ {
+ QString attrIndex = element.attribute( "index" ).lower();
+ if ( !attrIndex.isEmpty() )
+ index = attrIndex.toInt();
+ }
+
+ int offset = d->OffsetDefault;
+ bool newLine = d->NewLineDefault;
+ bool hidden = d->HiddenDefault;
+
+ {
+ QString attrOffset = element.attribute( "offset" );
+ if ( !attrOffset.isEmpty() )
+ offset = attrOffset.toInt();
+ }
+
+ {
+ QString attrNewLine = element.attribute( "newline" ).lower();
+ if ( !attrNewLine.isEmpty() )
+ newLine = attrNewLine == "true";
+ }
+
+ {
+ QString attrHidden = element.attribute( "hidden" ).lower();
+ if ( !attrHidden.isEmpty() ) {
+ hidden = attrHidden == "true";
+ }
+ }
+
+ d->toolBarInfo = KToolBarPrivate::ToolBarInfo( dock, index, newLine, offset );
+ mw->addDockWindow( this, dock, newLine );
+ mw->moveDockWindow( this, dock, newLine, index, offset );
+
+ // Apply the highlight button setting
+ d->m_highlight = highlightSetting();
+
+ if ( hidden )
+ hide();
+ else
+ show();
+
+ if ( loadingAppDefaults )
+ {
+ getAttributes( d->PositionDefault, d->IconTextDefault, index );
+ //kdDebug(220) << name() << " loadState IconTextDefault=" << d->IconTextDefault << endl;
+ d->OffsetDefault = offset;
+ d->NewLineDefault = newLine;
+ d->HiddenDefault = hidden;
+ d->IconSizeDefault = iconSize;
+ }
+ //kdDebug(220) << name() << " loadState hidden=" << hidden << endl;
+
+ // Apply transparent-toolbar-moving setting (ok, this is global to the mainwindow,
+ // but we do it only if there are toolbars...)
+ // KDE4: move to KMainWindow
+ if ( transparentSetting() != !mw->opaqueMoving() )
+ mw->setOpaqueMoving( !transparentSetting() );
+}
+
+int KToolBar::dockWindowIndex()
+{
+ int index = 0;
+ Q_ASSERT( mainWindow() );
+ if ( mainWindow() ) {
+ QMainWindow::ToolBarDock dock;
+ bool newLine;
+ int offset;
+ mainWindow()->getLocation( this, dock, index, newLine, offset );
+ }
+ return index;
+}
+
+void KToolBar::getAttributes( QString &position, QString &icontext, int &index )
+{
+ // get all of the stuff to save
+ switch ( barPos() ) {
+ case KToolBar::Flat:
+ position = "Flat";
+ break;
+ case KToolBar::Bottom:
+ position = "Bottom";
+ break;
+ case KToolBar::Left:
+ position = "Left";
+ break;
+ case KToolBar::Right:
+ position = "Right";
+ break;
+ case KToolBar::Floating:
+ position = "Floating";
+ break;
+ case KToolBar::Top:
+ default:
+ position = "Top";
+ break;
+ }
+
+ index = dockWindowIndex();
+
+ switch (d->m_iconText) {
+ case KToolBar::IconTextRight:
+ icontext = "IconTextRight";
+ break;
+ case KToolBar::IconTextBottom:
+ icontext = "IconTextBottom";
+ break;
+ case KToolBar::TextOnly:
+ icontext = "TextOnly";
+ break;
+ case KToolBar::IconOnly:
+ default:
+ icontext = "IconOnly";
+ break;
+ }
+ //kdDebug(220) << name() << " getAttributes: icontext=" << icontext << endl;
+}
+
+void KToolBar::saveState( QDomElement &current )
+{
+ Q_ASSERT( !current.isNull() );
+ QString position, icontext;
+ int index = -1;
+ getAttributes( position, icontext, index );
+
+ current.setAttribute( "noMerge", "1" );
+ current.setAttribute( "position", position );
+ current.setAttribute( "iconText", icontext );
+ current.setAttribute( "index", index );
+ current.setAttribute( "offset", offset() );
+ current.setAttribute( "newline", newLine() );
+ if ( isHidden() )
+ current.setAttribute( "hidden", "true" );
+ d->modified = true;
+
+ // TODO if this method is used by more than KXMLGUIBuilder, e.g. to save XML settings to *disk*,
+ // then the stuff below shouldn't always be done.
+ current.setAttribute( "offsetDefault", d->OffsetDefault );
+ current.setAttribute( "newlineDefault", d->NewLineDefault );
+ current.setAttribute( "hiddenDefault", d->HiddenDefault ? "true" : "false" );
+ current.setAttribute( "iconSizeDefault", d->IconSizeDefault );
+ current.setAttribute( "positionDefault", d->PositionDefault );
+ current.setAttribute( "iconTextDefault", d->IconTextDefault );
+
+ //kdDebug(220) << name() << " saveState: saving index=" << index << " iconText=" << icontext << " hidden=" << isHidden() << endl;
+}
+
+// Called by KMainWindow::finalizeGUI
+void KToolBar::positionYourself( bool force )
+{
+ if (force)
+ d->positioned = false;
+
+ if ( d->positioned || !mainWindow() )
+ {
+ //kdDebug(220) << name() << " positionYourself d->positioned=true ALREADY DONE" << endl;
+ return;
+ }
+ // we can't test for ForceHide after moveDockWindow because QDockArea
+ // does a reparent() with showIt == true
+ bool hidden = isHidden();
+ //kdDebug(220) << name() << " positionYourself dock=" << d->toolBarInfo.dock << " newLine=" << d->toolBarInfo.newline << " index=" << d->toolBarInfo.index << " offset=" << d->toolBarInfo.offset << endl;
+ mainWindow()->moveDockWindow( this, d->toolBarInfo.dock,
+ d->toolBarInfo.newline,
+ d->toolBarInfo.index,
+ d->toolBarInfo.offset );
+
+ //kdDebug(220) << name() << " positionYourself dockWindowIndex=" << dockWindowIndex() << endl;
+ if ( hidden )
+ hide();
+ else
+ show();
+ // This method can only have an effect once - unless force is set
+ d->positioned = true;
+}
+
+KPopupMenu *KToolBar::contextMenu()
+{
+ if ( context )
+ return context;
+ // Construct our context popup menu. Name it qt_dockwidget_internal so it
+ // won't be deleted by QToolBar::clear().
+ context = new KPopupMenu( this, "qt_dockwidget_internal" );
+ context->insertTitle(i18n("Toolbar Menu"));
+
+ KPopupMenu *orient = new KPopupMenu( context, "orient" );
+ orient->insertItem( i18n("toolbar position string","Top"), CONTEXT_TOP );
+ orient->insertItem( i18n("toolbar position string","Left"), CONTEXT_LEFT );
+ orient->insertItem( i18n("toolbar position string","Right"), CONTEXT_RIGHT );
+ orient->insertItem( i18n("toolbar position string","Bottom"), CONTEXT_BOTTOM );
+ orient->insertSeparator(-1);
+ orient->insertItem( i18n("toolbar position string","Floating"), CONTEXT_FLOAT );
+ orient->insertItem( i18n("min toolbar", "Flat"), CONTEXT_FLAT );
+
+ KPopupMenu *mode = new KPopupMenu( context, "mode" );
+ mode->insertItem( i18n("Icons Only"), CONTEXT_ICONS );
+ mode->insertItem( i18n("Text Only"), CONTEXT_TEXT );
+ mode->insertItem( i18n("Text Alongside Icons"), CONTEXT_TEXTRIGHT );
+ mode->insertItem( i18n("Text Under Icons"), CONTEXT_TEXTUNDER );
+
+ KPopupMenu *size = new KPopupMenu( context, "size" );
+ size->insertItem( i18n("Default"), CONTEXT_ICONSIZES );
+ // Query the current theme for available sizes
+ KIconTheme *theme = KGlobal::instance()->iconLoader()->theme();
+ QValueList<int> avSizes;
+ if (theme)
+ {
+ if (!::qstrcmp(QObject::name(), "mainToolBar"))
+ avSizes = theme->querySizes( KIcon::MainToolbar);
+ else
+ avSizes = theme->querySizes( KIcon::Toolbar);
+ }
+
+ d->iconSizes = avSizes;
+ qHeapSort(avSizes);
+
+ QValueList<int>::Iterator it;
+ if (avSizes.count() < 10) {
+ // Fixed or threshold type icons
+ QValueList<int>::Iterator end(avSizes.end());
+ for (it=avSizes.begin(); it!=end; ++it) {
+ QString text;
+ if ( *it < 19 )
+ text = i18n("Small (%1x%2)").arg(*it).arg(*it);
+ else if (*it < 25)
+ text = i18n("Medium (%1x%2)").arg(*it).arg(*it);
+ else if (*it < 35)
+ text = i18n("Large (%1x%2)").arg(*it).arg(*it);
+ else
+ text = i18n("Huge (%1x%2)").arg(*it).arg(*it);
+ //we use the size as an id, with an offset
+ size->insertItem( text, CONTEXT_ICONSIZES + *it );
+ }
+ }
+ else {
+ // Scalable icons.
+ const int progression[] = {16, 22, 32, 48, 64, 96, 128, 192, 256};
+
+ it = avSizes.begin();
+ for (uint i = 0; i < 9; i++) {
+ while (it++ != avSizes.end()) {
+ if (*it >= progression[i]) {
+ QString text;
+ if ( *it < 19 )
+ text = i18n("Small (%1x%2)").arg(*it).arg(*it);
+ else if (*it < 25)
+ text = i18n("Medium (%1x%2)").arg(*it).arg(*it);
+ else if (*it < 35)
+ text = i18n("Large (%1x%2)").arg(*it).arg(*it);
+ else
+ text = i18n("Huge (%1x%2)").arg(*it).arg(*it);
+ //we use the size as an id, with an offset
+ size->insertItem( text, CONTEXT_ICONSIZES + *it );
+ break;
+ }
+ }
+ }
+ }
+
+ context->insertItem( i18n("Orientation"), orient );
+ orient->setItemChecked(CONTEXT_TOP, true);
+ context->insertItem( i18n("Text Position"), mode );
+ context->setItemChecked(CONTEXT_ICONS, true);
+ context->insertItem( i18n("Icon Size"), size );
+
+ connect( context, SIGNAL( aboutToShow() ), this, SLOT( slotContextAboutToShow() ) );
+ // Unplugging a submenu from abouttohide leads to the popupmenu floating around
+ // So better simply call that code from after exec() returns (DF)
+ //connect( context, SIGNAL( aboutToHide() ), this, SLOT( slotContextAboutToHide() ) );
+ return context;
+}
+
+void KToolBar::slotContextAboutToShow()
+{
+ // The idea here is to reuse the "static" part of the menu to save time.
+ // But the "Toolbars" action is dynamic (can be a single action or a submenu)
+ // and ToolBarHandler::setupActions() deletes it, so better not keep it around.
+ // So we currently plug/unplug the last two actions of the menu.
+ // Another way would be to keep around the actions and plug them all into a (new each time) popupmenu.
+ KMainWindow *kmw = dynamic_cast<KMainWindow *>(mainWindow());
+ if ( kmw ) {
+ kmw->setupToolbarMenuActions();
+ // Only allow hiding a toolbar if the action is also plugged somewhere else (e.g. menubar)
+ KAction *tbAction = kmw->toolBarMenuAction();
+ if ( tbAction && tbAction->containerCount() > 0 )
+ tbAction->plug(context);
+ }
+
+ // try to find "configure toolbars" action
+ KAction *configureAction = 0;
+ const char* actionName = KStdAction::name(KStdAction::ConfigureToolbars);
+ if ( d->m_xmlguiClient )
+ configureAction = d->m_xmlguiClient->actionCollection()->action(actionName);
+ if ( !configureAction && kmw )
+ configureAction = kmw->actionCollection()->action(actionName);
+ if ( configureAction )
+ configureAction->plug(context);
+ KEditToolbar::setDefaultToolbar(QObject::name());
+
+ for(int i = CONTEXT_ICONS; i <= CONTEXT_TEXTUNDER; ++i)
+ context->setItemChecked(i, false);
+
+ switch( d->m_iconText )
+ {
+ case IconOnly:
+ default:
+ context->setItemChecked(CONTEXT_ICONS, true);
+ break;
+ case IconTextRight:
+ context->setItemChecked(CONTEXT_TEXTRIGHT, true);
+ break;
+ case TextOnly:
+ context->setItemChecked(CONTEXT_TEXT, true);
+ break;
+ case IconTextBottom:
+ context->setItemChecked(CONTEXT_TEXTUNDER, true);
+ break;
+ }
+
+ QValueList<int>::ConstIterator iIt = d->iconSizes.begin();
+ QValueList<int>::ConstIterator iEnd = d->iconSizes.end();
+ for (; iIt != iEnd; ++iIt )
+ context->setItemChecked( CONTEXT_ICONSIZES + *iIt, false );
+
+ context->setItemChecked( CONTEXT_ICONSIZES, false );
+
+ context->setItemChecked( CONTEXT_ICONSIZES + d->m_iconSize, true );
+
+ for ( int i = CONTEXT_TOP; i <= CONTEXT_FLAT; ++i )
+ context->setItemChecked( i, false );
+
+ switch ( barPos() )
+ {
+ case KToolBar::Flat:
+ context->setItemChecked( CONTEXT_FLAT, true );
+ break;
+ case KToolBar::Bottom:
+ context->setItemChecked( CONTEXT_BOTTOM, true );
+ break;
+ case KToolBar::Left:
+ context->setItemChecked( CONTEXT_LEFT, true );
+ break;
+ case KToolBar::Right:
+ context->setItemChecked( CONTEXT_RIGHT, true );
+ break;
+ case KToolBar::Floating:
+ context->setItemChecked( CONTEXT_FLOAT, true );
+ break;
+ case KToolBar::Top:
+ context->setItemChecked( CONTEXT_TOP, true );
+ break;
+ default: break;
+ }
+}
+
+void KToolBar::slotContextAboutToHide()
+{
+ // We have to unplug whatever slotContextAboutToShow plugged into the menu.
+ // Unplug the toolbar menu action
+ KMainWindow *kmw = dynamic_cast<KMainWindow *>(mainWindow());
+ if ( kmw && kmw->toolBarMenuAction() )
+ if ( kmw->toolBarMenuAction()->containerCount() > 1 )
+ kmw->toolBarMenuAction()->unplug(context);
+
+ // Unplug the configure toolbars action too, since it's afterwards anyway
+ KAction *configureAction = 0;
+ const char* actionName = KStdAction::name(KStdAction::ConfigureToolbars);
+ if ( d->m_xmlguiClient )
+ configureAction = d->m_xmlguiClient->actionCollection()->action(actionName);
+ if ( !configureAction && kmw )
+ configureAction = kmw->actionCollection()->action(actionName);
+ if ( configureAction )
+ configureAction->unplug(context);
+
+ QPtrListIterator<QWidget> it( widgets );
+ QWidget *wdg;
+ while ( ( wdg = it.current() ) != 0 ) {
+ if ( wdg->inherits( "QToolButton" ) )
+ static_cast<QToolButton*>( wdg )->setDown( false );
+ ++it;
+ }
+}
+
+void KToolBar::widgetDestroyed()
+{
+ removeWidgetInternal( (QWidget*)sender() );
+}
+
+void KToolBar::removeWidgetInternal( QWidget * w )
+{
+ widgets.removeRef( w );
+ QMap< QWidget*, int >::Iterator it = widget2id.find( w );
+ if ( it == widget2id.end() )
+ return;
+ id2widget.remove( *it );
+ widget2id.remove( it );
+}
+
+void KToolBar::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "ktoolbar.moc"
+
diff --git a/kdeui/ktoolbar.h b/kdeui/ktoolbar.h
new file mode 100644
index 000000000..3deab0f73
--- /dev/null
+++ b/kdeui/ktoolbar.h
@@ -0,0 +1,1128 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Reginald Stadlbauer (reggie@kde.org)
+ (C) 1997, 1998 Stephan Kulow (coolo@kde.org)
+ (C) 1997, 1998 Sven Radej (radej@kde.org)
+ (C) 1997, 1998 Mark Donohoe (donohoe@kde.org)
+ (C) 1997, 1998 Matthias Ettrich (ettrich@kde.org)
+ (C) 1999, 2000 Kurt Granroth (granroth@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KTOOLBAR_H
+#define KTOOLBAR_H
+
+#include <qtoolbar.h>
+#include <qmainwindow.h>
+#include <qcombobox.h>
+#include <qmap.h>
+#include <qptrlist.h>
+#include <qguardedptr.h>
+#include <qframe.h>
+#include <qiconset.h>
+
+#include <kglobal.h>
+
+class QDomElement;
+class QSize;
+class QPixmap;
+class QPopupMenu;
+class QStringList;
+class QDomDocument;
+class QTimer;
+
+class KLineEdit;
+class KToolBar;
+class KToolBarButton;
+class KToolBoxManager;
+class KAnimWidget;
+class KPopupMenu;
+class KInstance;
+class KComboBox;
+class KXMLGUIClient;
+
+class KToolBarPrivate;
+
+class KDEUI_EXPORT KToolBarSeparator : public QFrame
+{
+ Q_OBJECT
+public:
+ KToolBarSeparator( Orientation, bool l, QToolBar *parent, const char* name=0 );
+
+ QSize sizeHint() const;
+ Orientation orientation() const { return orient; }
+ QSizePolicy sizePolicy() const;
+ bool showLine() const { return line; }
+public slots:
+ void setOrientation( Orientation );
+protected:
+ void styleChange( QStyle& );
+ void drawContents( QPainter* );
+private:
+ Orientation orient;
+ bool line;
+};
+
+
+ /**
+ * @short Floatable toolbar with auto resize.
+ *
+ * A KDE-style toolbar.
+ *
+ * KToolBar can be dragged around in and between different docks.
+ *
+ * A KToolBar can contain all sorts of widgets.
+ *
+ * KToolBar can be used as a standalone widget, but KMainWindow
+ * provides easy factories and management of one or more toolbars.
+ * Once you have a KToolBar object, you can insert items into it with the
+ * insert... methods, or remove them with the removeItem() method. This
+ * can be done at any time; the toolbar will be automatically updated.
+ * There are also many methods to set per-child properties like alignment
+ * and toggle behavior.
+ *
+ * KToolBar uses a global config group to load toolbar settings on
+ * construction. It will reread this config group on a
+ * KApplication::appearanceChanged() signal.
+ *
+ * @author Reginald Stadlbauer <reggie@kde.org>, Stephan Kulow <coolo@kde.org>, Sven Radej <radej@kde.org>.
+ */
+
+class KDEUI_EXPORT KToolBar : public QToolBar
+{
+ Q_OBJECT
+ Q_ENUMS( IconText BarPosition )
+ Q_PROPERTY( IconText iconText READ iconText WRITE setIconText )
+ Q_PROPERTY( BarPosition barPos READ barPos WRITE setBarPos )
+ Q_PROPERTY( bool fullSize READ fullSize WRITE setFullSize )
+ Q_PROPERTY( int iconSize READ iconSize WRITE setIconSize )
+ Q_PROPERTY( QString text READ text WRITE setText )
+
+public:
+ enum IconText{IconOnly = 0, IconTextRight, TextOnly, IconTextBottom};
+ /**
+ * The state of the status bar.
+ * @deprecated
+ */
+ enum BarStatus{Toggle, Show, Hide};
+ /**
+ * Possible bar positions.
+ */
+ enum BarPosition{ Unmanaged, Floating, Top, Bottom, Right, Left, Flat};
+
+ /**
+ * Normal constructor.
+ * This constructor is used by the XML-GUI. If you use it, you need
+ * to call QMainWindow::addToolBar to specify the position of the toolbar.
+ * So it's simpler to use the other constructor.
+ *
+ * The toolbar will read in various global config settings for
+ * things like icon size and text position, etc. However, some of
+ * the settings will be honored only if @p honorStyle is set to
+ * true. All other toolbars will be IconOnly and use Medium icons.
+ *
+ * @param parent The standard toolbar parent (usually a
+ * KMainWindow)
+ * @param name The standard internal name
+ * @param honorStyle If true, then global settings for IconSize and IconText will be honored
+ * @param readConfig whether to apply the configuration (global and application-specific)
+ */
+ KToolBar( QWidget *parent, const char *name = 0, bool honorStyle = false, bool readConfig = true );
+
+ /**
+ * Constructor for non-XML-GUI applications.
+ *
+ * The toolbar will read in various global config settings for
+ * things like icon size and text position, etc. However, some of
+ * the settings will be honored only if @p honorStyle is set to
+ * true. All other toolbars will be IconOnly and use Medium icons.
+ *
+ * @param parentWindow The window that should be the parent of this toolbar
+ * @param dock The position of the toolbar. Usually QMainWindow::Top.
+ * @param newLine If true, start a new line in the dock for this toolbar.
+ * @param name The standard internal name
+ * @param honorStyle If true, then global settings for IconSize and IconText will be honored
+ * @param readConfig whether to apply the configuration (global and application-specific)
+ */
+ KToolBar( QMainWindow *parentWindow, QMainWindow::ToolBarDock dock /*= QMainWindow::Top*/, bool newLine = false,
+ const char *name = 0, bool honorStyle = false, bool readConfig = true );
+
+ /**
+ * Constructor for non-XML-GUI applications.
+ *
+ * The toolbar will read in various global config settings for
+ * things like icon size and text position, etc. However, some of
+ * the settings will be honored only if @p honorStyle is set to
+ * true. All other toolbars will be IconOnly and use Medium icons.
+ *
+ * @param parentWindow The window that should be the parent of this toolbar
+ * @param dock Another widget than the mainwindow to dock toolbar to.
+ * @param newLine If true, start a new line in the dock for this toolbar.
+ * @param name The standard internal name
+ * @param honorStyle If true, then global settings for IconSize and IconText will be honored
+ * @param readConfig whether to apply the configuration (global and application-specific)
+ */
+ KToolBar( QMainWindow *parentWindow, QWidget *dock, bool newLine = false,
+ const char *name = 0, bool honorStyle = false, bool readConfig = true );
+
+ /**
+ * Destructor
+ */
+ virtual ~KToolBar();
+
+ /**
+ * Insert a button (a KToolBarButton) with a pixmap. The
+ * pixmap is loaded by the button itself based on the global icon
+ * settings.
+ *
+ * You should connect to one or more signals in KToolBar:
+ * clicked() , pressed() , released() , or
+ * highlighted() and if the button is a toggle button
+ * ( setToggle() ) toggled() . Those signals have @p id
+ * of a button that caused the signal. If you want to bind a popup
+ * to button, see setButton().
+ *
+ * @param icon The name of the icon to use as the active pixmap
+ * @param id The id of this button
+ * @param enabled Enable or disable the button at startup
+ * @param text The tooltip or toolbar text (depending on state)
+ * @param index The position of the button. (-1 = at end).
+ * @param _instance instance this button will belong to
+ *
+ * @return The item index.
+ */
+ int insertButton(const QString& icon, int id, bool enabled = true,
+ const QString& text = QString::null, int index=-1,
+ KInstance *_instance = KGlobal::instance());
+
+ /**
+ * This is the same as above, but with specified signals and
+ * slots to which this button will be connected.
+ *
+ * You can add more signals with addConnection().
+ *
+ * @param icon The name of the icon to use as the active pixmap
+ * @param id The id of this button
+ * @param signal The signal to connect to
+ * @param receiver The slot's parent
+ * @param slot The slot to receive the signal specified in that argument.
+ * @param enabled Enable or disable the button at startup
+ * @param text The tooltip or toolbar text (depending on state)
+ * @param index The position of the button. (-1 = at end).
+ * @param _instance instance this button will belong to
+ *
+ * @return The item index.
+ */
+ int insertButton(const QString& icon, int id, const char *signal,
+ const QObject *receiver, const char *slot,
+ bool enabled = true, const QString& text = QString::null,
+ int index=-1, KInstance *_instance = KGlobal::instance() );
+
+ /**
+ * Inserts a button (a KToolBarButton) with the specified
+ * pixmap. This pixmap will be used as the "active" one and the
+ * disabled and default ones will be autogenerated.
+ *
+ * It is recommended that you use the insertButton function that
+ * allows you to specify the icon name rather then the pixmap
+ * itself. Specifying the icon name is much more flexible.
+ *
+ * You should connect to one or more signals in KToolBar:
+ * clicked() , pressed() , released() , or
+ * highlighted() and if the button is a toggle button
+ * ( setToggle() ) toggled() . Those signals have @p id
+ * of a button that caused the signal. If you want to bind a popup
+ * to button, see setButton().
+ *
+ * @param pixmap The active pixmap
+ * @param id The id of this button
+ * @param enabled Enable or disable the button at startup
+ * @param text The tooltip or toolbar text (depending on state)
+ * @param index The position of the button. (-1 = at end).
+ *
+ * @return The item index.
+ */
+ int insertButton(const QPixmap& pixmap, int id, bool enabled = true,
+ const QString& text = QString::null, int index=-1 );
+
+ /**
+ * This is the same as above, but with specified signals and
+ * slots to which this button will be connected.
+ *
+ * You can add more signals with addConnection().
+ *
+ * @param pixmap The name of the icon to use as the active pixmap
+ * @param id The id of this button
+ * @param signal The signal to connect to
+ * @param receiver The slot's parent
+ * @param slot The slot to receive the signal specified in that argument.
+ * @param enabled Enable or disable the button at startup
+ * @param text The tooltip or toolbar text (depending on state)
+ * @param index The position of the button. (-1 = at end).
+ *
+ * @return The item index.
+ */
+ int insertButton(const QPixmap& pixmap, int id, const char *signal,
+ const QObject *receiver, const char *slot,
+ bool enabled = true, const QString& text = QString::null,
+ int index=-1 );
+
+ /**
+ * Inserts a button with popupmenu.
+ *
+ * Button will have small
+ * triangle. You have to connect to popup's signals. The
+ * signals KButton::pressed(), KButton::released(),
+ * KButton::clicked() or KButton::doubleClicked() are @p not
+ * emmited by
+ * this button (see setDelayedPopup() for that).
+ * You can add custom popups which inherit QPopupMenu to get popups
+ * with tables, drawings etc. Just don't fiddle with events there.
+ */
+ int insertButton(const QString& icon, int id, QPopupMenu *popup,
+ bool enabled, const QString&_text, int index=-1);
+
+ /**
+ * Inserts a button with popupmenu.
+ *
+ * Button will have small
+ * triangle. You have to connect to popup's signals. The
+ * signals KButton::pressed(), KButton::released(),
+ * KButton::clicked() or KButton::doubleClicked() are @p not
+ * emmited by
+ * this button (see setDelayedPopup() for that).
+ * You can add custom popups which inherit QPopupMenu to get popups
+ * with tables, drawings etc. Just don't fiddle with events there.
+ */
+ int insertButton(const QPixmap& pixmap, int id, QPopupMenu *popup,
+ bool enabled, const QString&_text, int index=-1);
+
+ /**
+ * Inserts a KLineEdit. You have to specify signals and slots to
+ * which KLineEdit will be connected. KLineEdit has all slots QLineEdit
+ * has, plus signals KLineEdit::completion and KLineEdit::textRotation
+ * KLineEdit can be set to autoresize itself to full free width
+ * in toolbar, that is to last right aligned item. For that,
+ * toolbar must be set to full width (which it is by default).
+ * @see setFullWidth()
+ * @see setItemAutoSized()
+ * @see KLineEdit
+ * @return Item index.
+ */
+ int insertLined (const QString& text, int id,
+ const char *signal,
+ const QObject *receiver, const char *slot,
+ bool enabled = true,
+ const QString& toolTipText = QString::null,
+ int size = 70, int index =-1);
+
+ /**
+ * Inserts a KComboBox with list.
+ *
+ * Can be writable, but cannot contain
+ * pixmaps. By default inserting policy is AtBottom, i.e. typed items
+ * are placed at the bottom of the list. Can be autosized. If the size
+ * argument is specified as -1, the width of the combobox is automatically
+ * computed.
+ *
+ * @see setFullWidth()
+ * @see setItemAutoSized()
+ * @see KComboBox
+ * @return Item index.
+ */
+ int insertCombo (const QStringList &list, int id, bool writable,
+ const char *signal, const QObject *receiver,
+ const char *slot, bool enabled=true,
+ const QString& tooltiptext=QString::null,
+ int size=70, int index=-1,
+ QComboBox::Policy policy = QComboBox::AtBottom);
+
+ /**
+ * Insert a KComboBox with text.
+ *
+ * The rest is the same as above.
+ * @see setItemAutoSized()
+ *
+ * @see KComboBox
+ * @return Item index.
+ */
+ int insertCombo (const QString& text, int id, bool writable,
+ const char *signal, QObject *receiver,
+ const char *slot, bool enabled=true,
+ const QString& tooltiptext=QString::null,
+ int size=70, int index=-1,
+ QComboBox::Policy policy = QComboBox::AtBottom);
+
+ /**
+ * Inserts a separator into the toolbar with the given @p id.
+ * @return the separator's index
+ */
+ int insertSeparator( int index = -1, int id = -1 );
+
+ /**
+ * Inserts a line separator into the toolbar with the given @p id.
+ * @return the separator's index
+ */
+ int insertLineSeparator( int index = -1, int id = -1 );
+
+ /**
+ * Inserts a user-defined widget. The widget @p must have this
+ * toolbar as its parent.
+ *
+ * Widget must have a QWidget for base class. Widget can be
+ * autosized to full width. If you forget about it, you can get a
+ * pointer to this widget with getWidget().
+ * @see setItemAutoSized()
+ * @return Item index.
+ */
+ int insertWidget(int id, int width, QWidget *_widget, int index=-1);
+
+ /**
+ * Inserts an animated widget. A KAnimWidget will be created
+ * internally using the icon name you provide.
+ * This will emit a signal (clicked()) whenever the
+ * animation widget is clicked.
+ *
+ * @see animatedWidget()
+ *
+ * @param id The id for this toolbar item
+ * @param receiver The parent of your slot
+ * @param slot The slot to receive the clicked() signal
+ * @param icons The name of the animation icon group to use
+ * @param index The item index
+ *
+ * @return The item index
+ */
+ int insertAnimatedWidget(int id, QObject *receiver, const char *slot,
+ const QString& icons, int index = -1);
+
+ /**
+ * This will return a pointer to the animated widget with the
+ * given @p id, if it exists.
+ *
+ * @see insertAnimatedWidget
+ * @param id The id for the widget you want to get a pointer to
+ * @return A pointer to the current animated widget or 0L
+ */
+ KAnimWidget *animatedWidget( int id );
+
+ /**
+ * Adds connections to items.
+ *
+ * It is important that you
+ * know the @p id of particular item. Nothing happens if you forget @p id.
+ */
+ void addConnection (int id, const char *signal,
+ const QObject *receiver, const char *slot);
+ /**
+ * Enables/disables item.
+ */
+ void setItemEnabled( int id, bool enabled );
+
+ /**
+ * Sets the icon for a button.
+ *
+ * Can be used while button is visible.
+ */
+ void setButtonIcon( int id, const QString& _icon );
+
+ /**
+ * Sets button pixmap.
+ *
+ * Can be used while button is visible.
+ */
+ void setButtonPixmap( int id, const QPixmap& _pixmap );
+
+ /**
+ * Sets a button icon from a QIconSet.
+ *
+ * Can be used while button is visible.
+ */
+ void setButtonIconSet( int id, const QIconSet& iconset );
+
+ /**
+ * Sets a delayed popup for a button.
+ *
+ * Delayed popup is what you see in
+ * Netscape Navigator's Previous and Next buttons: If you click them you
+ * go back
+ * or forth. If you press them long enough, you get a history-menu.
+ * This is exactly what we do here.
+ *
+ * You will insert a normal button with connection (or use signals from
+ * toolbar):
+ * \code
+ * bar->insertButton(icon, id, SIGNAL(clicked ()), this,
+ * SLOT (slotClick()), true, "click or wait for popup");
+ * \endcode
+ * And then add a delayed popup:
+ * \code
+ * bar->setDelayedPopup (id, historyPopup);
+ * \endcode
+ *
+ * Don't add delayed popups to buttons which have normal popups.
+ *
+ * You may add popups which are derived from QPopupMenu. You may
+ * add popups that are already in the menu bar or are submenus of
+ * other popups.
+ */
+ void setDelayedPopup (int id , QPopupMenu *_popup, bool toggle = false);
+
+ /**
+ * Turns a button into an autorepeat button.
+ *
+ * Toggle buttons, buttons with menus, or
+ * buttons with delayed menus cannot be made into autorepeat buttons.
+ * Moreover, you can and will receive
+ * only the signal clicked(), but not pressed() or released().
+ * When the user presses this button, you will receive the signal clicked(),
+ * and if the button is still pressed after some time,
+ * you will receive more clicked() signals separated by regular
+ * intervals. Since this uses QButton::setAutoRepeat() ,
+ * I can't quantify 'some'.
+ */
+ void setAutoRepeat (int id, bool flag=true);
+
+
+ /**
+ * Turns button into a toggle button if @p flag is true.
+ */
+ void setToggle (int id, bool flag = true);
+
+ /**
+ * Toggles a togglebutton.
+ *
+ * If the button is a toggle button (see setToggle())
+ * the button state will be toggled. This will also cause the toolbar to
+ * emit the signal KButton::toggled() with parameter @p id. You must connect to
+ * this signal, or use addConnection() to connect directly to the
+ * button signal KButton::toggled().
+ */
+ void toggleButton (int id);
+
+ /**
+ * Sets a toggle button state.
+ *
+ * If the button is a toggle button (see setToggle())
+ * this will set its state flag. This will also emit the signal
+ * KButton::toggled().
+ *
+ * @see setToggle()
+ */
+ void setButton (int id, bool flag);
+
+ /**
+ * Returns @p true if button is on and is a toggle button
+ * @return @p true if button is on and is a toggle button
+ * @see setToggle()
+ */
+ bool isButtonOn (int id) const;
+
+ /**
+ * Sets the text of a line editor.
+ *
+ * Cursor is set at end of text.
+ */
+ void setLinedText (int id, const QString& text);
+
+ /**
+ * Returns the line editor text.
+ * @return the line editor text.
+ */
+ QString getLinedText (int id) const;
+
+ /**
+ * Inserts @p text in combobox @p id at position @p index.
+ */
+ void insertComboItem (int id, const QString& text, int index);
+
+ /**
+ * Inserts @p list in combobox @p id at position @p index.
+ */
+ void insertComboList (int id, const QStringList &list, int index);
+
+ /**
+ * Removes item @p index from combobox @p id.
+ */
+ void removeComboItem (int id, int index);
+
+ /**
+ * Sets item @p index to be current item in combobox @p id.
+ */
+ void setCurrentComboItem (int id, int index);
+
+ /**
+ * Changes item @p index in combobox @p id to text.
+ *
+ * @p index = -1 refers current item (one displayed in the button).
+ */
+ void changeComboItem (int id, const QString& text, int index=-1);
+
+ /**
+ * Clears the combobox @p id.
+ *
+ * Does not delete it or hide it.
+ */
+ void clearCombo (int id);
+
+ /**
+ * Returns text of item @p index from combobox @p id.
+ * @return text of item @p index from combobox @p id.
+ *
+ * @p index = -1 refers to current item.
+ */
+
+ QString getComboItem (int id, int index=-1) const;
+
+ /**
+ * Returns a pointer to the combobox with @p id.
+ * @return a pointer to the combobox with @p id.
+ *
+ * Example:
+ * \code
+ * KComboBox *combo = toolbar->getCombo(combo_id);
+ * \endcode
+ * That way you can get access to other public methods
+ * that KComboBox provides.
+ */
+ KComboBox * getCombo(int id);
+
+ /**
+ * Returns a pointer to KToolBarLined with @p id.
+ * @return a pointer to KToolBarLined with @p id.
+ *
+ * Example:
+ * \code
+ * KLineEdit * lined = toolbar->getKToolBarLined(lined_id);
+ * \endcode
+ * That way you can get access to other public methods
+ * that KLineEdit provides. KLineEdit is the same thing
+ * as QLineEdit plus completion signals.
+ */
+ KLineEdit * getLined (int id);
+
+ /**
+ * Returns a pointer to KToolBarButton.
+ *
+ * Example:
+ * \code
+ * KToolBarButton * button = toolbar->getButton(button_id);
+ * \endcode
+ * That way you can get access to other public methods
+ * that KToolBarButton provides.
+ *
+ * Using this method is not recommended.
+ */
+ KToolBarButton * getButton (int id);
+
+ /**
+ * Align item to the right.
+ *
+ * This works only if toolbar is set to full width.
+ * @see setFullWidth()
+ */
+ void alignItemRight (int id, bool right = true);
+
+ /**
+ * Returns a pointer to the widget corresponding to @p id.
+ * @return a pointer to the widget corresponding to @p id.
+ *
+ * Wrong ids are not tested.
+ * You can do with this whatever you want,
+ * except change its height (hardcoded). If you change its width
+ * you will probably have to call QToolBar::updateRects(true)
+ * @see QWidget
+ * @see updateRects()
+ */
+ QWidget *getWidget (int id); // ### KDE4: make this const!
+
+ /**
+ * Set item autosized.
+ *
+ * This works only if the toolbar is set to full width.
+ * Only @p one item can be autosized, and it has to be
+ * the last left-aligned item. Items that come after this must be right
+ * aligned. Items that can be right aligned are Lineds, Frames, Widgets and
+ * Combos. An autosized item will resize itself whenever the toolbar geometry
+ * changes to the last right-aligned item (or to end of toolbar if there
+ * are no right-aligned items.)
+ * @see setFullWidth()
+ * @see alignItemRight()
+ */
+ void setItemAutoSized (int id, bool yes = true);
+
+ /**
+ * Remove all items.
+ *
+ * The toolbar is redrawn after it.
+ */
+ void clear ();
+
+ /**
+ * Remove item @p id.
+ *
+ * Item is deleted. Toolbar is redrawn after it.
+ */
+ void removeItem (int id);
+
+ /**
+ * Remove item @p id.
+ *
+ * Item is deleted when toolbar is redrawn.
+ */
+ void removeItemDelayed (int id);
+
+ /**
+ * Hide item @p id.
+ */
+ void hideItem (int id);
+
+ /**
+ * Show item @p id.
+ */
+ void showItem (int id);
+
+ /**
+ * Returns the index of the item @p id.
+ * @return the index of the item @p id.
+ * @since 3.2
+ */
+ int itemIndex (int id); // ### KDE4: make this const!
+
+ /**
+ * Returns the id of the item at the given index.
+ * @since 3.2
+ */
+ int idAt(int index); // ### KDE4: make this const!
+
+ /**
+ * Set toolbar to full parent size (default).
+ *
+ * In full size mode the bar extends over the parent's full width or height.
+ * If the mode is disabled the toolbar tries to take as much space as it
+ * needs without wrapping, but it does not exceed the parent box. You can
+ * force a certain width or height with setMaxWidth() or
+ * setMaxHeight().
+ *
+ * If you want to use right-aligned items or auto-sized items you must use
+ * full size mode.
+ */
+ void setFullSize(bool flag = true);
+
+ /**
+ * Returns the full-size mode enabled flag.
+ * @return @p true if the full-size mode is enabled.
+ */
+ bool fullSize() const;
+
+ /**
+ * Enable or disable moving of toolbar.
+ * @deprecated use setMovingEnabled(bool) instead.
+ */
+ void enableMoving(bool flag = true) KDE_DEPRECATED;
+
+ /**
+ * Set position of toolbar.
+ * @see BarPosition()
+ */
+ void setBarPos (BarPosition bpos);
+
+ /**
+ * Returns the toolbar position.
+ * @return position of toolbar.
+ */
+ BarPosition barPos() const;
+
+ /**
+ * Show, hide, or toggle toolbar.
+ *
+ * This method is provided for compatibility only,
+ * please use show() and/or hide() instead.
+ * @see BarStatus
+ * @deprecated
+ */
+ bool enable(BarStatus stat) KDE_DEPRECATED;
+
+ /**
+ * Use setMaximumHeight() instead.
+ * @deprecated
+ */
+ void setMaxHeight (int h) KDE_DEPRECATED; // Set max height for vertical toolbars
+
+ /**
+ * Returns the value set with setMaxHeight().
+ * @deprecated
+ * Use maximumHeight() instead.
+ * @return the value set with setMaxHeight().
+ */
+ int maxHeight() KDE_DEPRECATED;
+
+ /**
+ * Use setMaximumWidth() instead.
+ * Set maximal width of horizontal (top or bottom) toolbar.
+ * @deprecated
+ */
+ void setMaxWidth (int dw) KDE_DEPRECATED;
+
+ /**
+ * Returns the value set with setMaxWidth().
+ * Use maximumWidth() instead.
+ * @return the value set with setMaxWidth().
+ * @deprecated
+ */
+ int maxWidth() KDE_DEPRECATED;
+
+ /**
+ * Set title for toolbar when it floats.
+ *
+ * Titles are however not (yet)
+ * visible. You can't change toolbar's title while it's floating.
+ */
+ void setTitle (const QString& _title);
+
+ /**
+ * Use setMovingEnabled(bool) instead.
+ * @deprecated
+ */
+ void enableFloating (bool flag) KDE_DEPRECATED;
+
+ /**
+ * Set the kind of painting for buttons.
+ *
+ * Choose from:
+ * @li IconOnly (only icons),
+ * @li IconTextRight (icon and text, text is left from icons),
+ * @li TextOnly (only text),
+ * @li IconTextBottom (icons and text, text is under icons).
+ * @see IconText
+ *
+ */
+ void setIconText(IconText it);
+ // Note: don't merge with the next one, it breaks Qt properties
+
+ /**
+ * Similar to setIconText(IconText it) but allows you to
+ * disable or enable updating. If @p update is false, then the
+ * buttons will not be updated. This is useful only if you know
+ * that you will be forcing an update later.
+ */
+ void setIconText(IconText it, bool update);
+
+ /**
+ * Returns the current text style for buttons.
+ * @return the current text style for buttons.
+ */
+ IconText iconText() const;
+
+ /**
+ * Set the icon size to load. Usually you should not call
+ * this, the icon size is taken care of by KIconLoader
+ * and globally configured.
+ * By default, the toolbar will load icons of size 32 for main
+ * toolbars and 22 for other toolbars
+ * @see KIconLoader.
+ *
+ * @param size The size to use
+ */
+ void setIconSize(int size);
+ // Note: don't merge with the next one, it breaks Qt properties
+
+ /**
+ * Same as setIconText(int size) but allows you
+ * to disable the toolbar update.
+ *
+ * @param size The size to use
+ * @param update If true, then the toolbar will be updated after
+ * this
+ */
+ void setIconSize(int size, bool update);
+
+ /**
+ * Returns the current icon size for buttons.
+ * @return the current icon size for buttons.
+ */
+ int iconSize() const;
+
+ /**
+ * Returns the default size for this type of toolbar.
+ * @return the default size for this type of toolbar.
+ */
+ int iconSizeDefault() const;
+
+ /**
+ * This allows you to enable or disable the context menu.
+ *
+ * @param enable If false, then the context menu will be disabled
+ */
+ void setEnableContextMenu(bool enable = true);
+
+ /**
+ * Returns the context menu enabled flag
+ * @return true if the context menu is disabled
+ */
+ bool contextMenuEnabled() const;
+
+ /**
+ * This will inform a toolbar button to ignore certain style
+ * changes. Specifically, it will ignore IconText (always IconOnly)
+ * and will not allow image effects to apply.
+ *
+ * @param id The button to exclude from styles
+ * @param no_style If true, then it is excluded (default: true).
+ */
+ void setItemNoStyle(int id, bool no_style = true);
+
+ void setFlat (bool flag);
+
+ /**
+ * Returns the total number of items in the toolbar
+ * @return the total number of items in the toolbar
+ */
+ int count() const;
+
+ /**
+ * Instruct the toolbar to save it's current state to either the app
+ * config file or to the XML-GUI resource file (whichever has
+ * precedence).
+ */
+ void saveState(); // BIC: remove for KDE4? This doesn't appear to be used internally,
+ // and apps use saveMainWindowSettings in KMainWindow anyway.
+
+ /**
+ * Save the toolbar settings to group @p configGroup in @p config.
+ */
+ void saveSettings(KConfig *config, const QString &configGroup);
+
+ /**
+ * Read the toolbar settings from group @p configGroup in @p config
+ * and apply them. Even default settings are re-applied if @p force is set.
+ */
+ void applySettings(KConfig *config, const QString &configGroup,bool force);
+ // KDE4 merge with force=false
+ void applySettings(KConfig *config, const QString &configGroup);
+
+ /*
+ * Tell the toolbar what XML-GUI resource file it should use to save
+ * it's state. The state of the toolbar (position, size, etc) is
+ * saved in KConfig files if the application does not use XML-GUI
+ * but if the app does, then it's saved the XML file. This function
+ * allows this to happen.
+ *
+ * @param xmlfile The XML-GUI resource file to write to
+ * @param xml The DOM document for the XML-GUI building
+ * @internal
+ */
+ // void setXML(const QString& xmlfile, const QDomDocument& xml);
+
+ void setXMLGUIClient( KXMLGUIClient *client );
+
+ /**
+ * Assign a (translated) text to this toolbar. This is used
+ * for the tooltip on the handle, and when listing the toolbars.
+ */
+ void setText( const QString & txt );
+
+ /**
+ * Returns the toolbar's text.
+ * @return the toolbar's text.
+ */
+ QString text() const;
+
+ void setStretchableWidget( QWidget *w );
+ QSizePolicy sizePolicy() const;
+ bool highlight() const;
+ QSize sizeHint() const;
+ QSize minimumSizeHint() const;
+ QSize minimumSize() const;
+
+ void hide();
+ void show();
+
+ void updateRects( bool = false ) {}
+
+ /**
+ * Load state from an XML element, called by KXMLGUIBuilder
+ */
+ void loadState( const QDomElement &e );
+ /*
+ * Save state into an XML element, called by KXMLGUIBuilder
+ */
+ void saveState( QDomElement &e );
+
+ /**
+ * @internal
+ */
+ void positionYourself( bool force = false);
+
+signals:
+ /**
+ * Emitted when button @p id is clicked.
+ */
+ void clicked(int id);
+
+ /**
+ * Emitted when button @p id is double-clicked.
+ *
+ * Note: you will always
+ * recive two clicked() , pressed() and released() signals.
+ * There is no way to avoid it - at least no easy way.
+ * If you need to resolve this all you can do is set up timers
+ * which wait for QApplication::doubleClickInterval() to expire.
+ * If in that time you don't get this signal, you may belive that
+ * button was only clicked and not double-clicked.
+ * And please note that butons with popup menus do not emit this signal,
+ * but those with delayed popup do.
+ */
+ void doubleClicked (int id);
+
+ /**
+ * Emitted when button @p id is pressed.
+ */
+ void pressed(int);
+
+ /**
+ * Emits when button @p id is released.
+ */
+ void released(int);
+
+ /**
+ * Emitted when a toggle button changes state.
+ *
+ * Emitted also if you change state
+ * with setButton() or toggleButton()
+ * If you make a button normal again, with
+ * setToggle(false), this signal won't
+ * be emitted.
+ */
+ void toggled(int);
+
+ /**
+ * This signal is emitted when item @p id gets highlighted/unhighlighted
+ * (i.e when mouse enters/exits).
+ *
+ * Note that this signal is emitted from
+ * all buttons (normal, disabled and toggle) even when there is no visible
+ * change in buttons (i.e., buttons do not raise when mouse enters).
+ * The parameter @p isHighlighted is @p true when mouse enters and @p false when
+ * mouse exits.
+ */
+ void highlighted(int id, bool isHighlighted);
+
+ /**
+ * This signal is emitted when item @p id gets highlighted/unhighlighted
+ * (i.e when mouse enters/exits).
+ *
+ * Note that this signal is emitted from
+ * all buttons (normal, disabled and toggle) even when there is no visible
+ * change in buttons (i.e., buttons do not raise when mouse enters).
+ */
+ void highlighted(int id );
+
+ /**
+ * Emitted when toolbar changes position, or when
+ * an item is removed from toolbar.
+ *
+ * If you subclass KMainWindow and reimplement
+ * KMainWindow::resizeEvent() be sure to connect to
+ * this signal. Note: You can connect this signal to a slot that
+ * doesn't take parameter.
+ */
+ void moved( BarPosition );
+
+ /**
+ * This signal is emitted when toolbar detects changing of
+ * following parameters:
+ * highlighting, button-size, button-mode. This signal is
+ * internal, aimed to buttons.
+ * @internal
+ */
+ void modechange ();
+
+ /**
+ * This signal is emitted when the toolbar is getting deleted,
+ * and before ~KToolbar finishes (so it's still time to remove
+ * widgets from the toolbar).
+ * Used by KWidgetAction.
+ * @since 3.2
+ */
+ void toolbarDestroyed();
+
+public:
+ /**
+ * Returns the global setting for "Highlight buttons under mouse"
+ * @return global setting for "Highlight buttons under mouse"
+ */
+ static bool highlightSetting();
+
+ /**
+ * Returns the global setting for "Toolbars transparent when moving"
+ * @return global setting for "Toolbars transparent when moving"
+ */
+ static bool transparentSetting();
+
+ /**
+ * Returns the global setting for "Icon Text"
+ * @return global setting for "Icon Text"
+ */
+ static IconText iconTextSetting();
+
+public slots:
+ virtual void setIconText( const QString &txt )
+ { QToolBar::setIconText( txt ); }
+
+protected:
+ void mousePressEvent( QMouseEvent * );
+ void childEvent( QChildEvent *e );
+ void showEvent( QShowEvent *e );
+ void resizeEvent( QResizeEvent *e );
+ bool event( QEvent *e );
+ void applyAppearanceSettings(KConfig *config, const QString &_configGroup, bool forceGlobal = false);
+ QString settingsGroup() const;
+
+private slots:
+ void rebuildLayout();
+ void slotReadConfig ();
+ void slotAppearanceChanged();
+ void slotIconChanged(int);
+ void slotRepaint();
+ void toolBarPosChanged( QToolBar *tb );
+ void slotContextAboutToShow();
+ void slotContextAboutToHide();
+ void widgetDestroyed();
+
+private:
+ void init( bool readConfig = true, bool honorStyle = false );
+ void doConnections( KToolBarButton *button );
+ void insertWidgetInternal( QWidget *w, int &index, int id );
+ void removeWidgetInternal( QWidget *w );
+ void getAttributes( QString &position, QString &icontext, int &index );
+ int dockWindowIndex();
+ KPopupMenu *contextMenu();
+ void doModeChange();
+
+ QMap<QWidget*, int > widget2id;
+ typedef QMap<int, QWidget* > Id2WidgetMap;
+ Id2WidgetMap id2widget;
+ KPopupMenu *context;
+ QPtrList<QWidget> widgets;
+ QTimer *layoutTimer;
+ QGuardedPtr<QWidget> stretchableWidget, rightAligned;
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KToolBarPrivate *d;
+};
+
+#endif
diff --git a/kdeui/ktoolbarbutton.cpp b/kdeui/ktoolbarbutton.cpp
new file mode 100644
index 000000000..919bfbe70
--- /dev/null
+++ b/kdeui/ktoolbarbutton.cpp
@@ -0,0 +1,781 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997, 1998 Stephan Kulow (coolo@kde.org)
+ (C) 1997, 1998 Mark Donohoe (donohoe@kde.org)
+ (C) 1997, 1998 Sven Radej (radej@kde.org)
+ (C) 1997, 1998 Matthias Ettrich (ettrich@kde.org)
+ (C) 1999 Chris Schlaeger (cs@kde.org)
+ (C) 1999 Kurt Granroth (granroth@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config.h>
+#include <string.h>
+
+#include "ktoolbarbutton.h"
+#include "ktoolbar.h"
+
+#include <qstyle.h>
+#include <qimage.h>
+#include <qtimer.h>
+#include <qdrawutil.h>
+#include <qtooltip.h>
+#include <qbitmap.h>
+#include <qpopupmenu.h>
+#include <qcursor.h>
+#include <qpainter.h>
+#include <qlayout.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+#include <kiconeffect.h>
+#include <kiconloader.h>
+
+// needed to get our instance
+#include <kmainwindow.h>
+
+template class QIntDict<KToolBarButton>;
+
+class KToolBarButtonPrivate
+{
+public:
+ KToolBarButtonPrivate()
+ {
+ m_buttonDown = false;
+
+ m_noStyle = false;
+ m_isSeparator = false;
+ m_isRadio = false;
+ m_highlight = false;
+ m_isRaised = false;
+ m_isActive = false;
+
+ m_iconName = QString::null;
+ m_iconText = KToolBar::IconOnly;
+ m_iconSize = 0;
+
+ m_parent = 0;
+ m_instance = KGlobal::instance();
+ }
+ ~KToolBarButtonPrivate()
+ {
+ }
+
+ int m_id;
+ bool m_buttonDown : 1;
+ bool m_noStyle: 1;
+ bool m_isSeparator: 1;
+ bool m_isRadio: 1;
+ bool m_highlight: 1;
+ bool m_isRaised: 1;
+ bool m_isActive: 1;
+
+ QString m_iconName;
+
+ KToolBar *m_parent;
+ KToolBar::IconText m_iconText;
+ int m_iconSize;
+ QSize size;
+
+ QPoint m_mousePressPos;
+
+ KInstance *m_instance;
+};
+
+// This will construct a separator
+KToolBarButton::KToolBarButton( QWidget *_parent, const char *_name )
+ : QToolButton( _parent , _name)
+{
+ d = new KToolBarButtonPrivate;
+
+ resize(6,6);
+ hide();
+ d->m_isSeparator = true;
+}
+
+KToolBarButton::KToolBarButton( const QString& _icon, int _id,
+ QWidget *_parent, const char *_name,
+ const QString &_txt, KInstance *_instance )
+ : QToolButton( _parent, _name ), d( 0 )
+{
+ d = new KToolBarButtonPrivate;
+
+ d->m_id = _id;
+ QToolButton::setTextLabel(_txt);
+ d->m_instance = _instance;
+
+ d->m_parent = dynamic_cast<KToolBar*>(_parent);
+ if (d->m_parent) {
+ connect(d->m_parent, SIGNAL( modechange() ),
+ this, SLOT( modeChange() ));
+ }
+
+ setFocusPolicy( NoFocus );
+
+ // connect all of our slots and start trapping events
+ connect(this, SIGNAL( clicked() ),
+ this, SLOT( slotClicked() ) );
+ connect(this, SIGNAL( pressed() ),
+ this, SLOT( slotPressed() ) );
+ connect(this, SIGNAL( released() ),
+ this, SLOT( slotReleased() ) );
+ installEventFilter(this);
+
+ d->m_iconName = _icon;
+
+ // do our initial setup
+ modeChange();
+}
+
+KToolBarButton::KToolBarButton( const QPixmap& pixmap, int _id,
+ QWidget *_parent, const char *name,
+ const QString& txt)
+ : QToolButton( _parent, name ), d( 0 )
+{
+ d = new KToolBarButtonPrivate;
+
+ d->m_id = _id;
+ QToolButton::setTextLabel(txt);
+
+ d->m_parent = dynamic_cast<KToolBar*>(_parent);
+ if (d->m_parent) {
+ connect(d->m_parent, SIGNAL( modechange() ),
+ this, SLOT( modeChange() ));
+ }
+
+ setFocusPolicy( NoFocus );
+
+ // connect all of our slots and start trapping events
+ connect(this, SIGNAL( clicked() ),
+ this, SLOT( slotClicked() ));
+ connect(this, SIGNAL( pressed() ),
+ this, SLOT( slotPressed() ));
+ connect(this, SIGNAL( released() ),
+ this, SLOT( slotReleased() ));
+ installEventFilter(this);
+
+ // set our pixmap and do our initial setup
+ setIconSet( QIconSet( pixmap ));
+ modeChange();
+}
+
+KToolBarButton::~KToolBarButton()
+{
+ delete d; d = 0;
+}
+
+void KToolBarButton::modeChange()
+{
+ QSize mysize;
+
+ // grab a few global variables for use in this function and others
+ if (d->m_parent) {
+ d->m_highlight = d->m_parent->highlight();
+ d->m_iconText = d->m_parent->iconText();
+
+ d->m_iconSize = d->m_parent->iconSize();
+ }
+ if (!d->m_iconName.isNull())
+ setIcon(d->m_iconName);
+
+ // we'll start with the size of our pixmap
+ int pix_width = d->m_iconSize;
+ if ( d->m_iconSize == 0 ) {
+ if (d->m_parent && !strcmp(d->m_parent->name(), "mainToolBar"))
+ pix_width = IconSize( KIcon::MainToolbar );
+ else
+ pix_width = IconSize( KIcon::Toolbar );
+ }
+ int pix_height = pix_width;
+
+ int text_height = 0;
+ int text_width = 0;
+
+ QToolTip::remove(this);
+ if (d->m_iconText != KToolBar::IconOnly)
+ {
+ // okay, we have to deal with fonts. let's get our information now
+ QFont tmp_font = KGlobalSettings::toolBarFont();
+
+ // now parse out our font sizes from our chosen font
+ QFontMetrics fm(tmp_font);
+
+ text_height = fm.lineSpacing();
+ text_width = fm.width(textLabel());
+
+ // none of the other modes want tooltips
+ }
+ else
+ {
+ QToolTip::add(this, textLabel());
+ }
+
+ switch (d->m_iconText)
+ {
+ case KToolBar::IconOnly:
+ mysize = QSize(pix_width, pix_height);
+ break;
+
+ case KToolBar::IconTextRight:
+ mysize = QSize(pix_width + text_width + 4, pix_height);
+ break;
+
+ case KToolBar::TextOnly:
+ mysize = QSize(text_width + 4, text_height);
+ break;
+
+ case KToolBar::IconTextBottom:
+ mysize = QSize((text_width + 4 > pix_width) ? text_width + 4 : pix_width, pix_height + text_height);
+ break;
+
+ default:
+ break;
+ }
+
+ mysize = style().sizeFromContents(QStyle::CT_ToolButton, this, mysize).
+ expandedTo(QApplication::globalStrut());
+
+ // make sure that this isn't taller then it is wide
+ if (mysize.height() > mysize.width())
+ mysize.setWidth(mysize.height());
+
+ d->size = mysize;
+ updateGeometry();
+}
+
+void KToolBarButton::setTextLabel( const QString& text, bool tipToo)
+{
+ if (text.isNull())
+ return;
+
+ QString txt(text);
+ if (txt.endsWith(QString::fromLatin1("...")))
+ txt.truncate(txt.length() - 3);
+
+ QToolButton::setTextLabel(txt, tipToo);
+ update();
+}
+
+void KToolBarButton::setText( const QString& text)
+{
+ setTextLabel(text, true);
+ modeChange();
+}
+
+void KToolBarButton::setIcon( const QString &icon )
+{
+ d->m_iconName = icon;
+ if (d->m_parent)
+ d->m_iconSize = d->m_parent->iconSize();
+ // QObject::name() return "const char *" instead of QString.
+ if (d->m_parent && !strcmp(d->m_parent->name(), "mainToolBar"))
+ QToolButton::setIconSet( d->m_instance->iconLoader()->loadIconSet(
+ d->m_iconName, KIcon::MainToolbar, d->m_iconSize ));
+ else
+ QToolButton::setIconSet( d->m_instance->iconLoader()->loadIconSet(
+ d->m_iconName, KIcon::Toolbar, d->m_iconSize ));
+}
+
+void KToolBarButton::setIconSet( const QIconSet &iconset )
+{
+ QToolButton::setIconSet( iconset );
+}
+
+// remove?
+void KToolBarButton::setPixmap( const QPixmap &pixmap )
+{
+ if( pixmap.isNull()) // called by QToolButton
+ {
+ QToolButton::setPixmap( pixmap );
+ return;
+ }
+ QIconSet set = iconSet();
+ set.setPixmap( pixmap, QIconSet::Automatic, QIconSet::Active );
+ QToolButton::setIconSet( set );
+}
+
+void KToolBarButton::setDefaultPixmap( const QPixmap &pixmap )
+{
+ QIconSet set = iconSet();
+ set.setPixmap( pixmap, QIconSet::Automatic, QIconSet::Normal );
+ QToolButton::setIconSet( set );
+}
+
+void KToolBarButton::setDisabledPixmap( const QPixmap &pixmap )
+{
+ QIconSet set = iconSet();
+ set.setPixmap( pixmap, QIconSet::Automatic, QIconSet::Disabled );
+ QToolButton::setIconSet( set );
+}
+
+void KToolBarButton::setDefaultIcon( const QString& icon )
+{
+ QIconSet set = iconSet();
+ QPixmap pm;
+ if (d->m_parent && !strcmp(d->m_parent->name(), "mainToolBar"))
+ pm = d->m_instance->iconLoader()->loadIcon( icon, KIcon::MainToolbar,
+ d->m_iconSize );
+ else
+ pm = d->m_instance->iconLoader()->loadIcon( icon, KIcon::Toolbar,
+ d->m_iconSize );
+ set.setPixmap( pm, QIconSet::Automatic, QIconSet::Normal );
+ QToolButton::setIconSet( set );
+}
+
+void KToolBarButton::setDisabledIcon( const QString& icon )
+{
+ QIconSet set = iconSet();
+ QPixmap pm;
+ if (d->m_parent && !strcmp(d->m_parent->name(), "mainToolBar"))
+ pm = d->m_instance->iconLoader()->loadIcon( icon, KIcon::MainToolbar,
+ d->m_iconSize );
+ else
+ pm = d->m_instance->iconLoader()->loadIcon( icon, KIcon::Toolbar,
+ d->m_iconSize );
+ set.setPixmap( pm, QIconSet::Automatic, QIconSet::Disabled );
+ QToolButton::setIconSet( set );
+}
+
+QPopupMenu *KToolBarButton::popup()
+{
+ // obsolete
+ // KDE4: remove me
+ return QToolButton::popup();
+}
+
+void KToolBarButton::setPopup(QPopupMenu *p, bool)
+{
+ QToolButton::setPopup(p);
+ QToolButton::setPopupDelay(-1);
+}
+
+
+void KToolBarButton::setDelayedPopup (QPopupMenu *p, bool)
+{
+ QToolButton::setPopup(p);
+ QToolButton::setPopupDelay(QApplication::startDragTime());
+}
+
+void KToolBarButton::leaveEvent(QEvent *)
+{
+ if( d->m_isRaised || d->m_isActive )
+ {
+ d->m_isRaised = false;
+ d->m_isActive = false;
+ repaint(false);
+ }
+
+ emit highlighted(d->m_id, false);
+}
+
+void KToolBarButton::enterEvent(QEvent *)
+{
+ if (d->m_highlight)
+ {
+ if (isEnabled())
+ {
+ d->m_isActive = true;
+ if (!isToggleButton())
+ d->m_isRaised = true;
+ }
+ else
+ {
+ d->m_isRaised = false;
+ d->m_isActive = false;
+ }
+
+ repaint(false);
+ }
+ emit highlighted(d->m_id, true);
+}
+
+bool KToolBarButton::eventFilter(QObject *o, QEvent *ev)
+{
+ if ((KToolBarButton *)o == this)
+ {
+
+ // Popup the menu when the left mousebutton is pressed and the mouse
+ // is moved by a small distance.
+ if (QToolButton::popup())
+ {
+ if (ev->type() == QEvent::MouseButtonPress)
+ {
+ QMouseEvent* mev = static_cast<QMouseEvent*>(ev);
+ d->m_mousePressPos = mev->pos();
+ }
+ else if (ev->type() == QEvent::MouseMove)
+ {
+ QMouseEvent* mev = static_cast<QMouseEvent*>(ev);
+ if ((mev->pos() - d->m_mousePressPos).manhattanLength()
+ > KGlobalSettings::dndEventDelay())
+ {
+ openPopup();
+ return true;
+ }
+ }
+ }
+
+ if (d->m_isRadio &&
+ (ev->type() == QEvent::MouseButtonPress ||
+ ev->type() == QEvent::MouseButtonRelease ||
+ ev->type() == QEvent::MouseButtonDblClick) && isOn())
+ return true;
+
+ // From Kai-Uwe Sattler <kus@iti.CS.Uni-Magdeburg.De>
+ if (ev->type() == QEvent::MouseButtonDblClick)
+ {
+ emit doubleClicked(d->m_id);
+ return false;
+ }
+ }
+
+ return QToolButton::eventFilter(o, ev);
+}
+
+void KToolBarButton::mousePressEvent( QMouseEvent * e )
+{
+ d->m_buttonDown = true;
+
+ if ( e->button() == MidButton )
+ {
+ // Get QToolButton to show the button being down while pressed
+ QMouseEvent ev( QEvent::MouseButtonPress, e->pos(), e->globalPos(), LeftButton, e->state() );
+ QToolButton::mousePressEvent(&ev);
+ return;
+ }
+ QToolButton::mousePressEvent(e);
+}
+
+void KToolBarButton::mouseReleaseEvent( QMouseEvent * e )
+{
+ Qt::ButtonState state = Qt::ButtonState(e->button() | (e->state() & KeyButtonMask));
+ if ( e->button() == MidButton )
+ {
+ QMouseEvent ev( QEvent::MouseButtonRelease, e->pos(), e->globalPos(), LeftButton, e->state() );
+ QToolButton::mouseReleaseEvent(&ev);
+ }
+ else
+ QToolButton::mouseReleaseEvent(e);
+
+ if ( !d->m_buttonDown )
+ return;
+ d->m_buttonDown = false;
+
+ if ( hitButton( e->pos() ) )
+ emit buttonClicked( d->m_id, state );
+}
+
+void KToolBarButton::drawButton( QPainter *_painter )
+{
+ QStyle::SFlags flags = QStyle::Style_Default;
+ QStyle::SCFlags active = QStyle::SC_None;
+
+ if (isDown()) {
+ flags |= QStyle::Style_Down;
+ active |= QStyle::SC_ToolButton;
+ }
+ if (isEnabled()) flags |= QStyle::Style_Enabled;
+ if (isOn()) flags |= QStyle::Style_On;
+ if (isEnabled() && hasMouse()) flags |= QStyle::Style_Raised;
+ if (hasFocus()) flags |= QStyle::Style_HasFocus;
+
+ // Draw a styled toolbutton
+ style().drawComplexControl(QStyle::CC_ToolButton, _painter, this, rect(),
+ colorGroup(), flags, QStyle::SC_ToolButton, active, QStyleOption());
+
+ int dx, dy;
+ QFont tmp_font(KGlobalSettings::toolBarFont());
+ QFontMetrics fm(tmp_font);
+ QRect textRect;
+ int textFlags = 0;
+
+ if (d->m_iconText == KToolBar::IconOnly) // icon only
+ {
+ QPixmap pixmap = iconSet().pixmap( QIconSet::Automatic,
+ isEnabled() ? (d->m_isActive ? QIconSet::Active : QIconSet::Normal) :
+ QIconSet::Disabled,
+ isOn() ? QIconSet::On : QIconSet::Off );
+ if( !pixmap.isNull())
+ {
+ dx = ( width() - pixmap.width() ) / 2;
+ dy = ( height() - pixmap.height() ) / 2;
+ if ( isDown() && style().styleHint(QStyle::SH_GUIStyle) == WindowsStyle )
+ {
+ ++dx;
+ ++dy;
+ }
+ _painter->drawPixmap( dx, dy, pixmap );
+ }
+ }
+ else if (d->m_iconText == KToolBar::IconTextRight) // icon and text (if any)
+ {
+ QPixmap pixmap = iconSet().pixmap( QIconSet::Automatic,
+ isEnabled() ? (d->m_isActive ? QIconSet::Active : QIconSet::Normal) :
+ QIconSet::Disabled,
+ isOn() ? QIconSet::On : QIconSet::Off );
+ if( !pixmap.isNull())
+ {
+ dx = 4;
+ dy = ( height() - pixmap.height() ) / 2;
+ if ( isDown() && style().styleHint(QStyle::SH_GUIStyle) == WindowsStyle )
+ {
+ ++dx;
+ ++dy;
+ }
+ _painter->drawPixmap( dx, dy, pixmap );
+ }
+
+ if (!textLabel().isNull())
+ {
+ textFlags = AlignVCenter|AlignLeft;
+ if (!pixmap.isNull())
+ dx = 4 + pixmap.width() + 2;
+ else
+ dx = 4;
+ dy = 0;
+ if ( isDown() && style().styleHint(QStyle::SH_GUIStyle) == WindowsStyle )
+ {
+ ++dx;
+ ++dy;
+ }
+ textRect = QRect(dx, dy, width()-dx, height());
+ }
+ }
+ else if (d->m_iconText == KToolBar::TextOnly)
+ {
+ if (!textLabel().isNull())
+ {
+ textFlags = AlignVCenter|AlignLeft;
+ dx = (width() - fm.width(textLabel())) / 2;
+ dy = (height() - fm.lineSpacing()) / 2;
+ if ( isDown() && style().styleHint(QStyle::SH_GUIStyle) == WindowsStyle )
+ {
+ ++dx;
+ ++dy;
+ }
+ textRect = QRect( dx, dy, fm.width(textLabel()), fm.lineSpacing() );
+ }
+ }
+ else if (d->m_iconText == KToolBar::IconTextBottom)
+ {
+ QPixmap pixmap = iconSet().pixmap( QIconSet::Automatic,
+ isEnabled() ? (d->m_isActive ? QIconSet::Active : QIconSet::Normal) :
+ QIconSet::Disabled,
+ isOn() ? QIconSet::On : QIconSet::Off );
+ if( !pixmap.isNull())
+ {
+ dx = (width() - pixmap.width()) / 2;
+ dy = (height() - fm.lineSpacing() - pixmap.height()) / 2;
+ if ( isDown() && style().styleHint(QStyle::SH_GUIStyle) == WindowsStyle )
+ {
+ ++dx;
+ ++dy;
+ }
+ _painter->drawPixmap( dx, dy, pixmap );
+ }
+
+ if (!textLabel().isNull())
+ {
+ textFlags = AlignBottom|AlignHCenter;
+ dx = (width() - fm.width(textLabel())) / 2;
+ dy = height() - fm.lineSpacing() - 4;
+
+ if ( isDown() && style().styleHint(QStyle::SH_GUIStyle) == WindowsStyle )
+ {
+ ++dx;
+ ++dy;
+ }
+ textRect = QRect( dx, dy, fm.width(textLabel()), fm.lineSpacing() );
+ }
+ }
+
+ // Draw the text at the position given by textRect, and using textFlags
+ if (!textLabel().isNull() && !textRect.isNull())
+ {
+ _painter->setFont(KGlobalSettings::toolBarFont());
+ if (!isEnabled())
+ _painter->setPen(palette().disabled().dark());
+ else if(d->m_isRaised)
+ _painter->setPen(KGlobalSettings::toolBarHighlightColor());
+ else
+ _painter->setPen( colorGroup().buttonText() );
+ _painter->drawText(textRect, textFlags, textLabel());
+ }
+
+ if (QToolButton::popup())
+ {
+ QStyle::SFlags arrowFlags = QStyle::Style_Default;
+
+ if (isDown()) arrowFlags |= QStyle::Style_Down;
+ if (isEnabled()) arrowFlags |= QStyle::Style_Enabled;
+
+ style().drawPrimitive(QStyle::PE_ArrowDown, _painter,
+ QRect(width()-7, height()-7, 7, 7), colorGroup(),
+ arrowFlags, QStyleOption() );
+ }
+}
+
+void KToolBarButton::paletteChange(const QPalette &)
+{
+ if(!d->m_isSeparator)
+ {
+ modeChange();
+ repaint(false); // no need to delete it first therefore only false
+ }
+}
+
+bool KToolBarButton::event(QEvent *e)
+{
+ if (e->type() == QEvent::ParentFontChange || e->type() == QEvent::ApplicationFontChange)
+ {
+ //If we use toolbar text, apply the settings again, to relayout...
+ if (d->m_iconText != KToolBar::IconOnly)
+ modeChange();
+ return true;
+ }
+
+ return QToolButton::event(e);
+}
+
+
+void KToolBarButton::showMenu()
+{
+ // obsolete
+ // KDE4: remove me
+}
+
+void KToolBarButton::slotDelayTimeout()
+{
+ // obsolete
+ // KDE4: remove me
+}
+
+void KToolBarButton::slotClicked()
+{
+ emit clicked( d->m_id );
+
+ // emit buttonClicked when the button was clicked while being in an extension popupmenu
+ if ( d->m_parent && !d->m_parent->rect().contains( geometry().center() ) ) {
+ ButtonState state = KApplication::keyboardMouseState();
+ if ( ( state & MouseButtonMask ) == NoButton )
+ state = ButtonState( LeftButton | state );
+ emit buttonClicked( d->m_id, state ); // Doesn't work with MidButton
+ }
+}
+
+void KToolBarButton::slotPressed()
+{
+ emit pressed( d->m_id );
+}
+
+void KToolBarButton::slotReleased()
+{
+ emit released( d->m_id );
+}
+
+void KToolBarButton::slotToggled()
+{
+ emit toggled( d->m_id );
+}
+
+void KToolBarButton::setNoStyle(bool no_style)
+{
+ d->m_noStyle = no_style;
+
+ modeChange();
+ d->m_iconText = KToolBar::IconTextRight;
+ repaint(false);
+}
+
+void KToolBarButton::setRadio (bool f)
+{
+ if ( d )
+ d->m_isRadio = f;
+}
+
+void KToolBarButton::on(bool flag)
+{
+ if(isToggleButton())
+ setOn(flag);
+ else
+ {
+ setDown(flag);
+ leaveEvent((QEvent *) 0);
+ }
+ repaint();
+}
+
+void KToolBarButton::toggle()
+{
+ setOn(!isOn());
+ repaint();
+}
+
+void KToolBarButton::setToggle(bool flag)
+{
+ setToggleButton(flag);
+ if (flag)
+ connect(this, SIGNAL(toggled(bool)), this, SLOT(slotToggled()));
+ else
+ disconnect(this, SIGNAL(toggled(bool)), this, SLOT(slotToggled()));
+}
+
+QSize KToolBarButton::sizeHint() const
+{
+ return d->size;
+}
+
+QSize KToolBarButton::minimumSizeHint() const
+{
+ return d->size;
+}
+
+QSize KToolBarButton::minimumSize() const
+{
+ return d->size;
+}
+
+bool KToolBarButton::isRaised() const
+{
+ return d->m_isRaised;
+}
+
+bool KToolBarButton::isActive() const
+{
+ return d->m_isActive;
+}
+
+int KToolBarButton::iconTextMode() const
+{
+ return static_cast<int>( d->m_iconText );
+}
+
+int KToolBarButton::id() const
+{
+ return d->m_id;
+}
+
+// KToolBarButtonList
+KToolBarButtonList::KToolBarButtonList()
+{
+ setAutoDelete(false);
+}
+
+void KToolBarButton::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "ktoolbarbutton.moc"
diff --git a/kdeui/ktoolbarbutton.h b/kdeui/ktoolbarbutton.h
new file mode 100644
index 000000000..20ab5024d
--- /dev/null
+++ b/kdeui/ktoolbarbutton.h
@@ -0,0 +1,330 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997, 1998 Stephan Kulow (coolo@kde.org)
+ (C) 1997, 1998 Sven Radej (radej@kde.org)
+ (C) 1997, 1998 Mark Donohoe (donohoe@kde.org)
+ (C) 1997, 1998 Matthias Ettrich (ettrich@kde.org)
+ (C) 2000 Kurt Granroth (granroth@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _KTOOLBARBUTTON_H
+#define _KTOOLBARBUTTON_H
+
+#include <qpixmap.h>
+#include <qtoolbutton.h>
+#include <qintdict.h>
+#include <qstring.h>
+#include <kglobal.h>
+
+class KToolBar;
+class KToolBarButtonPrivate;
+class KInstance;
+class QEvent;
+class QPopupMenu;
+class QPainter;
+
+/**
+ * A toolbar button. This is used internally by KToolBar, use the
+ * KToolBar methods instead.
+ * @internal
+ */
+class KDEUI_EXPORT KToolBarButton : public QToolButton
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Construct a button with an icon loaded by the button itself.
+ * This will trust the button to load the correct icon with the
+ * correct size.
+ *
+ * @param icon Name of icon to load (may be absolute or relative)
+ * @param id Id of this button
+ * @param parent This button's parent
+ * @param name This button's internal name
+ * @param txt This button's text (in a tooltip or otherwise)
+ * @param _instance the instance to use for this button
+ */
+ KToolBarButton(const QString& icon, int id, QWidget *parent,
+ const char *name=0L, const QString &txt=QString::null,
+ KInstance *_instance = KGlobal::instance());
+
+ /**
+ * Construct a button with an existing pixmap. It is not
+ * recommended that you use this as the internal icon loading code
+ * will almost always get it "right".
+ *
+ * @param pixmap Name of icon to load (may be absolute or relative)
+ * @param id Id of this button
+ * @param parent This button's parent
+ * @param name This button's internal name
+ * @param txt This button's text (in a tooltip or otherwise)
+ */
+ KToolBarButton(const QPixmap& pixmap, int id, QWidget *parent,
+ const char *name=0L, const QString &txt=QString::null);
+
+ /**
+ * Construct a separator button
+ *
+ * @param parent This button's parent
+ * @param name This button's internal name
+ */
+ KToolBarButton(QWidget *parent=0L, const char *name=0L);
+
+ /**
+ * Standard destructor
+ */
+ ~KToolBarButton();
+
+#ifndef KDE_NO_COMPAT
+ /**
+ * @deprecated
+ * Set the pixmap directly for this button. This pixmap should be
+ * the active one... the dimmed and disabled pixmaps are constructed
+ * based on this one. However, don't use this function unless you
+ * are positive that you don't want to use setIcon.
+ *
+ * @param pixmap The active pixmap
+ */
+ // this one is from QButton, so #ifdef-ing it out doesn't break BC
+ virtual void setPixmap(const QPixmap &pixmap) KDE_DEPRECATED;
+
+ /**
+ * @deprecated
+ * Force the button to use this pixmap as the default one rather
+ * then generating it using effects.
+ *
+ * @param pixmap The pixmap to use as the default (normal) one
+ */
+ void setDefaultPixmap(const QPixmap& pixmap) KDE_DEPRECATED;
+
+ /**
+ * @deprecated
+ * Force the button to use this pixmap when disabled one rather then
+ * generating it using effects.
+ *
+ * @param pixmap The pixmap to use when disabled
+ */
+ void setDisabledPixmap(const QPixmap& pixmap) KDE_DEPRECATED;
+#endif
+
+ /**
+ * Set the text for this button. The text will be either used as a
+ * tooltip (IconOnly) or will be along side the icon
+ *
+ * @param text The button (or tooltip) text
+ */
+ virtual void setText(const QString &text);
+
+ /**
+ * Set the icon for this button. The icon will be loaded internally
+ * with the correct size. This function is preferred over setIconSet
+ *
+ * @param icon The name of the icon
+ */
+ virtual void setIcon(const QString &icon);
+
+ /// @since 3.1
+ virtual void setIcon( const QPixmap &pixmap )
+ { QToolButton::setIcon( pixmap ); }
+
+ /**
+ * Set the pixmaps for this toolbar button from a QIconSet.
+ * If you call this you don't need to call any of the other methods
+ * that set icons or pixmaps.
+ * @param iconset The iconset to use
+ */
+ virtual void setIconSet( const QIconSet &iconset );
+
+#ifndef KDE_NO_COMPAT
+ /**
+ * @deprecated
+ * Set the active icon for this button. The pixmap itself is loaded
+ * internally based on the icon size... .. the disabled and default
+ * pixmaps, however will only be constructed if generate is
+ * true. This function is preferred over setPixmap
+ *
+ * @param icon The name of the active icon
+ * @param generate If true, then the other icons are automagically
+ * generated from this one
+ */
+ KDE_DEPRECATED void setIcon(const QString &icon, bool generate ) { Q_UNUSED(generate); setIcon( icon ); }
+
+ /**
+ * @deprecated
+ * Force the button to use this icon as the default one rather
+ * then generating it using effects.
+ *
+ * @param icon The icon to use as the default (normal) one
+ */
+ void setDefaultIcon(const QString& icon) KDE_DEPRECATED;
+
+ /**
+ * @deprecated
+ * Force the button to use this icon when disabled one rather then
+ * generating it using effects.
+ *
+ * @param icon The icon to use when disabled
+ */
+ void setDisabledIcon(const QString& icon) KDE_DEPRECATED;
+#endif
+
+ /**
+ * Turn this button on or off
+ *
+ * @param flag true or false
+ */
+ void on(bool flag = true);
+
+ /**
+ * Toggle this button
+ */
+ void toggle();
+
+ /**
+ * Turn this button into a toggle button or disable the toggle
+ * aspects of it. This does not toggle the button itself.
+ * Use toggle() for that.
+ *
+ * @param toggle true or false
+ */
+ void setToggle(bool toggle = true);
+
+ /**
+ * Return a pointer to this button's popup menu (if it exists)
+ */
+ QPopupMenu *popup();
+
+ /**
+ * Returns the button's id.
+ * @since 3.2
+ */
+ int id() const;
+
+ /**
+ * Give this button a popup menu. There will not be a delay when
+ * you press the button. Use setDelayedPopup if you want that
+ * behavior.
+ *
+ * @param p The new popup menu
+ * @param unused Has no effect - ignore it.
+ */
+ void setPopup (QPopupMenu *p, bool unused = false);
+
+ /**
+ * Gives this button a delayed popup menu.
+ *
+ * This function allows you to add a delayed popup menu to the button.
+ * The popup menu is then only displayed when the button is pressed and
+ * held down for about half a second.
+ *
+ * @param p the new popup menu
+ * @param unused Has no effect - ignore it.
+ */
+ void setDelayedPopup(QPopupMenu *p, bool unused = false);
+
+ /**
+ * Turn this button into a radio button
+ *
+ * @param f true or false
+ */
+ void setRadio(bool f = true);
+
+ /**
+ * Toolbar buttons naturally will assume the global styles
+ * concerning icons, icons sizes, etc. You can use this function to
+ * explicitly turn this off, if you like.
+ *
+ * @param no_style Will disable styles if true
+ */
+ void setNoStyle(bool no_style = true);
+
+signals:
+ /**
+ * Emitted when the toolbar button is clicked (with LMB or MMB)
+ */
+ void clicked(int);
+ /**
+ * Emitted when the toolbar button is clicked (with any mouse button)
+ * @param state makes it possible to find out which button was pressed,
+ * and whether any keyboard modifiers were held.
+ * @since 3.4
+ */
+ void buttonClicked(int, Qt::ButtonState state);
+ void doubleClicked(int);
+ void pressed(int);
+ void released(int);
+ void toggled(int);
+ void highlighted(int, bool);
+
+public slots:
+ /**
+ * This slot should be called whenever the toolbar mode has
+ * potentially changed. This includes such events as text changing,
+ * orientation changing, etc.
+ */
+ void modeChange();
+ virtual void setTextLabel(const QString&, bool tipToo);
+
+protected:
+ bool event(QEvent *e);
+ void paletteChange(const QPalette &);
+ void leaveEvent(QEvent *e);
+ void enterEvent(QEvent *e);
+ void drawButton(QPainter *p);
+ bool eventFilter (QObject *o, QEvent *e);
+ /// @since 3.4
+ void mousePressEvent( QMouseEvent * );
+ /// @since 3.4
+ void mouseReleaseEvent( QMouseEvent * );
+ void showMenu();
+ QSize sizeHint() const;
+ QSize minimumSizeHint() const;
+ QSize minimumSize() const;
+
+ /// @since 3.1
+ bool isRaised() const;
+ /// @since 3.1
+ bool isActive() const;
+ /// @since 3.1
+ int iconTextMode() const;
+
+protected slots:
+ void slotClicked();
+ void slotPressed();
+ void slotReleased();
+ void slotToggled();
+ void slotDelayTimeout();
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KToolBarButtonPrivate *d;
+};
+
+/**
+* List of KToolBarButton objects.
+* @internal
+* @version $Id$
+*/
+class KDEUI_EXPORT KToolBarButtonList : public QIntDict<KToolBarButton>
+{
+public:
+ KToolBarButtonList();
+ ~KToolBarButtonList() {}
+};
+
+#endif
diff --git a/kdeui/ktoolbarhandler.cpp b/kdeui/ktoolbarhandler.cpp
new file mode 100644
index 000000000..91a35d0c4
--- /dev/null
+++ b/kdeui/ktoolbarhandler.cpp
@@ -0,0 +1,246 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2002 Simon Hausmann <hausmann@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "ktoolbarhandler.h"
+
+#include <qpopupmenu.h>
+#include <kapplication.h>
+#include <ktoolbar.h>
+#include <kmainwindow.h>
+#include <klocale.h>
+#include <kaction.h>
+#include <assert.h>
+
+namespace
+{
+ const char *actionListName = "show_menu_and_toolbar_actionlist";
+
+ const char *guiDescription = ""
+ "<!DOCTYPE kpartgui><kpartgui name=\"StandardToolBarMenuHandler\">"
+ "<MenuBar>"
+ " <Menu name=\"settings\">"
+ " <ActionList name=\"%1\" />"
+ " </Menu>"
+ "</MenuBar>"
+ "</kpartgui>";
+
+ const char *resourceFileName = "barhandler.rc";
+
+ class BarActionBuilder
+ {
+ public:
+ BarActionBuilder( KActionCollection *actionCollection, KMainWindow *mainWindow, QPtrList<KToolBar> &oldToolBarList )
+ : m_actionCollection( actionCollection ), m_mainWindow( mainWindow ), m_needsRebuild( false )
+ {
+ QPtrList<QDockWindow> dockWindows = m_mainWindow->dockWindows();
+ QPtrListIterator<QDockWindow> dockWindowIt( dockWindows );
+ for ( ; dockWindowIt.current(); ++dockWindowIt ) {
+
+ KToolBar *toolBar = dynamic_cast<KToolBar *>( dockWindowIt.current() );
+ if ( !toolBar )
+ continue;
+
+ if ( oldToolBarList.findRef( toolBar ) == -1 )
+ m_needsRebuild = true;
+
+ m_toolBars.append( toolBar );
+ }
+
+ if ( !m_needsRebuild )
+ m_needsRebuild = ( oldToolBarList.count() != m_toolBars.count() );
+ }
+
+ bool needsRebuild() const { return m_needsRebuild; }
+
+ QPtrList<KAction> create()
+ {
+ if ( !m_needsRebuild )
+ return QPtrList<KAction>();
+
+ QPtrListIterator<KToolBar> toolBarIt( m_toolBars );
+ for ( ; toolBarIt.current(); ++toolBarIt )
+ handleToolBar( toolBarIt.current() );
+
+ QPtrList<KAction> actions;
+
+ if ( m_toolBarActions.count() == 0 )
+ return actions;
+
+ if ( m_toolBarActions.count() == 1 ) {
+ KToggleToolBarAction* action = static_cast<KToggleToolBarAction *>( m_toolBarActions.getFirst() );
+ action->setText( i18n( "Show Toolbar" ) );
+ action->setCheckedState( i18n( "Hide Toolbar" ) );
+ return m_toolBarActions;
+ }
+
+ KActionMenu *menuAction = new KActionMenu( i18n( "Toolbars" ), m_actionCollection, "toolbars_submenu_action" );
+
+ QPtrListIterator<KAction> actionIt( m_toolBarActions );
+ for ( ; actionIt.current(); ++actionIt )
+ menuAction->insert( actionIt.current() );
+
+ actions.append( menuAction );
+ return actions;
+ }
+
+ const QPtrList<KToolBar> &toolBars() const { return m_toolBars; }
+
+ private:
+ void handleToolBar( KToolBar *toolBar )
+ {
+ KToggleToolBarAction *action = new KToggleToolBarAction(
+ toolBar,
+ toolBar->label(),
+ m_actionCollection,
+ toolBar->name() );
+ // ## tooltips, whatsthis?
+ m_toolBarActions.append( action );
+ }
+
+ KActionCollection *m_actionCollection;
+ KMainWindow *m_mainWindow;
+
+ QPtrList<KToolBar> m_toolBars;
+ QPtrList<KAction> m_toolBarActions;
+
+ bool m_needsRebuild : 1;
+ };
+}
+
+using namespace KDEPrivate;
+
+ToolBarHandler::ToolBarHandler( KMainWindow *mainWindow, const char *name )
+ : QObject( mainWindow, name ), KXMLGUIClient( mainWindow )
+{
+ init( mainWindow );
+}
+
+ToolBarHandler::ToolBarHandler( KMainWindow *mainWindow, QObject *parent, const char *name )
+ : QObject( parent, name ), KXMLGUIClient( mainWindow )
+{
+ init( mainWindow );
+}
+
+ToolBarHandler::~ToolBarHandler()
+{
+ m_actions.setAutoDelete( true );
+ m_actions.clear();
+}
+
+KAction *ToolBarHandler::toolBarMenuAction()
+{
+ assert( m_actions.count() == 1 );
+ return m_actions.getFirst();
+}
+
+void ToolBarHandler::setupActions()
+{
+ if ( !factory() || !m_mainWindow )
+ return;
+
+ BarActionBuilder builder( actionCollection(), m_mainWindow, m_toolBars );
+
+ if ( !builder.needsRebuild() )
+ return;
+
+ unplugActionList( actionListName );
+
+ m_actions.setAutoDelete( true );
+ m_actions.clear();
+ m_actions.setAutoDelete( false );
+
+ m_actions = builder.create();
+
+ /*
+ for ( QPtrListIterator<KToolBar> toolBarIt( m_toolBars );
+ toolBarIt.current(); ++toolBarIt )
+ toolBarIt.current()->disconnect( this );
+ */
+
+ m_toolBars = builder.toolBars();
+
+ /*
+ for ( QPtrListIterator<KToolBar> toolBarIt( m_toolBars );
+ toolBarIt.current(); ++toolBarIt )
+ connect( toolBarIt.current(), SIGNAL( destroyed() ),
+ this, SLOT( setupActions() ) );
+ */
+
+ if (kapp && kapp->authorizeKAction("options_show_toolbar"))
+ plugActionList( actionListName, m_actions );
+
+ connectToActionContainers();
+}
+
+void ToolBarHandler::clientAdded( KXMLGUIClient *client )
+{
+ if ( client == this )
+ setupActions();
+}
+
+void ToolBarHandler::init( KMainWindow *mainWindow )
+{
+ d = 0;
+ m_mainWindow = mainWindow;
+
+ connect( m_mainWindow->guiFactory(), SIGNAL( clientAdded( KXMLGUIClient * ) ),
+ this, SLOT( clientAdded( KXMLGUIClient * ) ) );
+
+ /* re-use an existing resource file if it exists. can happen if the user launches the
+ * toolbar editor */
+ /*
+ setXMLFile( resourceFileName );
+ */
+
+ if ( domDocument().documentElement().isNull() ) {
+
+ QString completeDescription = QString::fromLatin1( guiDescription )
+ .arg( actionListName );
+
+ setXML( completeDescription, false /*merge*/ );
+ }
+}
+
+void ToolBarHandler::connectToActionContainers()
+{
+ QPtrListIterator<KAction> actionIt( m_actions );
+ for ( ; actionIt.current(); ++actionIt )
+ connectToActionContainer( actionIt.current() );
+}
+
+void ToolBarHandler::connectToActionContainer( KAction *action )
+{
+ uint containerCount = action->containerCount();
+ for ( uint i = 0; i < containerCount; ++i )
+ connectToActionContainer( action->container( i ) );
+}
+
+void ToolBarHandler::connectToActionContainer( QWidget *container )
+{
+ QPopupMenu *popupMenu = dynamic_cast<QPopupMenu *>( container );
+ if ( !popupMenu )
+ return;
+
+ connect( popupMenu, SIGNAL( aboutToShow() ),
+ this, SLOT( setupActions() ) );
+}
+
+#include "ktoolbarhandler.moc"
+
+/* vim: et sw=4 ts=4
+ */
diff --git a/kdeui/ktoolbarhandler.h b/kdeui/ktoolbarhandler.h
new file mode 100644
index 000000000..c0cc332cc
--- /dev/null
+++ b/kdeui/ktoolbarhandler.h
@@ -0,0 +1,69 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2002 Simon Hausmann <hausmann@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KBARHANDLER_H
+#define KBARHANDLER_H
+
+#include <qobject.h>
+#include <qguardedptr.h>
+#include <kxmlguiclient.h>
+
+class KMainWindow;
+class KToolBar;
+
+namespace KDEPrivate
+{
+
+/// @since 3.1
+class ToolBarHandler : public QObject,
+ public KXMLGUIClient
+{
+ Q_OBJECT
+public:
+ ToolBarHandler( KMainWindow *mainWindow, const char *name = 0 );
+ ToolBarHandler( KMainWindow *mainWindow, QObject *parent, const char *name = 0 );
+ virtual ~ToolBarHandler();
+
+ KAction *toolBarMenuAction();
+
+public slots:
+ void setupActions();
+
+private slots:
+ void clientAdded( KXMLGUIClient *client );
+
+private:
+ void init( KMainWindow *mainWindow );
+ void connectToActionContainers();
+ void connectToActionContainer( KAction *action );
+ void connectToActionContainer( QWidget *container );
+
+ struct Data;
+ Data *d;
+
+ QGuardedPtr<KMainWindow> m_mainWindow;
+ QPtrList<KAction> m_actions;
+ QPtrList<KToolBar> m_toolBars;
+};
+
+} // namespace KDEPrivate
+
+#endif // KBARHANDLER_H
+
+/* vim: et sw=4 ts=4
+ */
diff --git a/kdeui/ktoolbarlabelaction.cpp b/kdeui/ktoolbarlabelaction.cpp
new file mode 100644
index 000000000..9eac6a1bc
--- /dev/null
+++ b/kdeui/ktoolbarlabelaction.cpp
@@ -0,0 +1,117 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2004 Felix Berger <felixberger@beldesign.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "ktoolbarlabelaction.h"
+
+#include <qlabel.h>
+#include <qapplication.h>
+
+class KToolBarLabelAction::KToolBarLabelActionPrivate
+{
+public:
+ KToolBarLabelActionPrivate()
+ : m_label(0)
+ {
+ }
+ QLabel* m_label;
+};
+
+
+KToolBarLabelAction::KToolBarLabelAction(const QString &text,
+ const KShortcut &cut,
+ const QObject *receiver,
+ const char *slot,
+ KActionCollection *parent,
+ const char *name)
+ : KWidgetAction(new QLabel(text, 0, "kde toolbar widget"), text, cut,
+ receiver, slot, parent, name),
+ d(new KToolBarLabelActionPrivate)
+{
+ init();
+}
+
+KToolBarLabelAction::KToolBarLabelAction(QWidget* buddy,
+ const QString &text,
+ const KShortcut &cut,
+ const QObject *receiver,
+ const char *slot,
+ KActionCollection *parent,
+ const char *name)
+ : KWidgetAction(new QLabel(buddy, text, 0, "kde toolbar widget"), text,
+ cut, receiver, slot, parent, name),
+ d(new KToolBarLabelActionPrivate)
+{
+ init();
+}
+
+KToolBarLabelAction::KToolBarLabelAction(QLabel* label,
+ const KShortcut &cut,
+ const QObject *receiver,
+ const char *slot,
+ KActionCollection* parent,
+ const char *name)
+ : KWidgetAction(label, label->text(), cut, receiver, slot, parent, name),
+ d(new KToolBarLabelActionPrivate)
+{
+ Q_ASSERT(QString::fromLatin1("kde toolbar widget") == label->name());
+ init();
+}
+
+KToolBarLabelAction::~KToolBarLabelAction()
+{
+ delete d;
+ d = 0;
+}
+
+void KToolBarLabelAction::init()
+{
+ d->m_label = static_cast<QLabel*>(widget());
+ /* these lines were copied from Konqueror's KonqDraggableLabel class in
+ konq_misc.cc */
+ d->m_label->setBackgroundMode(Qt::PaletteButton);
+ d->m_label->setAlignment((QApplication::reverseLayout()
+ ? Qt::AlignRight : Qt::AlignLeft) |
+ Qt::AlignVCenter | Qt::ShowPrefix );
+ d->m_label->adjustSize();
+}
+
+void KToolBarLabelAction::setText(const QString& text)
+{
+ KWidgetAction::setText(text);
+ d->m_label->setText(text);
+}
+
+void KToolBarLabelAction::setBuddy(QWidget* buddy)
+{
+ d->m_label->setBuddy(buddy);
+}
+
+QWidget* KToolBarLabelAction::buddy() const
+{
+ return d->m_label->buddy();
+}
+
+QLabel* KToolBarLabelAction::label() const
+{
+ return d->m_label;
+}
+
+void KToolBarLabelAction::virtual_hook(int, void*)
+{
+
+}
diff --git a/kdeui/ktoolbarlabelaction.h b/kdeui/ktoolbarlabelaction.h
new file mode 100644
index 000000000..926d75c7d
--- /dev/null
+++ b/kdeui/ktoolbarlabelaction.h
@@ -0,0 +1,137 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2004 Felix Berger <felixberger@beldesign.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef KTOOLBARLABELACTION_H
+#define KTOOLBARLABELACTION_H
+
+#include <kactionclasses.h>
+
+class QLabel;
+
+/**
+ * @short Class to display a label in a toolbar.
+ *
+ * KToolBarLabelAction is a convenience class for displaying a label in a
+ * toolbar.
+ *
+ * It provides easy access to the label's #setBuddy(QWidget*) and #buddy()
+ * methods and can be used as follows:
+ *
+ * \code
+ *
+ * KHistoryCombo* findCombo = new KHistoryCombo(true, this);
+ * KWidgetAction* action
+ * = new KWidgetAction(findCombo, i18n("F&ind Combo"), Qt::Key_F6, this,
+ * SLOT(slotFocus()), actionCollection(), "find_combo");
+ *
+ * new KToolBarLabelAction(findCombo, i18n("F&ind "), 0, this,
+ * SLOT(slotFocus()), actionCollection(),
+ * "find_label");
+ *
+ * \endcode
+ *
+ * @author Felix Berger <felixberger@beldesign.de>
+ */
+class KDEUI_EXPORT KToolBarLabelAction : public KWidgetAction
+{
+public:
+ /**
+ * Constructs a toolbar label.
+ *
+ * @param text The label's and the action's text.
+ * @param cut The action's shortcut.
+ * @param receiver The SLOT's parent.
+ * @param slot The SLOT to invoke to execute this action.
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KToolBarLabelAction(const QString &text,
+ const KShortcut &cut,
+ const QObject *receiver, const char *slot,
+ KActionCollection *parent, const char *name);
+ /**
+ * Constructs a toolbar label setting a buddy for the label.
+ *
+ * @param buddy The widget which is focused when the label's accelerator is
+ * typed.
+ * @param text The label's and the action's text.
+ * @param cut The action's shortcut.
+ * @param receiver The SLOT's parent.
+ * @param slot The SLOT to invoke to execute this action.
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KToolBarLabelAction(QWidget* buddy, const QString &text,
+ const KShortcut &cut,
+ const QObject *receiver, const char *slot,
+ KActionCollection *parent, const char *name);
+ /**
+ * Constructs a toolbar label for a label.
+ *
+ * You can use this constructor if you want to display a class which is
+ * derived from QLabel in the toolbar. Note that ownership of the label is
+ * transferred to the action and the label is deleted when the action is
+ * deleted. So you shouldn't hold any pointers to the label.
+ *
+ * It's important that the label's name is set to "kde toolbar widget" in
+ * its constructor, otherwise it is not correctly rendered in some kde
+ * styles.
+ *
+ * @param label the label which is displayed in the toolbar.
+ * @param cut The action's shortcut.
+ * @param receiver The SLOT's parent.
+ * @param slot The SLOT to invoke to execute this action.
+ * @param parent This action's parent.
+ * @param name An internal name for this action.
+ */
+ KToolBarLabelAction(QLabel* label, const KShortcut &cut,
+ const QObject *receiver, const char *slot,
+ KActionCollection* parent, const char *name);
+
+ virtual ~KToolBarLabelAction();
+ /**
+ * Reimplemented to update both the action's text and the label's text.
+ */
+ virtual void setText(const QString& text);
+ /**
+ * Sets the label's buddy to buddy.
+ *
+ * See QLabel#setBuddy() for details.
+ */
+ virtual void setBuddy(QWidget* buddy);
+ /**
+ * Returns the label's buddy or 0 if no buddy is currently set.
+ *
+ * See QLabel#buddy() and QLabel#setBuddy() for more information.
+ */
+ QWidget* buddy() const;
+ /**
+ * Returns the label which is used internally.
+ */
+ QLabel* label() const;
+
+protected:
+ virtual void virtual_hook(int id, void* data);
+
+private:
+ class KToolBarLabelActionPrivate;
+ KToolBarLabelActionPrivate *d;
+ void init();
+};
+
+
+#endif
diff --git a/kdeui/ktoolbarradiogroup.cpp b/kdeui/ktoolbarradiogroup.cpp
new file mode 100644
index 000000000..ca78db630
--- /dev/null
+++ b/kdeui/ktoolbarradiogroup.cpp
@@ -0,0 +1,77 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997, 1998 Stephan Kulow (coolo@kde.org)
+ (C) 1997, 1998 Mark Donohoe (donohoe@kde.org)
+ (C) 1997, 1998 Sven Radej (radej@kde.org)
+ (C) 1997, 1998 Matthias Ettrich (ettrich@kde.org)
+ (C) 1999 Chris Schlaeger (cs@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config.h>
+
+#include "ktoolbarradiogroup.h"
+#include "ktoolbar.h"
+#include "ktoolbarbutton.h"
+
+/*************************************************************************
+ * KToolBarRadioGroup *
+ *************************************************************************/
+
+
+KToolBarRadioGroup::KToolBarRadioGroup (KToolBar *_parent, const char *_name)
+: QObject(_parent, _name)
+{
+ buttons = new KToolBarButtonList();
+ tb = _parent;
+ connect (tb, SIGNAL(toggled(int)), this, SLOT(slotToggled(int)));
+}
+
+KToolBarRadioGroup::~KToolBarRadioGroup()
+{
+ delete buttons;
+}
+
+void KToolBarRadioGroup::addButton (int id)
+{
+ KToolBarButton *b = tb->getButton( id );
+ b->setRadio( true );
+ buttons->insert( id, b );
+}
+
+void KToolBarRadioGroup::removeButton (int id)
+{
+ if (!buttons->find(id))
+ return;
+ buttons->find(id)->setRadio(false);
+ buttons->remove(id);
+}
+
+void KToolBarRadioGroup::slotToggled(int id)
+{
+ if (buttons->find(id) && buttons->find(id)->isOn())
+ {
+ QIntDictIterator<KToolBarButton> it(*buttons);
+ while (it.current())
+ {
+ if (it.currentKey() != id)
+ it.current()->on(false);
+ ++it;
+ }
+ }
+}
+
+#include "ktoolbarradiogroup.moc"
+
diff --git a/kdeui/ktoolbarradiogroup.h b/kdeui/ktoolbarradiogroup.h
new file mode 100644
index 000000000..2cdc1c8e9
--- /dev/null
+++ b/kdeui/ktoolbarradiogroup.h
@@ -0,0 +1,88 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997, 1998 Stephan Kulow (coolo@kde.org)
+ (C) 1997, 1998 Sven Radej (radej@kde.org)
+ (C) 1997, 1998 Mark Donohoe (donohoe@kde.org)
+ (C) 1997, 1998 Matthias Ettrich (ettrich@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _KTOOLBARRADIOGROUP_H
+#define _KTOOLBARRADIOGROUP_H
+
+#include <qobject.h>
+
+#include <kdelibs_export.h>
+
+class KToolBar;
+class KToolBarButtonList;
+class KToolBarRadioGroupPrivate;
+
+/*************************************************************************
+ * KToolBarRadioGroup *
+ *************************************************************************/
+ /**
+ * @short Class for group of radio butons in toolbar.
+ *
+ * KToolBarRadioGroup is class for group of radio butons in toolbar.
+ * Take toggle buttons which you already inserted into toolbar,
+ * create KToolBarRadioGroup instance and add them here.
+ * All buttons will emit signals toggled (bool) (or you can
+ * use sitgnal toggled (int id) from toolbar). When one button is set
+ * down, all others are unset. All buttons emit signals - those who
+ * "go down" and those who "go up".
+ *
+ * @author Sven Radej <radej@kde.org>
+ */
+class KDEUI_EXPORT KToolBarRadioGroup : public QObject
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Constructor. Parent must be KToolBar .
+ */
+ KToolBarRadioGroup (KToolBar *_parent, const char *_name=0);
+ /**
+ * Destructor.
+ */
+ ~KToolBarRadioGroup ();
+
+ /**
+ * Adds button to group. Button cannot be unset by mouse clicks (you
+ * must press some other button tounset this one)
+ */
+ void addButton (int id);
+
+ /**
+ * Removes button from group, making it again toggle button (i.e.
+ * You can unset it with mouse).
+ */
+ void removeButton (int id);
+
+public slots:
+ /**
+ * Internal - nothing for you here.
+ */
+ void slotToggled (int);
+
+private:
+ KToolBarButtonList *buttons;
+ KToolBar *tb;
+
+ KToolBarRadioGroupPrivate *d;
+};
+
+#endif
diff --git a/kdeui/kurllabel.cpp b/kdeui/kurllabel.cpp
new file mode 100644
index 000000000..f45fce3a7
--- /dev/null
+++ b/kdeui/kurllabel.cpp
@@ -0,0 +1,450 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1998 Kurt Granroth <granroth@kde.org>
+ Copyright (C) 2000 Peter Putzer <putzer@kde.org>
+ Copyright (C) 2005 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qcolor.h>
+#include <qtimer.h>
+#include <qtooltip.h>
+#include <qpixmap.h>
+#include <qpainter.h>
+#include <qstyle.h>
+#include <qapplication.h>
+
+#include <kcursor.h>
+#include <kglobalsettings.h>
+
+#include "kurllabel.h"
+
+class KURLLabel::Private
+{
+public:
+ Private (const QString& url, KURLLabel* label)
+ : URL (url),
+ LinkColor (KGlobalSettings::linkColor()),
+ HighlightedLinkColor (Qt::red),
+ Tip(url),
+ Cursor (0L),
+ Underline (true),
+ UseTips (false),
+ Glow (true),
+ Float (false),
+ RealUnderline (true),
+ MousePressed(false),
+ WasInsideRect(false),
+ MarginAltered(false),
+ Timer (new QTimer (label))
+ {
+ connect (Timer, SIGNAL (timeout ()), label, SLOT (updateColor ()));
+ }
+
+ ~Private ()
+ {
+ delete Cursor;
+ }
+
+ QString URL;
+ QPixmap AltPixmap;
+
+ QColor LinkColor;
+ QColor HighlightedLinkColor;
+
+ QString Tip;
+ QCursor* Cursor;
+ bool Underline:1;
+ bool UseTips:1;
+ bool Glow:1;
+ bool Float:1;
+ bool RealUnderline:1;
+ bool MousePressed:1;
+ bool WasInsideRect:1;
+ bool MarginAltered:1;
+ QPixmap RealPixmap;
+
+ QTimer* Timer;
+};
+
+KURLLabel::KURLLabel (const QString& url, const QString& text,
+ QWidget* parent, const char* name)
+ : QLabel (!text.isNull() ? text : url, parent, name),
+ d (new Private (url, this))
+{
+ setFont (font());
+ setUseCursor (true);
+ setLinkColor (d->LinkColor);
+ setFocusPolicy( QWidget::StrongFocus ); //better accessibility
+ setMouseTracking (true);
+}
+
+KURLLabel::KURLLabel (QWidget* parent, const char* name)
+ : QLabel (parent, name),
+ d (new Private (QString::null, this))
+{
+ setFont (font());
+ setUseCursor (true);
+ setLinkColor (d->LinkColor);
+ setFocusPolicy( QWidget::StrongFocus ); //better accessibility
+ setMouseTracking (true);
+}
+
+KURLLabel::~KURLLabel ()
+{
+ delete d;
+}
+
+void KURLLabel::mouseReleaseEvent (QMouseEvent* e)
+{
+ QLabel::mouseReleaseEvent (e);
+ if (!d->MousePressed)
+ return;
+ d->MousePressed = false;
+ QRect r( activeRect() );
+ if (!r.contains(e->pos()))
+ return;
+
+ setLinkColor (d->HighlightedLinkColor);
+ d->Timer->start (300);
+
+ switch (e->button())
+ {
+ case LeftButton:
+ emit leftClickedURL ();
+ emit leftClickedURL (d->URL);
+ break;
+
+ case MidButton:
+ emit middleClickedURL ();
+ emit middleClickedURL (d->URL);
+ break;
+
+ case RightButton:
+ emit rightClickedURL ();
+ emit rightClickedURL (d->URL);
+ break;
+
+ default:
+ ; // nothing
+ }
+}
+
+void KURLLabel::setFont (const QFont& f)
+{
+ QFont newFont = f;
+ newFont.setUnderline (d->Underline);
+
+ QLabel::setFont (newFont);
+}
+
+void KURLLabel::setUnderline (bool on)
+{
+ d->Underline = on;
+
+ setFont (font());
+}
+
+void KURLLabel::updateColor ()
+{
+ d->Timer->stop();
+
+ QRect r( activeRect() );
+ if (!(d->Glow || d->Float) || !r.contains (mapFromGlobal(QCursor::pos())))
+ setLinkColor (d->LinkColor);
+}
+
+void KURLLabel::setLinkColor (const QColor& col)
+{
+ QPalette p = palette();
+ p.setColor (QColorGroup::Foreground, col);
+ setPalette (p);
+
+ update();
+}
+
+void KURLLabel::setURL (const QString& url)
+{
+ if ( d->Tip == d->URL ) { // update the tip as well
+ d->Tip = url;
+ setUseTips( d->UseTips );
+ }
+
+ d->URL = url;
+}
+
+const QString& KURLLabel::url () const
+{
+ return d->URL;
+}
+
+void KURLLabel::unsetCursor ()
+{
+ delete d->Cursor;
+ d->Cursor = 0;
+}
+
+void KURLLabel::setCursor ( const QCursor& cursor )
+{
+ delete d->Cursor;
+ d->Cursor = new QCursor( cursor );
+}
+
+void KURLLabel::setUseCursor (bool on, QCursor* cursor)
+{
+ if (on)
+ {
+ if (cursor)
+ KURLLabel::setCursor (*cursor);
+ else
+ KURLLabel::setCursor (KCursor::handCursor());
+ }
+ else
+ KURLLabel::unsetCursor ();
+}
+
+bool KURLLabel::useCursor () const
+{
+ return d->Cursor;
+}
+
+void KURLLabel::setUseTips (bool on)
+{
+ d->UseTips = on;
+
+ if (on) {
+ QToolTip::add (this, activeRect(), d->Tip);
+ } else
+ QToolTip::remove (this);
+}
+
+void KURLLabel::setTipText (const QString& tip)
+{
+ d->Tip = tip;
+
+ setUseTips (d->UseTips);
+}
+
+bool KURLLabel::useTips () const
+{
+ return d->UseTips;
+}
+
+const QString& KURLLabel::tipText () const
+{
+ return d->Tip;
+}
+
+void KURLLabel::setHighlightedColor (const QColor& highcolor)
+{
+ d->LinkColor = highcolor;
+
+ if (!d->Timer->isActive())
+ setLinkColor (highcolor);
+}
+
+void KURLLabel::setHighlightedColor (const QString& highcolor)
+{
+ setHighlightedColor (QColor (highcolor));
+}
+
+void KURLLabel::setSelectedColor (const QColor& selcolor)
+{
+ d->HighlightedLinkColor = selcolor;
+
+ if (d->Timer->isActive())
+ setLinkColor (selcolor);
+}
+
+void KURLLabel::setSelectedColor (const QString& selcolor)
+{
+ setSelectedColor (QColor (selcolor));
+}
+
+void KURLLabel::setGlow (bool glow)
+{
+ d->Glow = glow;
+}
+
+void KURLLabel::setFloat (bool do_float)
+{
+ d->Float = do_float;
+}
+
+bool KURLLabel::isGlowEnabled () const
+{
+ return d->Glow;
+}
+
+bool KURLLabel::isFloatEnabled () const
+{
+ return d->Float;
+}
+
+void KURLLabel::setAltPixmap (const QPixmap& altPix)
+{
+ d->AltPixmap = altPix;
+}
+
+const QPixmap* KURLLabel::altPixmap () const
+{
+ return &d->AltPixmap;
+}
+
+void KURLLabel::enterEvent (QEvent* e)
+{
+ QLabel::enterEvent (e);
+
+ QRect r( activeRect() );
+ if (!r.contains( static_cast<QMouseEvent*>(e)->pos() ))
+ return;
+
+ if (!d->AltPixmap.isNull() && pixmap())
+ {
+ d->RealPixmap = *pixmap();
+ setPixmap (d->AltPixmap);
+ }
+
+ if (d->Glow || d->Float)
+ {
+ d->Timer->stop();
+
+ setLinkColor (d->HighlightedLinkColor);
+
+ d->RealUnderline = d->Underline;
+
+ if (d->Float)
+ setUnderline (true);
+ }
+
+ emit enteredURL ();
+ emit enteredURL (d->URL);
+}
+
+void KURLLabel::leaveEvent (QEvent* e)
+{
+ QLabel::leaveEvent (e);
+
+ if (!d->AltPixmap.isNull() && pixmap())
+ setPixmap (d->RealPixmap);
+
+ if ((d->Glow || d->Float) && !d->Timer->isActive())
+ setLinkColor (d->LinkColor);
+
+ setUnderline (d->RealUnderline);
+
+ emit leftURL ();
+ emit leftURL (d->URL);
+}
+
+bool KURLLabel::event (QEvent *e)
+{
+ if (e && e->type() == QEvent::ParentPaletteChange)
+ {
+ // use parentWidget() unless you are a toplevel widget, then try qAapp
+ QPalette p = parentWidget() ? parentWidget()->palette() : qApp->palette();
+ p.setBrush(QColorGroup::Base, p.brush(QPalette::Normal, QColorGroup::Background));
+ p.setColor(QColorGroup::Foreground, palette().active().foreground());
+ setPalette(p);
+ d->LinkColor = KGlobalSettings::linkColor();
+ setLinkColor(d->LinkColor);
+ return true;
+ }
+ else if (e->type() == QEvent::Paint) {
+ const bool result = QLabel::event(e);
+ if (result && hasFocus()) {
+ QPainter p(this);
+ QRect r( activeRect() );
+ style().drawPrimitive( QStyle::PE_FocusRect, &p, r, colorGroup() );
+ }
+ return result;
+ }
+ else if (e->type() == QEvent::KeyPress) {
+ QKeyEvent* ke = static_cast<QKeyEvent*>(e);
+ if (ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Return) {
+ setLinkColor (d->HighlightedLinkColor);
+ d->Timer->start (300);
+ emit leftClickedURL ();
+ emit leftClickedURL (d->URL);
+ ke->accept();
+ return true;
+ }
+ }
+ else if (e->type() == QEvent::MouseButtonPress) {
+ QRect r( activeRect() );
+ d->MousePressed = r.contains(static_cast<QMouseEvent*>(e)->pos());
+ }
+ else if (e->type() == QEvent::MouseMove) {
+ if (d->Cursor) {
+ QRect r( activeRect() );
+ bool inside = r.contains(static_cast<QMouseEvent*>(e)->pos());
+ if (d->WasInsideRect != inside) {
+ if (inside)
+ QLabel::setCursor(*d->Cursor);
+ else
+ QLabel::unsetCursor();
+ d->WasInsideRect = inside;
+ }
+ }
+ }
+ return QLabel::event(e);
+}
+
+QRect KURLLabel::activeRect() const
+{
+ QRect r( contentsRect() );
+ if (text().isEmpty() || (!d->MarginAltered && sizePolicy() == QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)))
+ return r; //fixed size is sometimes used with pixmap
+ int hAlign = QApplication::horizontalAlignment( alignment() );
+ int indentX = (hAlign && indent()>0) ? indent() : 0;
+ QFontMetrics fm(font());
+ r.setWidth( QMIN(fm.width(text()), r.width()));
+ if ( hAlign & AlignLeft )
+ r.moveLeft(r.left() + indentX);
+ if ( hAlign & AlignCenter )
+ r.moveLeft((contentsRect().width()-r.width())/2+margin());
+ if ( hAlign & AlignRight )
+ r.moveLeft(contentsRect().width()-r.width()-indentX+margin());
+ int add = QMIN(3, margin());
+ r = QRect(r.left()-add, r.top()-add, r.width()+2*add, r.height()+2*add);
+ return r;
+}
+
+void KURLLabel::setMargin( int margin )
+{
+ QLabel::setMargin(margin);
+ d->MarginAltered = true;
+}
+
+void KURLLabel::setFocusPolicy( FocusPolicy policy )
+{
+ QLabel::setFocusPolicy(policy);
+ if (!d->MarginAltered) {
+ QLabel::setMargin(policy == NoFocus ? 0 : 3); //better default : better look when focused
+ }
+}
+
+void KURLLabel::setSizePolicy ( QSizePolicy policy )
+{
+ QLabel::setSizePolicy(policy);
+ if (!d->MarginAltered && policy.horData()==QSizePolicy::Fixed && policy.verData()==QSizePolicy::Fixed) {
+ QLabel::setMargin(0); //better default : better look when fixed size
+ }
+}
+
+void KURLLabel::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "kurllabel.moc"
diff --git a/kdeui/kurllabel.h b/kdeui/kurllabel.h
new file mode 100644
index 000000000..81f2d97ab
--- /dev/null
+++ b/kdeui/kurllabel.h
@@ -0,0 +1,407 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1998 Kurt Granroth <granroth@kde.org>
+ Copyright (C) 2000 Peter Putzer <putzer@kde.org>
+ Copyright (C) 2005 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KURLLABEL_H
+#define KURLLABEL_H
+
+#include <qlabel.h>
+
+#include <kdelibs_export.h>
+
+class QColor;
+class QCursor;
+class QPixmap;
+
+/**
+ * @short A drop-in replacement for QLabel that displays hyperlinks.
+ *
+ * KURLLabel is a drop-in replacement for QLabel that handles text
+ * in a fashion similar to how an HTML widget handles hyperlinks. The
+ * text can be underlined (or not) and set to different colors. It
+ * can also "glow" (cycle colors) when the mouse passes over it.
+ *
+ * KURLLabel also provides signals for several events, including
+ * the mouse leaving and entering the text area and all forms of
+ * mouse clicking.
+ *
+ * By default KURLLabel accepts focus. When focused, standard
+ * focus rectangle is displayed as in HTML widget.
+ * Pressing Enter key accepts the focused label.
+ *
+ * A typical usage would be something like so:
+ *
+ * \code
+ * KURLLabel *address = new KURLLabel(this);
+ * address->setText("My homepage");
+ * address->setURL("http://www.home.com/~me");
+ * connect(address, SIGNAL(leftClickedURL(const QString&)),
+ * SLOT(processMyURL(const QString&)));
+ * \endcode
+ *
+ * In this example, the text "My homepage" would be displayed
+ * as blue, underlined text. When the mouse passed over it,
+ * it would "glow" red. When the user clicks on the text, the
+ * signal leftClickedURL() would be emitted with "http://www.home.com/~me"
+ * as its argument.
+ *
+ * \image html kurllabel.png "KDE URL Label"
+ *
+ * @author Kurt Granroth <granroth@kde.org> (Interface)
+ * @author Peter Putzer <putzer@kde.org> (Rewrite)
+ * @version $Id$
+ *
+ */
+class KDEUI_EXPORT KURLLabel : public QLabel
+{
+ Q_OBJECT
+ Q_PROPERTY (QString url READ url WRITE setURL)
+ Q_PROPERTY (QString tipText READ tipText WRITE setTipText )
+ Q_PROPERTY (QPixmap altPixmap READ altPixmap WRITE setAltPixmap)
+ Q_PROPERTY (bool glowEnabled READ isGlowEnabled WRITE setGlow )
+ Q_PROPERTY (bool floatEnabled READ isFloatEnabled WRITE setFloat )
+ Q_PROPERTY (bool useTips READ useTips WRITE setUseTips )
+ Q_PROPERTY (bool useCursor READ useCursor WRITE setUseCursor )
+
+public:
+ /**
+ * Default constructor.
+ *
+ * Use setURL() and setText() or QListView::setPixmap()
+ * to set the resp. properties.
+ */
+ KURLLabel (QWidget* parent = 0L, const char* name = 0L);
+
+ /**
+ * Convenience constructor.
+ *
+ * @param url is the URL emitted when the label is clicked.
+ * @param text is the displayed string. If it's equal to QString::null
+ * the @p url will be used instead.
+ * @param parent Passed to lower level constructor
+ * @param name Passed to lower level constructor
+ *
+ * @p parent and @p name are passed to QLabel, which in turn passes
+ * them further down
+ */
+ KURLLabel (const QString& url, const QString& text = QString::null,
+ QWidget* parent = 0L, const char* name = 0L);
+
+ /**
+ * Destructs the label.
+ */
+ virtual ~KURLLabel ();
+
+ /**
+ * Returns the URL.
+ */
+ const QString& url () const;
+
+ /**
+ * Returns the current tooltip text.
+ */
+ const QString& tipText () const;
+
+ /**
+ * @return true if a tooltip will be displayed.
+ *
+ * @see setTipText()
+ */
+ bool useTips () const;
+
+ /**
+ * @return true if the cursor will change while over the URL.
+ *
+ * @see setUseCursor ()
+ */
+ bool useCursor () const;
+
+ /**
+ * When this is on, the text will switch to the selected
+ * color whenever the mouse passes over it.
+ */
+ bool isGlowEnabled () const;
+
+ /**
+ * This feature is very similar to the "glow" feature in that the color of the
+ * label switches to the selected color when the cursor passes
+ * over it. In addition, underlining is turned on for as
+ * long as the mouse is overhead. Note that if "glow" and
+ * underlining are both already turned on, this feature
+ * will have no visible effect.
+ */
+ bool isFloatEnabled () const;
+
+ /**
+ * @return the alternate pixmap (may be 0L if none was set).
+ */
+ const QPixmap* altPixmap () const;
+
+ /**
+ * Reimplemented for internal reasons, the API is not affected.
+ */
+ virtual void setMargin ( int margin );
+
+ /**
+ * Reimplemented for internal reasons, the API is not affected.
+ */
+ virtual void setFocusPolicy ( FocusPolicy policy );
+
+ /**
+ * Reimplemented for internal reasons, the API is not affected.
+ */
+ virtual void setSizePolicy ( QSizePolicy );
+
+public slots:
+ /**
+ * Turns on or off the underlining.
+ *
+ * When this is on, the
+ * text will be underlined. By default, it is @p true.
+ */
+ void setUnderline (bool on = true);
+
+ /**
+ * Sets the URL for this label to @p url.
+ *
+ * @see url
+ */
+ void setURL (const QString& url);
+
+ /**
+ * Overridden for internal reasons; the API remains unaffected.
+ */
+ virtual void setFont (const QFont&);
+
+ /**
+ * Turns on or off the tool tip feature.
+ *
+ * When this is on, the URL will be displayed as a
+ * tooltip whenever the mouse passes passes over it.
+ * By default, it is @p false.
+ */
+ void setUseTips (bool on = true);
+
+ /**
+ * Specifies what text to display when tooltips are turned on.
+ *
+ * If this is not used, the tip will default to the URL.
+ *
+ * @see setUseTips()
+ */
+ void setTipText (const QString& tip);
+
+ /**
+ * Sets the highlight color.
+ *
+ * This is the default foreground
+ * color (non-selected). By default, it is @p blue.
+ */
+ void setHighlightedColor(const QColor& highcolor);
+
+ /**
+ * This is an overloaded version for convenience.
+ *
+ * @see setHighlightedColor()
+ */
+ void setHighlightedColor(const QString& highcolor);
+
+ /**
+ * Sets the selected color.
+ *
+ * This is the color the text will change
+ * to when either a mouse passes over it and "glow" mode is on or
+ * when it is selected (clicked). By default, it is @p red.
+ */
+ void setSelectedColor(const QColor& selcolor);
+
+ /**
+ * This is an overloaded version for convenience.
+ *
+ * @see setSelectedColor()
+ */
+ void setSelectedColor(const QString& selcolor);
+
+ /**
+ * Overridden for internal reasons; the API remains unaffected.
+ */
+ virtual void setCursor ( const QCursor& cursor );
+
+ /**
+ * Overridden for internal reasons; the API remains unaffected.
+ */
+ virtual void unsetCursor ();
+
+ /**
+ * Turns the custom cursor feature on or off.
+ *
+ * When this is on, the cursor will change to a custom cursor
+ * (default is a "pointing hand") whenever the cursor passes
+ * over the label. By default, it is on.
+ *
+ * @param on whether a custom cursor should be displayed.
+ * @param cursor is the custom cursor. @p 0L indicates the default "hand cursor".
+ */
+ void setUseCursor (bool on, QCursor* cursor = 0L);
+
+ /**
+ * Turns on or off the "glow" feature.
+ *
+ * When this is on, the text will switch to the
+ * selected color whenever the mouse
+ * passes over it. By default, it is @p true.
+ */
+ void setGlow (bool glow = true);
+
+ /**
+ * Turns on or off the "float" feature.
+ *
+ * This feature is very similar to the "glow" feature in
+ * that the color of the label switches to the selected
+ * color when the cursor passes over it. In addition,
+ * underlining is turned on for as long as the mouse is overhead.
+ * Note that if "glow" and underlining are both already turned
+ * on, this feature will have no visible effect.
+ * By default, it is @p false.
+ */
+ void setFloat (bool do_float = true);
+
+ /**
+ * Sets the "alt" pixmap.
+ *
+ * This pixmap will be displayed when the
+ * cursor passes over the label. The effect is similar to the
+ * trick done with 'onMouseOver' in javascript.
+ *
+ * @see altPixmap()
+ */
+ void setAltPixmap (const QPixmap& altPix);
+
+signals:
+
+ /**
+ * Emitted when the mouse has passed over the label.
+ *
+ * @param url The URL for this label.
+ */
+ void enteredURL (const QString& url);
+
+ /**
+ * Emitted when the mouse has passed over the label.
+ */
+ void enteredURL ();
+
+ /**
+ * Emitted when the mouse is no longer over the label.
+ *
+ * @param url The URL for this label.
+ */
+ void leftURL (const QString& url);
+
+ /**
+ * Emitted when the mouse is no longer over the label.
+ */
+ void leftURL ();
+
+ /**
+ * Emitted when the user clicked the left mouse button on this label.
+ *
+ * @param url The URL for this label.
+ */
+ void leftClickedURL(const QString& url);
+
+ /**
+ * Emitted when the user clicked the left mouse button on this label.
+ */
+ void leftClickedURL();
+
+ /**
+ * Emitted when the user clicked the right mouse button on this label.
+ *
+ * @param url The URL for this label.
+ */
+ void rightClickedURL(const QString& url);
+
+ /**
+ * Emitted when the user clicked the right mouse button on this label.
+ */
+ void rightClickedURL();
+
+ /**
+ * Emitted when the user clicked the middle mouse button on this label.
+ *
+ * @param url The URL for this label.
+ */
+ void middleClickedURL(const QString& url);
+
+ /**
+ * Emitted when the user clicked the left mouse button on this label.
+ */
+ void middleClickedURL();
+
+protected:
+
+ /**
+ * Overridden for internal reasons; the API remains unaffected.
+ */
+ virtual void mouseReleaseEvent ( QMouseEvent * e );
+
+ /**
+ * Overridden for internal reasons; the API remains unaffected.
+ */
+ virtual void enterEvent (QEvent*);
+
+ /**
+ * Overridden for internal reasons; the API remains unaffected.
+ */
+ virtual void leaveEvent (QEvent*);
+
+ /**
+ * Catch parent palette changes
+ */
+ virtual bool event (QEvent *e);
+
+ /**
+ *
+ */
+ QRect activeRect() const;
+
+
+private slots:
+ /**
+ * @internal
+ * Slot used to reset the link-color to normal (timer-driven).
+ */
+ void updateColor ();
+
+private:
+ /**
+ * @internal
+ * A private helper function to set the link-color to @p col.
+ */
+ void setLinkColor (const QColor& col);
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ class Private;
+ Private* d;
+};
+
+#endif // KURLLABEL_H
diff --git a/kdeui/kwhatsthismanager.cpp b/kdeui/kwhatsthismanager.cpp
new file mode 100644
index 000000000..77c957a62
--- /dev/null
+++ b/kdeui/kwhatsthismanager.cpp
@@ -0,0 +1,121 @@
+/* This file is part of the KDE Libraries
+ * Copyright (C) 2004 Peter Rockai (mornfall) <mornfall@danill.sk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#include "kwhatsthismanager_p.h"
+#include "qwhatsthis.h"
+#include <qvariant.h>
+#include <kdebug.h>
+#include <qtextedit.h>
+#include <klocale.h>
+#include <kapplication.h>
+
+KWhatsThisManager *KWhatsThisManager::s_instance = 0;
+
+class KWhatsThisUndefined : public QWhatsThis
+{
+ public:
+ KWhatsThisUndefined (QWidget *);
+ QString text (const QPoint &);
+ public slots:
+ bool clicked (const QString &);
+ protected:
+ QWidget *m_widget;
+};
+
+KWhatsThisUndefined::KWhatsThisUndefined (QWidget *w)
+ : QWhatsThis (w)
+{
+ m_widget = w;
+}
+
+QString KWhatsThisUndefined::text (const QPoint &)
+{
+ if (!m_widget)
+ return "";
+ QString txt = i18n ("<b>Not Defined</b><br>There is no \"What's This?\""
+ " help assigned to this widget. If you want to help us to "
+ " describe the widget, you are welcome to <a href=\"submit"
+ "-whatsthis\">send us your own \"What's This?\" help</a> for it.");
+ QString parent;
+ if (m_widget -> parentWidget ())
+ parent = QWhatsThis::textFor (m_widget -> parentWidget ());
+ if (parent != txt)
+ if (! parent . isEmpty ())
+ return parent;
+ return txt;
+}
+
+bool KWhatsThisUndefined::clicked (const QString& href)
+{
+ if (href == "submit-whatsthis") {
+ QWidget *w = m_widget;
+ QString body;
+ body . append ("Widget text: '" + (m_widget -> property ("text") . toString ()) + "'\n");
+ QString dsc = QString ("current --> ") + m_widget -> name ();
+ dsc . append (QString (" (") + m_widget -> className () + ")\n");
+ for (w = m_widget; w && w != m_widget -> topLevelWidget (); w = w -> parentWidget ()) {
+ dsc . append (w -> name ());
+ dsc . append (QString (" (") + w -> className () + ")\n");
+ }
+ w = m_widget -> topLevelWidget ();
+ if (w) {
+ dsc . append ("toplevel --> ");
+ dsc . append (w -> name ());
+ dsc . append (QString (" (") + w -> className () + ")\n");
+ }
+ body . append (dsc);
+ QString subj ("What's This submission: ");
+ subj . append (qApp -> argv () [0]);
+ body . append ("\nPlease type in your what's this help between these lines: "
+ "\n--%-----------------------------------------------------------------------\n"
+ "\n--%-----------------------------------------------------------------------");
+ kapp -> invokeMailer ("quality-whatsthis@kde.org", "", "", subj, body);
+ }
+ return TRUE;
+}
+
+void KWhatsThisManager::init ()
+{
+ if (s_instance)
+ return;
+ s_instance = new KWhatsThisManager;
+}
+
+KWhatsThisManager::KWhatsThisManager ()
+{
+ // go away...
+ // qApp -> installEventFilter (this);
+}
+
+bool KWhatsThisManager::eventFilter (QObject * /*o*/, QEvent *e)
+{
+ if (e -> type () == QEvent::ChildInserted) {
+ QChildEvent *ce = (QChildEvent *)e;
+ // kdDebug () << "new qobject:" << ce -> child () << endl;
+ if (ce -> child () -> isWidgetType ()) {
+ QWidget *w = (QWidget *) (ce -> child ());
+ // kdDebug () << "new qwidget:" << w << endl;
+ if (QWhatsThis::textFor (w) . isEmpty ())
+ new KWhatsThisUndefined (w);
+ }
+ }
+ return false;
+}
+
+#include "kwhatsthismanager_p.moc"
+
diff --git a/kdeui/kwhatsthismanager_p.h b/kdeui/kwhatsthismanager_p.h
new file mode 100644
index 000000000..6dd420be5
--- /dev/null
+++ b/kdeui/kwhatsthismanager_p.h
@@ -0,0 +1,58 @@
+/* This file is part of the KDE Libraries
+ * Copyright (C) 2004 Peter Rockai (mornfall) <mornfall@danill.sk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef KWHATSTHISMANAGER_P_H
+#define KWHATSTHISMANAGER_P_H
+
+#include <qwhatsthis.h>
+#include <qapplication.h>
+
+#include <kdialogbase.h>
+
+class QToolButton;
+class QPopupMenu;
+class QStyleSheet;
+class QTextEdit;
+
+/**
+ * This class is used automatically by KMainWindow and KDialog to attach a
+ * What's This templates to all new widgets. If you don't use either of those
+ * classes and want this functionality, call KWhatsThisManager::init () before
+ * creating any widgets.
+ *
+ * It works by watching for child creation events and if the new objects are
+ * widgets, it attachs the whatsthis template to them (unless there already is
+ * What's This defined). This template will be overriden by any custom What's
+ * This info.
+ *
+ * @see QWhatsThis
+ * @author Peter Rockai (mornfall) <mornfall@danill.sk>
+ **/
+class KDEUI_EXPORT KWhatsThisManager : public QObject
+{
+ Q_OBJECT
+ public:
+ static void init ();
+ bool eventFilter (QObject *o, QEvent *e);
+ protected:
+ static KWhatsThisManager *s_instance;
+ private:
+ KWhatsThisManager ();
+};
+
+#endif
diff --git a/kdeui/kwindowinfo.cpp b/kdeui/kwindowinfo.cpp
new file mode 100644
index 000000000..263deae84
--- /dev/null
+++ b/kdeui/kwindowinfo.cpp
@@ -0,0 +1,178 @@
+/*
+ * copyright : (C) 2001-2002 by Richard Moore
+ * License : This file is released under the terms of the LGPL, version 2.
+ * email : rich@kde.org
+ */
+
+#include <qobjectlist.h>
+#include <qpixmap.h>
+#include <qtimer.h>
+#include <qtooltip.h>
+#include <ksystemtray.h>
+#include <kwin.h>
+
+#include "kwindowinfo.h"
+#include "kwindowinfo.moc"
+
+static const int UNSPECIFIED_TIMEOUT = -1;
+static const int DEFAULT_MESSAGE_TIMEOUT = 3000;
+
+KWindowInfo::KWindowInfo( QWidget *parent, const char *name )
+ : QObject( parent, name ), win( parent ), autoDel( false )
+{
+}
+
+KWindowInfo::~KWindowInfo()
+{
+}
+
+void KWindowInfo::showMessage( QWidget *window, const QString &text, int timeout )
+{
+ KWindowInfo *info = new KWindowInfo( window );
+ info->autoDel = true;
+ info->message( text, timeout );
+ if ( timeout == 0 )
+ delete info;
+}
+
+void KWindowInfo::showMessage( QWidget *window, const QString &text, const QPixmap &pix, int timeout )
+{
+ KWindowInfo *info = new KWindowInfo( window );
+ info->autoDel = true;
+ info->message( text, pix, timeout );
+}
+
+void KWindowInfo::message( const QString &text )
+{
+ message( text, QPixmap(), UNSPECIFIED_TIMEOUT );
+}
+
+void KWindowInfo::message( const QString &text, const QPixmap &pix )
+{
+ message( text, pix, UNSPECIFIED_TIMEOUT );
+}
+
+void KWindowInfo::message( const QString &text, int timeout )
+{
+ message( text, QPixmap(), timeout );
+}
+
+void KWindowInfo::message( const QString &text, const QPixmap &pix, int timeout )
+{
+ if ( timeout != 0 )
+ save();
+
+ display( text, pix );
+
+ if ( timeout < 0 )
+ timeout = DEFAULT_MESSAGE_TIMEOUT;
+ if ( timeout != 0 )
+ QTimer::singleShot( timeout, this, SLOT( restore() ) );
+}
+
+void KWindowInfo::permanent( const QString &text )
+{
+#ifdef Q_WS_X11
+ oldMiniIcon = KWin::icon( win->winId(), 16, 16, true );
+ oldIcon = KWin::icon( win->winId(), 34, 34, false );
+ if ( oldIcon.isNull() )
+ oldIcon = KWin::icon( win->winId(), 32, 32, true );
+#endif
+
+ permanent( text, oldIcon );
+}
+
+void KWindowInfo::permanent( const QString &text, const QPixmap &pix )
+{
+ if ( !oldText.isNull() ) {
+ QObjectList *l = queryList( "QTimer" );
+ QObjectListIt it( *l );
+ QObject *obj;
+
+ while ( (obj = it.current()) != 0 ) {
+ ++it;
+ delete obj;
+ }
+ delete l;
+ }
+
+ oldText = QString::null;
+ display( text, pix );
+}
+
+void KWindowInfo::display( const QString &text, const QPixmap &pix )
+{
+ QPixmap icon;
+ if ( pix.isNull() )
+ icon.load( "bell.png" );
+ else
+ icon = pix;
+
+ if ( win->inherits( "KSystemTray" ) ) {
+ KSystemTray *tray = static_cast<KSystemTray *>( win );
+ tray->setPixmap( icon );
+ QToolTip::add( tray, text );
+ return;
+ }
+
+ win->setCaption( text );
+ win->setIcon( icon );
+#ifdef Q_WS_X11
+ KWin::setIcons( win->winId(), icon, icon );
+#endif
+}
+
+void KWindowInfo::save()
+{
+ if ( !oldText.isNull() )
+ return;
+
+ if ( win->inherits( "KSystemTray" ) ) {
+ KSystemTray *tray = static_cast<KSystemTray *>( win );
+ oldIcon = *(tray->pixmap());
+ oldText = QToolTip::textFor( tray );
+ return;
+ }
+
+ oldText = win->caption();
+#ifdef Q_WS_X11
+ oldMiniIcon = KWin::icon( win->winId(), 16, 16, true );
+ oldIcon = KWin::icon( win->winId(), 34, 34, false );
+ if ( oldIcon.isNull() )
+ oldIcon = KWin::icon( win->winId(), 32, 32, true );
+#endif
+
+ if ( oldIcon.isNull() ) {
+ const QPixmap *px = win->icon();
+ if ( px )
+ oldIcon = *px;
+ else
+ oldIcon.resize( 0, 0 );
+ }
+}
+
+void KWindowInfo::restore()
+{
+ if ( win->inherits( "KSystemTray" ) ) {
+ KSystemTray *tray = static_cast<KSystemTray *>( win );
+ tray->setPixmap( oldIcon );
+ QToolTip::add( tray, oldText );
+ oldText = QString::null;
+ return;
+ }
+
+ win->setIcon( oldIcon );
+#ifdef Q_WS_X11
+ KWin::setIcons( win->winId(), oldIcon, oldMiniIcon );
+#endif
+ win->setCaption( oldText );
+ oldText = QString::null;
+
+ if ( autoDel )
+ delete this;
+}
+
+
+
+
+
diff --git a/kdeui/kwindowinfo.h b/kdeui/kwindowinfo.h
new file mode 100644
index 000000000..c419a41d3
--- /dev/null
+++ b/kdeui/kwindowinfo.h
@@ -0,0 +1,145 @@
+// -*- c++ -*-
+
+/*
+ * copyright : (C) 2001-2002 by Richard Moore
+ * License : This file is released under the terms of the LGPL, version 2.
+ * email : rich@kde.org
+ */
+
+#ifndef KWINDOWINFO_H
+#define KWINDOWINFO_H
+
+#include <qobject.h>
+#include <qpixmap.h>
+#include <qstring.h>
+
+#include <kdelibs_export.h>
+
+/**
+ * Displays messages in the window icon and title. The message is usually
+ * transient with the original title and icon being restored automatically
+ * after a specified time. The simplest use displays a text message in the
+ * window title:
+ * \code
+ * KWindowInfo::showMessage( this, i18n("Message Body") );
+ * \endcode
+ * This more complex example changes the window icon, as well as
+ * displaying the text. In addition, this example overrides the
+ * default timeout to ensure the message is only displayed for 1
+ * second.
+ * \code
+ * QPixmap px;
+ * px.load( "lo16-app-logtracker.png" );
+ * KWindowInfo::showMessage( this, i18n("Message Body"), px, 1000 );
+ * \endcode
+ * If the parent window inherits KSystemTray then KWindowInfo changes the
+ * pixmap and tooltip of the system window to display the message.
+ *
+ * @author Richard Moore, rich@kde.org
+ * @since 3.1
+*/
+class KDEUI_EXPORT KWindowInfo : public QObject
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Creates a KWindowInfo with the specified parent.
+ */
+ KWindowInfo( QWidget *parent, const char *name=0 );
+
+ /**
+ * Cleans up.
+ */
+ virtual ~KWindowInfo();
+
+ /**
+ * Returns true iff the object should delete itself when it resets.
+ */
+ bool autoDelete() const { return autoDel; }
+
+ /**
+ * Set to true if you want the object to delete itself when the message
+ * timeout occurs.
+ */
+ void setAutoDelete( bool enable ) { autoDel = enable; }
+
+ /**
+ * Utility method to display a title bar message for the specified
+ * window.
+ */
+ static void showMessage( QWidget *window, const QString &text, int timeout = -1 );
+
+ /**
+ * Utility method to display a title bar message and icon for the
+ * specified window.
+ */
+ static void showMessage( QWidget *window, const QString &text,
+ const QPixmap &pix, int timeout = -1 );
+
+public slots:
+ /**
+ * Shows the specified text in the window title.
+ */
+ void message( const QString &text );
+
+ /**
+ * Shows the specified text in the window title, and sets the window icon.
+ */
+ void message( const QString &text, const QPixmap &pix );
+
+ /**
+ * Shows the specified text in the window title for the specified time.
+ */
+ void message( const QString &text, int timeout );
+
+ /**
+ * Shows the specified icon and text in the window title and WM
+ * icon, for the specified time. The time is a delay specified in
+ * milliseconds, or one of the two special values. The special
+ * values are -1 which means the default timeout should be used,
+ * and 0 which means the message is permanent.
+ */
+ void message( const QString &text, const QPixmap &pix, int timeout );
+
+ /**
+ * Shows the specified text in the window title with no timeout.
+ */
+ void permanent( const QString &text );
+
+ /**
+ * Shows the specified text and icon in the window title with no timeout.
+ */
+ void permanent( const QString &text, const QPixmap &pix );
+
+protected:
+ /**
+ * Displays the message in the titlebar/icon.
+ */
+ virtual void display( const QString &text, const QPixmap &pix );
+
+protected slots:
+ /**
+ * Saves the window title and icon.
+ */
+ virtual void save();
+
+ /**
+ * Resets the window title and icon to the saved values. If
+ * auto-delete is enabled then the object is deleted.
+ */
+ virtual void restore();
+
+private:
+ QWidget *win;
+ QPixmap oldIcon;
+ QPixmap oldMiniIcon;
+ QString oldText;
+ bool autoDel;
+
+ /* @internal */
+ class Private *d;
+};
+
+#endif // KWINDOWINFO_H
+
diff --git a/kdeui/kwindowlistmenu.cpp b/kdeui/kwindowlistmenu.cpp
new file mode 100644
index 000000000..8167bcdae
--- /dev/null
+++ b/kdeui/kwindowlistmenu.cpp
@@ -0,0 +1,257 @@
+/*****************************************************************
+
+Copyright (c) 2000 Matthias Elter <elter@kde.org>
+ Matthias Ettrich <ettrich@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qglobal.h>
+
+#ifdef Q_WS_X11
+
+#include "config.h"
+#include <qpainter.h>
+#include <qvaluelist.h>
+
+#include <kwin.h>
+#include <kwinmodule.h>
+
+#include <klocale.h>
+#include <kstringhandler.h>
+
+#include <netwm.h>
+#include <kapplication.h>
+#include <kstyle.h>
+#include <dcopclient.h>
+
+#undef Bool
+#include "kwindowlistmenu.h"
+#include "kwindowlistmenu.moc"
+
+static QCString kwinName() {
+ QCString appname;
+ int screen_number = DefaultScreen(qt_xdisplay());
+ if (screen_number == 0)
+ appname = "kwin";
+ else
+ appname.sprintf("kwin-screen-%d", screen_number);
+ return appname;
+}
+
+// helper class
+namespace
+{
+class NameSortedInfoList : public QPtrList<KWin::WindowInfo>
+{
+public:
+ NameSortedInfoList() { setAutoDelete(true); }
+ ~NameSortedInfoList() {}
+
+private:
+ int compareItems( QPtrCollection::Item s1, QPtrCollection::Item s2 );
+};
+
+int NameSortedInfoList::compareItems( QPtrCollection::Item s1, QPtrCollection::Item s2 )
+{
+ KWin::WindowInfo *i1 = static_cast<KWin::WindowInfo *>(s1);
+ KWin::WindowInfo *i2 = static_cast<KWin::WindowInfo *>(s2);
+ QString title1, title2;
+ if (i1)
+ title1 = i1->visibleNameWithState().lower();
+ if (i2)
+ title2 = i2->visibleNameWithState().lower();
+ return title1.compare(title2);
+}
+
+} // namespace
+
+KWindowListMenu::KWindowListMenu(QWidget *parent, const char *name)
+ : KPopupMenu(parent, name)
+{
+ kwin_module = new KWinModule(this);
+
+ connect(this, SIGNAL(activated(int)), SLOT(slotExec(int)));
+}
+
+KWindowListMenu::~KWindowListMenu()
+{
+
+}
+
+static bool standaloneDialog( const KWin::WindowInfo* info, const NameSortedInfoList& list )
+{
+ WId group = info->groupLeader();
+ if( group == 0 )
+ {
+ return info->transientFor() == qt_xrootwin();
+ }
+ for( QPtrListIterator< KWin::WindowInfo > it( list );
+ it.current() != NULL;
+ ++it )
+ if( (*it)->groupLeader() == group )
+ return false;
+ return true;
+}
+
+void KWindowListMenu::init()
+{
+ int i, d;
+ i = 0;
+
+ int nd = kwin_module->numberOfDesktops();
+ int cd = kwin_module->currentDesktop();
+ WId active_window = kwin_module->activeWindow();
+
+ // Make sure the popup is not too wide, otherwise clicking in the middle of kdesktop
+ // wouldn't leave any place for the popup, and release would activate some menu entry.
+ int maxwidth = kapp->desktop()->screenGeometry( this ).width() / 2 - 100;
+
+ clear();
+ map.clear();
+
+ int unclutter = insertItem( i18n("Unclutter Windows"),
+ this, SLOT( slotUnclutterWindows() ) );
+ int cascade = insertItem( i18n("Cascade Windows"),
+ this, SLOT( slotCascadeWindows() ) );
+
+ // if we only have one desktop we won't be showing titles, so put a separator in
+ if (nd == 1)
+ {
+ insertSeparator();
+ }
+
+
+ QValueList<KWin::WindowInfo> windows;
+ for (QValueList<WId>::ConstIterator it = kwin_module->windows().begin();
+ it != kwin_module->windows().end(); ++it) {
+ windows.append( KWin::windowInfo( *it, NET::WMDesktop ));
+ }
+ bool show_all_desktops_group = ( nd > 1 );
+ for (d = 1; d <= nd + (show_all_desktops_group ? 1 : 0); d++) {
+ bool on_all_desktops = ( d > nd );
+ int items = 0;
+
+ if (!active_window && d == cd)
+ setItemChecked(1000 + d, true);
+
+ NameSortedInfoList list;
+ list.setAutoDelete(true);
+
+ for (QValueList<KWin::WindowInfo>::ConstIterator it = windows.begin();
+ it != windows.end(); ++it) {
+ if (((*it).desktop() == d) || (on_all_desktops && (*it).onAllDesktops())
+ || (!show_all_desktops_group && (*it).onAllDesktops())) {
+ list.inSort(new KWin::WindowInfo( (*it).win(),
+ NET::WMVisibleName | NET::WMState | NET::XAWMState | NET::WMWindowType,
+ NET::WM2GroupLeader | NET::WM2TransientFor ));
+ }
+ }
+
+ for (KWin::WindowInfo* info = list.first(); info; info = list.next(), ++i)
+ {
+ QString itemText = KStringHandler::cPixelSqueeze(info->visibleNameWithState(), fontMetrics(), maxwidth);
+ NET::WindowType windowType = info->windowType( NET::NormalMask | NET::DesktopMask
+ | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask
+ | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask );
+ if ( (windowType == NET::Normal || windowType == NET::Unknown
+ || (windowType == NET::Dialog && standaloneDialog( info, list )))
+ && !(info->state() & NET::SkipTaskbar) ) {
+ QPixmap pm = KWin::icon(info->win(), 16, 16, true );
+ items++;
+
+ // ok, we have items on this desktop, let's show the title
+ if ( items == 1 && nd > 1 )
+ {
+ if( !on_all_desktops )
+ insertTitle(kwin_module->desktopName( d ), 1000 + d);
+ else
+ insertTitle(i18n("On All Desktops"), 2000 );
+ }
+
+ // Avoid creating unwanted accelerators.
+ itemText.replace('&', QString::fromLatin1("&&"));
+ insertItem( pm, itemText, i);
+ map.insert(i, info->win());
+ if (info->win() == active_window)
+ setItemChecked(i, true);
+ }
+ }
+
+ if (d == cd)
+ {
+ setItemEnabled(unclutter, items > 0);
+ setItemEnabled(cascade, items > 0);
+ }
+ }
+
+ // no windows?
+ if (i == 0)
+ {
+ if (nd > 1)
+ {
+ // because we don't have any titles, nor a separator
+ insertSeparator();
+ }
+
+ setItemEnabled(insertItem(i18n("No Windows")), false);
+ }
+}
+
+void KWindowListMenu::slotExec(int id)
+{
+ if (id == 2000)
+ ; // do nothing
+ else if (id > 1000)
+ KWin::setCurrentDesktop(id - 1000);
+ else if ( id >= 0 )
+ KWin::forceActiveWindow(map[id]);
+}
+
+// This popup is much more useful from keyboard if it has the active
+// window active by default - however, QPopupMenu tries hard to resist.
+// QPopupMenu::popup() resets the active item, so this needs to be
+// called after popup().
+void KWindowListMenu::selectActiveWindow()
+{
+ for( unsigned int i = 0;
+ i < count();
+ ++i )
+ if( isItemChecked( idAt( i )))
+ {
+ setActiveItem( i );
+ break;
+ }
+}
+
+void KWindowListMenu::slotUnclutterWindows()
+{
+ kapp->dcopClient()->send(kwinName(), "KWinInterface", "unclutterDesktop()", "");
+}
+
+void KWindowListMenu::slotCascadeWindows()
+{
+ kapp->dcopClient()->send(kwinName(), "KWinInterface", "cascadeDesktop()", "");
+}
+
+void KWindowListMenu::virtual_hook( int id, void* data )
+{ KPopupMenu::virtual_hook( id, data ); }
+
+#endif // Q_WS_X11
+
diff --git a/kdeui/kwindowlistmenu.h b/kdeui/kwindowlistmenu.h
new file mode 100644
index 000000000..8e63ed59e
--- /dev/null
+++ b/kdeui/kwindowlistmenu.h
@@ -0,0 +1,70 @@
+/*****************************************************************
+
+Copyright (c) 2000 Matthias Elter <elter@kde.org>
+ Matthias Ettrich <ettrich@kde.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __kwindowlistmenu_h__
+#define __kwindowlistmenu_h__
+
+#include <kpopupmenu.h>
+#include <qmap.h>
+
+#ifdef Q_WS_X11 // not yet available for non-X11
+
+class KWinModule;
+class KWindowListMenuPrivate;
+
+class KDEUI_EXPORT KWindowListMenu : public KPopupMenu
+{
+ Q_OBJECT
+
+public:
+ KWindowListMenu( QWidget *parent = 0, const char *name = 0 );
+ virtual ~KWindowListMenu();
+
+ void init();
+
+public slots:
+ /**
+ * Pre-selects the active window in the popup menu, for faster
+ * keyboard navigation. Needs to be called after popup().
+ * Should not be used when the popup is invoked using the mouse.
+ */
+ void selectActiveWindow();
+
+protected slots:
+ void slotExec(int id);
+ void slotUnclutterWindows();
+ void slotCascadeWindows();
+
+private:
+ KWinModule* kwin_module;
+ QMap<int,WId> map;
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KWindowListMenuPrivate *d;
+};
+
+#endif // Q_WS_X11
+
+#endif
diff --git a/kdeui/kwizard.cpp b/kdeui/kwizard.cpp
new file mode 100644
index 000000000..80443fead
--- /dev/null
+++ b/kdeui/kwizard.cpp
@@ -0,0 +1,57 @@
+/* This file is part of the KDE Libraries
+ Copyright ( C ) 2002 Nadeem Hasan ( nhasan@kde.org )
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or ( at your option ) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qstring.h>
+#include <qapplication.h>
+#include <qpushbutton.h>
+
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kglobalsettings.h>
+#include <kstdguiitem.h>
+
+#include "kwizard.h"
+
+KWizard::KWizard( QWidget *parent, const char *name, bool modal, WFlags f )
+ : QWizard( parent, name, modal, f )
+{
+ bool useIcons = KGlobalSettings::showIconsOnPushButtons();
+
+ if ( useIcons )
+ {
+ KGuiItem back = KStdGuiItem::back( KStdGuiItem::UseRTL );
+ KGuiItem forward = KStdGuiItem::forward( KStdGuiItem::UseRTL );
+
+ backButton()->setIconSet( back.iconSet() );
+ nextButton()->setIconSet( forward.iconSet() );
+
+ finishButton()->setIconSet( SmallIconSet( "apply" ) );
+ cancelButton()->setIconSet( SmallIconSet( "button_cancel" ) );
+ helpButton()->setIconSet( SmallIconSet( "help" ) );
+
+ backButton()->setText( i18n( "&Back" ) );
+ nextButton()->setText( i18n( "Opposite to Back","&Next" ) );
+ }
+
+ QFont font = titleFont();
+ font.setBold( true );
+ setTitleFont( font );
+}
+
+#include "kwizard.moc"
diff --git a/kdeui/kwizard.h b/kdeui/kwizard.h
new file mode 100644
index 000000000..d9d1e05a1
--- /dev/null
+++ b/kdeui/kwizard.h
@@ -0,0 +1,62 @@
+/* This file is part of the KDE Libraries
+ Copyright (C) 1999 Harri Porten (porten@kde.org)
+
+ Replacement for KWizard from KDE 1.x.
+ Copyright (C) 1998 Thomas Tanghus (tanghus@earthling.net)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __KWIZARD_H
+#define __KWIZARD_H
+
+#include <qwizard.h>
+
+#include <kdelibs_export.h>
+
+/**
+* General-purpose multi-page dialog.
+*
+* KWizard is a class for a multi-page dialog. The user can navigate trough
+* the pages with "Next" and "Back" buttons and is optionally offered "Finish",
+* "Cancel" and "Help" buttons. A wizard comes in handy for tutorials or
+* configuration dialogs with sequential steps.
+*
+* KWizard is just a wrapper for Qt's QWizard class. See the
+* QWizard documentation for a detailed description of available
+* functions. The only added functionality is a KDE conformant translation
+* mechanism for the built-in buttons.
+*
+* @author Harri Porten <porten@kde.org>
+* @version 0.3
+*/
+class KDEUI_EXPORT KWizard : public QWizard
+{
+ Q_OBJECT
+public:
+/**
+* Constructor
+*/
+ KWizard(QWidget *parent = 0, const char *name = 0, bool modal = false, WFlags f = 0);
+/**
+* Destructor
+*/
+ ~KWizard() {}
+};
+
+#endif // __KWIZARD_H
+
+
diff --git a/kdeui/kwordwrap.cpp b/kdeui/kwordwrap.cpp
new file mode 100644
index 000000000..4b2e801d0
--- /dev/null
+++ b/kdeui/kwordwrap.cpp
@@ -0,0 +1,269 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2001 David Faure <david@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kwordwrap.h"
+#include <kdebug.h>
+#include <kstringhandler.h>
+#include <qpainter.h>
+
+class KWordWrapPrivate {
+public:
+ QRect m_constrainingRect;
+};
+
+KWordWrap::KWordWrap(const QRect & r) {
+ d = new KWordWrapPrivate;
+ d->m_constrainingRect = r;
+}
+
+KWordWrap* KWordWrap::formatText( QFontMetrics &fm, const QRect & r, int /*flags*/, const QString & str, int len )
+{
+ KWordWrap* kw = new KWordWrap( r );
+ // The wordwrap algorithm
+ // The variable names and the global shape of the algorithm are inspired
+ // from QTextFormatterBreakWords::format().
+ //kdDebug() << "KWordWrap::formatText " << str << " r=" << r.x() << "," << r.y() << " " << r.width() << "x" << r.height() << endl;
+ int height = fm.height();
+ if ( len == -1 )
+ kw->m_text = str;
+ else
+ kw->m_text = str.left( len );
+ if ( len == -1 )
+ len = str.length();
+ int lastBreak = -1;
+ int lineWidth = 0;
+ int x = 0;
+ int y = 0;
+ int w = r.width();
+ int textwidth = 0;
+ bool isBreakable = false;
+ bool wasBreakable = false; // value of isBreakable for last char (i-1)
+ bool isParens = false; // true if one of ({[
+ bool wasParens = false; // value of isParens for last char (i-1)
+
+ for ( int i = 0 ; i < len; ++i )
+ {
+ QChar c = str[i];
+ int ww = fm.charWidth( str, i );
+
+ isParens = ( c == '(' || c == '[' || c == '{' );
+ // isBreakable is true when we can break _after_ this character.
+ isBreakable = ( c.isSpace() || c.isPunct() || c.isSymbol() ) & !isParens;
+
+ // Special case for '(', '[' and '{': we want to break before them
+ if ( !isBreakable && i < len-1 ) {
+ QChar nextc = str[i+1]; // look at next char
+ isBreakable = ( nextc == '(' || nextc == '[' || nextc == '{' );
+ }
+ // Special case for '/': after normal chars it's breakable (e.g. inside a path),
+ // but after another breakable char it's not (e.g. "mounted at /foo")
+ // Same thing after a parenthesis (e.g. "dfaure [/fool]")
+ if ( c == '/' && (wasBreakable || wasParens) )
+ isBreakable = false;
+
+ /*kdDebug() << "c='" << QString(c) << "' i=" << i << "/" << len
+ << " x=" << x << " ww=" << ww << " w=" << w
+ << " lastBreak=" << lastBreak << " isBreakable=" << isBreakable << endl;*/
+ int breakAt = -1;
+ if ( x + ww > w && lastBreak != -1 ) // time to break and we know where
+ breakAt = lastBreak;
+ if ( x + ww > w - 4 && lastBreak == -1 ) // time to break but found nowhere [-> break here]
+ breakAt = i;
+ if ( i == len - 2 && x + ww + fm.charWidth( str, i+1 ) > w ) // don't leave the last char alone
+ breakAt = lastBreak == -1 ? i - 1 : lastBreak;
+ if ( c == '\n' ) // Forced break here
+ {
+ if ( breakAt == -1 && lastBreak != -1) // only break if not already breaking
+ {
+ breakAt = i - 1;
+ lastBreak = -1;
+ }
+ // remove the line feed from the string
+ kw->m_text.remove(i, 1);
+ len--;
+ }
+ if ( breakAt != -1 )
+ {
+ //kdDebug() << "KWordWrap::formatText breaking after " << breakAt << endl;
+ kw->m_breakPositions.append( breakAt );
+ int thisLineWidth = lastBreak == -1 ? x + ww : lineWidth;
+ kw->m_lineWidths.append( thisLineWidth );
+ textwidth = QMAX( textwidth, thisLineWidth );
+ x = 0;
+ y += height;
+ wasBreakable = true;
+ wasParens = false;
+ if ( lastBreak != -1 )
+ {
+ // Breakable char was found, restart from there
+ i = lastBreak;
+ lastBreak = -1;
+ continue;
+ }
+ } else if ( isBreakable )
+ {
+ lastBreak = i;
+ lineWidth = x + ww;
+ }
+ x += ww;
+ wasBreakable = isBreakable;
+ wasParens = isParens;
+ }
+ textwidth = QMAX( textwidth, x );
+ kw->m_lineWidths.append( x );
+ y += height;
+ //kdDebug() << "KWordWrap::formatText boundingRect:" << r.x() << "," << r.y() << " " << textwidth << "x" << y << endl;
+ if ( r.height() >= 0 && y > r.height() )
+ textwidth = r.width();
+ int realY = y;
+ if ( r.height() >= 0 )
+ {
+ while ( realY > r.height() )
+ realY -= height;
+ realY = QMAX( realY, 0 );
+ }
+ kw->m_boundingRect.setRect( 0, 0, textwidth, realY );
+ return kw;
+}
+
+KWordWrap::~KWordWrap() {
+ delete d;
+}
+
+QString KWordWrap::wrappedString() const
+{
+ // We use the calculated break positions to insert '\n' into the string
+ QString ws;
+ int start = 0;
+ QValueList<int>::ConstIterator it = m_breakPositions.begin();
+ for ( ; it != m_breakPositions.end() ; ++it )
+ {
+ int end = (*it);
+ ws += m_text.mid( start, end - start + 1 ) + '\n';
+ start = end + 1;
+ }
+ ws += m_text.mid( start );
+ return ws;
+}
+
+QString KWordWrap::truncatedString( bool dots ) const
+{
+ if ( m_breakPositions.isEmpty() )
+ return m_text;
+
+ QString ts = m_text.left( m_breakPositions.first() + 1 );
+ if ( dots )
+ ts += "...";
+ return ts;
+}
+
+static QColor mixColors(double p1, QColor c1, QColor c2) {
+ return QColor(int(c1.red() * p1 + c2.red() * (1.0-p1)),
+ int(c1.green() * p1 + c2.green() * (1.0-p1)),
+ int(c1.blue() * p1 + c2.blue() * (1.0-p1)));
+}
+
+void KWordWrap::drawFadeoutText(QPainter *p, int x, int y, int maxW,
+ const QString &t) {
+ QFontMetrics fm = p->fontMetrics();
+ QColor bgColor = p->backgroundColor();
+ QColor textColor = p->pen().color();
+
+ if ( ( fm.boundingRect( t ).width() > maxW ) && ( t.length() > 1 ) ) {
+ unsigned int tl = 0;
+ int w = 0;
+ while ( tl < t.length() ) {
+ w += fm.charWidth( t, tl );
+ if ( w >= maxW )
+ break;
+ tl++;
+ }
+
+ if (tl > 3) {
+ p->drawText( x, y, t.left( tl - 3 ) );
+ x += fm.width( t.left( tl - 3 ) );
+ }
+ int n = QMIN( tl, 3);
+ for (int i = 0; i < n; i++) {
+ p->setPen( mixColors( 0.70 - i * 0.25, textColor, bgColor ) );
+ QString s( t.at( tl - n + i ) );
+ p->drawText( x, y, s );
+ x += fm.width( s );
+ }
+ }
+ else
+ p->drawText( x, y, t );
+}
+
+void KWordWrap::drawTruncateText(QPainter *p, int x, int y, int maxW,
+ const QString &t) {
+ QString tmpText = KStringHandler::rPixelSqueeze( t, p->fontMetrics(), maxW );
+ p->drawText( x, y, tmpText, maxW );
+}
+
+void KWordWrap::drawText( QPainter *painter, int textX, int textY, int flags ) const
+{
+ //kdDebug() << "KWordWrap::drawText text=" << wrappedString() << " x=" << textX << " y=" << textY << endl;
+ // We use the calculated break positions to draw the text line by line using QPainter
+ int start = 0;
+ int y = 0;
+ QFontMetrics fm = painter->fontMetrics();
+ int height = fm.height(); // line height
+ int ascent = fm.ascent();
+ int maxwidth = m_boundingRect.width();
+ QValueList<int>::ConstIterator it = m_breakPositions.begin();
+ QValueList<int>::ConstIterator itw = m_lineWidths.begin();
+ for ( ; it != m_breakPositions.end() ; ++it, ++itw )
+ {
+ // if this is the last line, leave the loop
+ if ( (d->m_constrainingRect.height() >= 0) &&
+ ((y + 2 * height) > d->m_constrainingRect.height()) )
+ break;
+ int end = (*it);
+ int x = textX;
+ if ( flags & Qt::AlignHCenter )
+ x += ( maxwidth - *itw ) / 2;
+ else if ( flags & Qt::AlignRight )
+ x += maxwidth - *itw;
+ painter->drawText( x, textY + y + ascent, m_text.mid( start, end - start + 1 ) );
+ y += height;
+ start = end + 1;
+ }
+ // Draw the last line
+ int x = textX;
+ if ( flags & Qt::AlignHCenter )
+ x += ( maxwidth - *itw ) / 2;
+ else if ( flags & Qt::AlignRight )
+ x += maxwidth - *itw;
+ if ( (d->m_constrainingRect.height() < 0) ||
+ ((y + height) <= d->m_constrainingRect.height()) ) {
+ if ( it == m_breakPositions.end() )
+ painter->drawText( x, textY + y + ascent, m_text.mid( start ) );
+ else if (flags & FadeOut)
+ drawFadeoutText( painter, textX, textY + y + ascent,
+ d->m_constrainingRect.width(),
+ m_text.mid( start ) );
+ else if (flags & Truncate)
+ drawTruncateText( painter, textX, textY + y + ascent,
+ d->m_constrainingRect.width(),
+ m_text.mid( start ) );
+ else
+ painter->drawText( x, textY + y + ascent,
+ m_text.mid( start, (*it) - start + 1 ) );
+ }
+}
diff --git a/kdeui/kwordwrap.h b/kdeui/kwordwrap.h
new file mode 100644
index 000000000..676000789
--- /dev/null
+++ b/kdeui/kwordwrap.h
@@ -0,0 +1,149 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2001 David Faure <david@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef kwordwrap_h
+#define kwordwrap_h
+
+#include <qfontmetrics.h>
+#include <qvaluelist.h>
+#include <qrect.h>
+#include <qstring.h>
+
+#include <kdelibs_export.h>
+
+/**
+ * Word-wrap algorithm that takes into account beautifulness ;)
+ *
+ * That means:
+ * @li not letting a letter alone on the last line,
+ * @li breaking at punctuation signs (not only at spaces)
+ * @li improved handling of (), [] and {}
+ * @li improved handling of '/' (e.g. for paths)
+ *
+ * Usage: call the static method, formatText, with the text to
+ * wrap and the constraining rectangle etc., it will return an instance of KWordWrap
+ * containing internal data, result of the word-wrapping.
+ * From that instance you can retrieve the boundingRect, and invoke drawing.
+ *
+ * This design allows to call the word-wrap algorithm only when the text changes
+ * and not every time we want to know the bounding rect or draw the text.
+ *
+ * @author David Faure <faure@kde.org>
+ */
+class KDEUI_EXPORT KWordWrap
+{
+public:
+ /**
+ * Use this flag in drawText() if you want to fade out the text if it does
+ * not fit into the constraining rectangle.
+ * @since 3.2
+ */
+ enum { FadeOut = 0x10000000, Truncate = 0x20000000 };
+
+ /**
+ * Main method for wrapping text.
+ *
+ * @param fm Font metrics, for the chosen font. Better cache it, creating a QFontMetrics is expensive.
+ * @param r Constraining rectangle. Only the width and height matter. With
+ * negative height the complete text will be rendered
+ * @param flags currently unused
+ * @param str The text to be wrapped.
+ * @param len Length of text to wrap (default is -1 for all).
+ * @return a KWordWrap instance. The caller is responsible for storing and deleting the result.
+ */
+ static KWordWrap* formatText( QFontMetrics &fm, const QRect & r, int flags, const QString & str, int len = -1 );
+
+ /**
+ * @return the bounding rect, calculated by formatText. The width is the
+ * width of the widest text line, and never wider than
+ * the rectangle given to formatText. The height is the
+ * text block. X and Y are always 0.
+ */
+ QRect boundingRect() const { return m_boundingRect; }
+
+ /**
+ * @return the original string, with '\n' inserted where
+ * the text is broken by the wordwrap algorithm.
+ */
+ QString wrappedString() const; // gift for Dirk :)
+
+ /**
+ * @return the original string, truncated to the first line.
+ * If @p dots was set, '...' is appended in case the string was truncated.
+ * Bug: Note that the '...' come out of the bounding rect.
+ */
+ QString truncatedString( bool dots = true ) const;
+
+ /**
+ * Draw the text that has been previously wrapped, at position x,y.
+ * Flags are for alignment, e.g. Qt::AlignHCenter. Default is
+ * Qt::AlignAuto.
+ * @param painter the QPainter to use.
+ * @param x the horizontal position of the text
+ * @param y the vertical position of the text
+ * @param flags the ORed text alignment flags from the Qt namespace,
+ * ORed with FadeOut if you want the text to fade out if it
+ * does not fit (the @p painter's background must be set
+ * accordingly)
+ */
+ void drawText( QPainter *painter, int x, int y, int flags = Qt::AlignAuto ) const;
+
+ /**
+ * Destructor.
+ */
+ ~KWordWrap();
+
+ /**
+ * Draws the string @p t at the given coordinates, if it does not
+ * @p fit into @p maxW the text will be faded out.
+ * @param p the painter to use. Must have set the pen for the text
+ * color and the background for the color to fade out
+ * @param x the horizontal position of the text
+ * @param y the vertical position of the text
+ * @param maxW the maximum width of the text (including the fade-out
+ * effect)
+ * @param t the text to draw
+ * @since 3.2
+ */
+ static void drawFadeoutText( QPainter *p, int x, int y, int maxW,
+ const QString &t );
+
+ /**
+ * Draws the string @p t at the given coordinates, if it does not
+ * @p fit into @p maxW the text will be truncated.
+ * @param p the painter to use
+ * @param x the horizontal position of the text
+ * @param y the vertical position of the text
+ * @param maxW the maximum width of the text (including the '...')
+ * @param t the text to draw
+ * @since 3.3
+ */
+ static void drawTruncateText( QPainter *p, int x, int y, int maxW,
+ const QString &t );
+
+private:
+ KWordWrap( const QRect & r );
+ QValueList<int> m_breakPositions;
+ QValueList<int> m_lineWidths;
+ QRect m_boundingRect;
+ QString m_text;
+private:
+ class KWordWrapPrivate* d;
+};
+
+#endif
diff --git a/kdeui/kxmlgui.h b/kdeui/kxmlgui.h
new file mode 100644
index 000000000..c5196e419
--- /dev/null
+++ b/kdeui/kxmlgui.h
@@ -0,0 +1,6 @@
+#ifndef KDE_NO_COMPAT
+#ifndef __KXMLGUI_H_
+#define __KXMLGUI_H_
+#include <kxmlguifactory.h>
+#endif
+#endif
diff --git a/kdeui/kxmlgui.xsd b/kdeui/kxmlgui.xsd
new file mode 100644
index 000000000..c0979cb72
--- /dev/null
+++ b/kdeui/kxmlgui.xsd
@@ -0,0 +1,445 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!-- kxmlgui XSD v1.0 -->
+<xsd:schema
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns="http://www.kde.org/standards/kxmlgui/1.0"
+ targetNamespace="http://www.kde.org/standards/kxmlgui/1.0"
+ version="1.0"
+ elementFormDefault="qualified" >
+
+ <xsd:annotation>
+ <xsd:documentation>
+ * Originally Copyright (c) 2000 Federico David Sacerdoti &gt;tech@slinuxmachines.com&lt;
+ * Modifications/Extensions Simon Hausmann &gt;hausmann@kde.org&lt;
+ * Minor updates Richard J. Moore &gt;rich@kde.org&lt;
+ * Conversion to XSD (c) 2004 Frans Englich &lt;frans.englich@telia.com&gt;
+
+ Permission to use, copy, modify and distribute this XSD
+ and its accompanying documentation for any purpose and without fee
+ is hereby granted in perpetuity, provided that the above copyright
+ notice and this paragraph appear in all copies. The copyright
+ holders make no representation about the suitability of the XSD for
+ any purpose. It is provided "as is" without expressed or implied
+ warranty.
+
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:annotation>
+ <xsd:documentation>
+
+ This is the XML Schema for KDE's XMLGUI framework, a way of describing a
+ application's Graphical User Interface in an XML file.
+
+ A document instance of this Schema should have a declaration
+ looking like this:
+
+ <![CDATA[
+
+ <?xml version="1.0" encoding="UTF-8" ?>
+ <gui name=""
+ version=""
+ xmlns="http://www.kde.org/standards/kxmlgui/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kxmlgui/1.0
+ http://www.kde.org/standards/kxmlgui/1.0/kxmlgui.xsd" >
+ <!-- the content -->
+ </gui>
+
+ ]]>
+
+ Where the name and version tag is of your taste.
+
+ </xsd:documentation>
+ </xsd:annotation>
+
+ <xsd:simpleType name="identifier">
+ <xsd:annotation>
+ <xsd:documentation>
+
+ The name used for every name and group attribute. Maps to QObject::name() in most cases.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:Name">
+ <!-- TODO Restrict harder, perhaps? -->
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:element name="Separator">
+ <xsd:annotation>
+ <xsd:documentation>
+
+ Inserts a separator item into a menubar or toolbar.
+
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:attribute name="lineSeparator" default="true" type="xsd:boolean"/>
+ <xsd:attribute name="group" type="identifier"/>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="WeakSeparator">
+ <xsd:annotation>
+ <xsd:documentation>
+
+ TODO Docs. What am I?
+
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+
+ <xsd:element name="Merge">
+ <xsd:complexType>
+ <xsd:attribute name="name" type="identifier" use="optional" />
+ </xsd:complexType>
+ <!-- Merge, MergeLocal and other more exotic elements are everywhere. Cannot more than one(etc.) occur in the various places, such as Menu? Needs fixing then - better restriction on how many of those elements that can appear where. -->
+ </xsd:element>
+
+ <xsd:element name="MergeLocal">
+ <xsd:annotation>
+ <xsd:documentation>
+
+ Specifies an entry index for merging application defined actions into
+ those with positions fixed by the style guide and ui_standards.rc. This
+ tag should not be used anywhere except ui_standards.rc.
+
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:attribute name="name" type="identifier" use="optional" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="DefineGroup">
+ <xsd:annotation>
+ <xsd:documentation>
+
+ Specifies a entry index for merging, similar to the Merge tag, but with a
+ global scope and accessible via the group attribute of other tags.
+
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:attribute name="name" type="identifier" />
+ </xsd:complexType>
+ <!-- TODO: Needs to be checked if it is allowed proper amounts of times, in those places it's used. -->
+ </xsd:element>
+
+ <xsd:complexType name="caption">
+ <xsd:simpleContent>
+ <xsd:annotation>
+ <xsd:documentation>
+
+ The user visible string shown as titles.
+
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:extension base="xsd:string"/>
+ </xsd:simpleContent>
+
+
+ </xsd:complexType>
+
+ <xsd:element name="Action" >
+ <xsd:complexType >
+ <xsd:annotation>
+ <xsd:documentation>
+
+ Defines both Standard and app-specific actions. An action can appear
+ in a menu, a toolbar or in a menubar.
+ Attributes:
+ - name of the action: this is matched with the KAction name.
+ - group: this is used to control the placement of the action when
+ merging e.g. a part, it matches the name of a DefineGroup in the
+ mainwindow's rc file.
+ - append: this is used to control the placement of the action during
+ the merging with ui_standards.rc. This is mapped to MergeLocal tags
+ there. Note that this feature is currently only available for the
+ mainwindow, not for parts/plugins.
+ - text, whatsThis, toolTip, shortText, shortcut, icon: all those are
+ mapped to KAction properties.
+
+
+ </xsd:documentation>
+ </xsd:annotation>
+
+ <xsd:attribute name="name" type="identifier"/>
+ <xsd:attribute name="group" type="identifier" use="optional" />
+ <xsd:attribute name="append" type="identifier" use="optional" />
+ <xsd:attribute name="text" type="xsd:string" use="optional"/>
+ <xsd:attribute name="whatsThis" type="xsd:string" use="optional"/>
+ <xsd:attribute name="toolTip" type="xsd:string" use="optional"/>
+ <xsd:attribute name="shortText" type="xsd:string" use="optional"/>
+ <xsd:attribute name="shortcut" type="xsd:string" use="optional">
+ <!-- TODO: Restrict the possible values with enumeration, or regexp -->
+ </xsd:attribute>
+ <xsd:attribute name="icon" type="xsd:string" use="optional" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="ActionList">
+ <xsd:annotation>
+ <xsd:documentation>
+
+ Specifies a dynamic list of actions, each of which can be changed by
+ plugging/unplugging it
+
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:attribute name="name" type="identifier"/>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:complexType name="state">
+ <xsd:sequence>
+ <xsd:element maxOccurs="unbounded" ref="Action"/>
+ </xsd:sequence>
+ <xsd:attribute name="name" type="identifier" />
+ </xsd:complexType>
+
+ <xsd:element name="Menu">
+ <xsd:complexType>
+ <xsd:annotation>
+ <xsd:documentation>
+
+ A Menu such as the &quot;File&quot; or &quot;Edit&quot; menu. Can be used to define popup
+ menus as well.
+
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:choice maxOccurs="unbounded" >
+ <!-- TODO: What's the difference between text and title? Which one(s) are required? The whole Menu is a mess. Fix maxOccurs, minOccurs for all of them. -->
+ <xsd:element minOccurs="0" name="text" type="caption" />
+ <xsd:element minOccurs="0" name="title" type="caption" />
+
+ <xsd:element ref="Action" maxOccurs="unbounded" />
+ <xsd:element ref="ActionList" maxOccurs="unbounded" />
+
+ <xsd:element minOccurs="0" maxOccurs="unbounded" name="TearOffHandle">
+ <xsd:complexType>
+ <xsd:attribute name="group" type="identifier"/>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element minOccurs="0" maxOccurs="unbounded" name="DefineGroup">
+ <xsd:complexType>
+ <xsd:attribute name="name" type="identifier"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" maxOccurs="unbounded" name="MergeLocal">
+ <xsd:complexType>
+ <xsd:attribute name="name" type="identifier" use="optional" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" maxOccurs="unbounded" ref="Separator" />
+ <xsd:element minOccurs="0" maxOccurs="unbounded" ref="WeakSeparator" />
+ <xsd:element minOccurs="0" maxOccurs="unbounded" ref="Menu" />
+ <xsd:element minOccurs="0" maxOccurs="unbounded" name="Merge" />
+
+ </xsd:choice>
+ <xsd:attribute name="name" type="identifier"/>
+ <xsd:attribute name="append" type="identifier" use="optional" />
+ <xsd:attribute name="group" type="identifier" use="optional" />
+ <xsd:attribute name="icon" type="xsd:string" use="optional" />
+ <xsd:attribute name="noMerge" type="xsd:boolean" use="optional" />
+ </xsd:complexType>
+ </xsd:element>
+
+
+ <xsd:element name="gui">
+ <xsd:annotation>
+ <xsd:documentation>
+
+ The root element that must enclose all other tags in the document. This
+ element replaces the kpartgui element used previously.
+ Note: do not forget to increase the version attribute for each change in
+ your file, otherwise the changes will not be taken into account.
+
+
+ </xsd:documentation>
+ </xsd:annotation>
+
+ <xsd:complexType>
+ <xsd:sequence>
+
+ <!-- TODO: Menu is allowed in gui, as per the original DTD. Why is it so? Shouldn't Menu only be in Menubar? If this is about Popup/Regular menu distinction, then should probably different complexTypes be used, if it's possible to separate the two. Perhaps a popupMenu element in gui could be allowed, which is no where else. -->
+ <xsd:element ref="Menu" maxOccurs="unbounded" minOccurs="0"/>
+ <xsd:element name="MenuBar">
+ <xsd:complexType>
+
+ <xsd:sequence>
+ <xsd:element ref="Menu" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element ref="Separator" minOccurs="0" maxOccurs="0" />
+ <xsd:element ref="Action" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="ActionList" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="Merge" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element ref="MergeLocal" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element ref="DefineGroup" minOccurs="0" maxOccurs="unbounded"/>
+ <!-- TODO:
+ - Why is ActionList and Action in MenuBar?
+ - Check that min/maxOccurs is correct
+ -->
+ </xsd:sequence>
+
+ <xsd:attribute name="name" type="identifier" use="optional" />
+ <xsd:attribute name="group" type="identifier" use="optional" />
+ </xsd:complexType>
+ </xsd:element>
+
+
+ <xsd:element name="ToolBar" minOccurs="0" maxOccurs="unbounded" >
+ <xsd:annotation>
+ <xsd:documentation>
+
+ A tool bar. Attributes:
+
+ - name: a unique name for the toolbar, use mainToolBar for
+ the main one
+
+ - fullWidth: if true (default), the toolbar extends to the
+ full width of the window
+
+ - position: the position of the toolbar in the window
+ - iconText: whether to show icon or text or both
+ - iconSize: the size of the icons (0 for default, or usually
+ 22 or 32)
+
+ - index: the index in the toolbar dock (see
+ QMainWindow::moveToolBar)
+
+ - offset: the X offset in the toolbar dock (see
+ QMainWindow::moveToolBar)
+
+ TODO: Those APIs are obsolete, are the attribute too?
+
+ - newline: if true, this toolbar will start a new line (i.e.
+ under the ones before it).
+
+ - group: optional group name, for named merging (?)
+
+ - hidden: if true, the toolbar is initially hidden. There
+ should be a menu entry for showing it.
+
+ - noEdit: if true, the toolbar won't appear in the toolbar
+ editor
+
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded" >
+ <xsd:element name="text" type="caption" />
+ <xsd:element ref="Action" minOccurs="0" maxOccurs="unbounded" />
+ <!-- Should 0 ActionS really be allowed? konqueror.rc does it.. -->
+ <xsd:element ref="Separator" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="WeakSeparator" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="ActionList" minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element ref="Merge" minOccurs="0" />
+ <xsd:element ref="MergeLocal" minOccurs="0" />
+ <xsd:element ref="DefineGroup" minOccurs="0" />
+ </xsd:choice>
+
+ <xsd:attribute name="name" type="identifier" />
+ <xsd:attribute name="fullWidth" use="optional" type="xsd:boolean" default="true" />
+ <xsd:attribute name="position" use="optional" >
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="top" />
+ <xsd:enumeration value="bottom" />
+ <xsd:enumeration value="left" />
+ <xsd:enumeration value="right" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ <xsd:attribute name="iconText" use="optional" >
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="icontextright" />
+ <xsd:enumeration value="icontextbottom" />
+ <xsd:enumeration value="textonly" />
+ <xsd:enumeration value="icononly" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ <xsd:attribute name="iconSize" use="optional" >
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:nonNegativeInteger">
+ <!-- TODO: This restriction is correct, right? -->
+ <xsd:enumeration value="0" /><!-- Implies default -->
+ <xsd:enumeration value="16" />
+ <xsd:enumeration value="22" />
+ <xsd:enumeration value="32" />
+ <xsd:enumeration value="48" />
+ <xsd:enumeration value="64" />
+ <xsd:enumeration value="128" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+
+ <!-- TODO: Since these are positiveInteger, and not nonNegativeInteger, they can't be 0 -->
+ <xsd:attribute name="index" use="optional" type="xsd:positiveInteger"/>
+ <xsd:attribute name="offset" use="optional" type="xsd:positiveInteger"/>
+ <xsd:attribute name="newline" use="optional" default="false" type="xsd:boolean" />
+ <xsd:attribute name="hidden" use="optional" default="false" type="xsd:boolean"/>
+ <xsd:attribute name="noEdit" use="optional" default="false" type="xsd:boolean"/>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element minOccurs="0" name="State">
+ <!-- Where should this be? -->
+ <xsd:annotation>
+ <xsd:documentation>
+
+ Defines a GUI state, esp. which actions to enable and which
+ ones to disable on entering this state (see
+ KXMLGUIClient::stateChanged()).
+
+ Actions listed in &quot;disable&quot; are disabled, and vice
+ versa for &quot;enable&quot;.
+
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:choice>
+ <!-- ( enable, disable? ) | ( disable, enable? ) -->
+ <xsd:sequence>
+ <xsd:element name="enable" type="state" />
+ <xsd:element minOccurs="0" name="disable" type="state" />
+ </xsd:sequence>
+ <xsd:sequence>
+ <xsd:element name="disable" type="state" />
+ <xsd:element minOccurs="0" name="enable" type="state" />
+ </xsd:sequence>
+ </xsd:choice>
+ <xsd:attribute name="name" type="identifier"/>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="ActionProperties" minOccurs="0" >
+ <xsd:annotation>
+ <xsd:documentation>
+
+ Allows standard actions to be customized.
+
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="Action" maxOccurs="unbounded" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ </xsd:sequence>
+
+ <!-- Not used nor referenced. Yet.
+ <xsd:element name="MainWindow"/>
+ <xsd:element name="StatusBar" />
+ -->
+
+ <xsd:attribute name="name" type="identifier"/>
+ <xsd:attribute name="version" type="xsd:positiveInteger" />
+ <xsd:attribute name="library" type="identifier" use="optional" />
+ </xsd:complexType>
+ </xsd:element>
+</xsd:schema>
+
diff --git a/kdeui/kxmlguibuilder.cpp b/kdeui/kxmlguibuilder.cpp
new file mode 100644
index 000000000..d3a19b77b
--- /dev/null
+++ b/kdeui/kxmlguibuilder.cpp
@@ -0,0 +1,441 @@
+/* This file is part of the KDE project
+ Copyright (C) 2000 Simon Hausmann <hausmann@kde.org>
+ David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kapplication.h"
+#include "kxmlguibuilder.h"
+#include "kmenubar.h"
+#include "kpopupmenu.h"
+#include "ktoolbar.h"
+#include "kstatusbar.h"
+#include "kmainwindow.h"
+#include "kaction.h"
+#include "kglobalsettings.h"
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+#include <qobjectlist.h>
+
+class KXMLGUIBuilderPrivate
+{
+public:
+ KXMLGUIBuilderPrivate() {
+ }
+ ~KXMLGUIBuilderPrivate() {
+ }
+
+ QWidget *m_widget;
+
+ QString tagMainWindow;
+ QString tagMenuBar;
+ QString tagMenu;
+ QString tagToolBar;
+ QString tagStatusBar;
+
+ QString tagSeparator;
+ QString tagTearOffHandle;
+ QString tagMenuTitle;
+
+ QString attrName;
+ QString attrLineSeparator;
+
+ QString attrText1;
+ QString attrText2;
+ QString attrContext;
+
+ QString attrIcon;
+
+ KInstance *m_instance;
+ KXMLGUIClient *m_client;
+};
+
+KXMLGUIBuilder::KXMLGUIBuilder( QWidget *widget )
+{
+ d = new KXMLGUIBuilderPrivate;
+ d->m_widget = widget;
+
+ d->tagMainWindow = QString::fromLatin1( "mainwindow" );
+ d->tagMenuBar = QString::fromLatin1( "menubar" );
+ d->tagMenu = QString::fromLatin1( "menu" );
+ d->tagToolBar = QString::fromLatin1( "toolbar" );
+ d->tagStatusBar = QString::fromLatin1( "statusbar" );
+
+ d->tagSeparator = QString::fromLatin1( "separator" );
+ d->tagTearOffHandle = QString::fromLatin1( "tearoffhandle" );
+ d->tagMenuTitle = QString::fromLatin1( "title" );
+
+ d->attrName = QString::fromLatin1( "name" );
+ d->attrLineSeparator = QString::fromLatin1( "lineseparator" );
+
+ d->attrText1 = QString::fromLatin1( "text" );
+ d->attrText2 = QString::fromLatin1( "Text" );
+ d->attrContext = QString::fromLatin1( "context" );
+
+ d->attrIcon = QString::fromLatin1( "icon" );
+
+ d->m_instance = 0;
+ d->m_client = 0;
+}
+
+KXMLGUIBuilder::~KXMLGUIBuilder()
+{
+ delete d;
+}
+
+QWidget *KXMLGUIBuilder::widget()
+{
+ return d->m_widget;
+}
+
+QStringList KXMLGUIBuilder::containerTags() const
+{
+ QStringList res;
+ res << d->tagMenu << d->tagToolBar << d->tagMainWindow << d->tagMenuBar << d->tagStatusBar;
+
+ return res;
+}
+
+QWidget *KXMLGUIBuilder::createContainer( QWidget *parent, int index, const QDomElement &element, int &id )
+{
+ id = -1;
+ if ( element.tagName().lower() == d->tagMainWindow )
+ {
+ KMainWindow *mainwindow = 0;
+ if ( ::qt_cast<KMainWindow *>( d->m_widget ) )
+ mainwindow = static_cast<KMainWindow *>(d->m_widget);
+
+ return mainwindow;
+ }
+
+ if ( element.tagName().lower() == d->tagMenuBar )
+ {
+ KMenuBar *bar;
+
+ if ( ::qt_cast<KMainWindow *>( d->m_widget ) )
+ bar = static_cast<KMainWindow *>(d->m_widget)->menuBar();
+ else
+ bar = new KMenuBar( d->m_widget );
+
+ bar->show();
+ return bar;
+ }
+
+ if ( element.tagName().lower() == d->tagMenu )
+ {
+ // Look up to see if we are inside a mainwindow. If yes, then
+ // use it as parent widget (to get kaction to plug itself into the
+ // mainwindow). Don't use a popupmenu as parent widget, otherwise
+ // the popup won't be hidden if it is used as a standalone menu as well.
+ // And we don't want to set the parent for a standalone popupmenu,
+ // otherwise its shortcuts appear.
+ QWidget* p = parent;
+ while ( p && !::qt_cast<KMainWindow *>( p ) )
+ p = p->parentWidget();
+
+ QCString name = element.attribute( d->attrName ).utf8();
+
+ if (!kapp->authorizeKAction(name))
+ return 0;
+
+ KPopupMenu *popup = new KPopupMenu( p, name);
+
+ QString i18nText;
+ QDomElement textElem = element.namedItem( d->attrText1 ).toElement();
+ if ( textElem.isNull() ) // try with capital T
+ textElem = element.namedItem( d->attrText2 ).toElement();
+ QCString text = textElem.text().utf8();
+ QCString context = textElem.attribute(d->attrContext).utf8();
+
+ if ( text.isEmpty() ) // still no luck
+ i18nText = i18n( "No text!" );
+ else if ( context.isEmpty() )
+ i18nText = i18n( text );
+ else
+ i18nText = i18n( context, text );
+
+ QString icon = element.attribute( d->attrIcon );
+ QIconSet pix;
+
+ if ( !icon.isEmpty() )
+ {
+ KInstance *instance = d->m_instance;
+ if ( !instance )
+ instance = KGlobal::instance();
+
+ pix = SmallIconSet( icon, 16, instance );
+ }
+
+ if ( parent && ::qt_cast<KMenuBar *>( parent ) )
+ {
+ if ( !icon.isEmpty() )
+ id = static_cast<KMenuBar *>(parent)->insertItem( pix, i18nText, popup, -1, index );
+ else
+ id = static_cast<KMenuBar *>(parent)->insertItem( i18nText, popup, -1, index );
+ }
+ else if ( parent && ::qt_cast<QPopupMenu *>( parent ) )
+ {
+ if ( !icon.isEmpty() )
+ id = static_cast<QPopupMenu *>(parent)->insertItem( pix, i18nText, popup, -1, index );
+ else
+ id = static_cast<QPopupMenu *>(parent)->insertItem( i18nText, popup, -1, index );
+ }
+
+ return popup;
+ }
+
+ if ( element.tagName().lower() == d->tagToolBar )
+ {
+ bool honor = (element.attribute( d->attrName ) == "mainToolBar");
+
+ QCString name = element.attribute( d->attrName ).utf8();
+
+ KToolBar *bar = static_cast<KToolBar*>(d->m_widget->child( name, "KToolBar" ));
+ if( !bar )
+ {
+ bar = new KToolBar( d->m_widget, name, honor, false );
+ }
+
+ if ( ::qt_cast<KMainWindow *>( d->m_widget ) )
+ {
+ if ( d->m_client && !d->m_client->xmlFile().isEmpty() )
+ bar->setXMLGUIClient( d->m_client );
+ }
+
+ bar->loadState( element );
+
+ return bar;
+ }
+
+ if ( element.tagName().lower() == d->tagStatusBar )
+ {
+ if ( ::qt_cast<KMainWindow *>( d->m_widget ) )
+ {
+ KMainWindow *mainWin = static_cast<KMainWindow *>(d->m_widget);
+ mainWin->statusBar()->show();
+ return mainWin->statusBar();
+ }
+ KStatusBar *bar = new KStatusBar( d->m_widget );
+ return bar;
+ }
+
+ return 0L;
+}
+
+void KXMLGUIBuilder::removeContainer( QWidget *container, QWidget *parent, QDomElement &element, int id )
+{
+ // Warning parent can be 0L
+
+ if ( ::qt_cast<QPopupMenu *>( container ) )
+ {
+ if ( parent )
+ {
+ if ( ::qt_cast<KMenuBar *>( parent ) )
+ static_cast<KMenuBar *>(parent)->removeItem( id );
+ else if ( ::qt_cast<QPopupMenu *>( parent ) )
+ static_cast<QPopupMenu *>(parent)->removeItem( id );
+ }
+
+ delete container;
+ }
+ else if ( ::qt_cast<KToolBar *>( container ) )
+ {
+ KToolBar *tb = static_cast<KToolBar *>( container );
+
+ tb->saveState( element );
+ delete tb;
+ }
+ else if ( ::qt_cast<KMenuBar *>( container ) )
+ {
+ KMenuBar *mb = static_cast<KMenuBar *>( container );
+ mb->hide();
+ // Don't delete menubar - it can be reused by createContainer.
+ // If you decide that you do need to delete the menubar, make
+ // sure that QMainWindow::d->mb does not point to a deleted
+ // menubar object.
+ }
+ else if ( ::qt_cast<KStatusBar *>( container ) )
+ {
+ if ( ::qt_cast<KMainWindow *>( d->m_widget ) )
+ container->hide();
+ else
+ delete static_cast<KStatusBar *>(container);
+ }
+ else
+ kdWarning() << "Unhandled container to remove : " << container->className() << endl;
+}
+
+QStringList KXMLGUIBuilder::customTags() const
+{
+ QStringList res;
+ res << d->tagSeparator << d->tagTearOffHandle << d->tagMenuTitle;
+ return res;
+}
+
+int KXMLGUIBuilder::createCustomElement( QWidget *parent, int index, const QDomElement &element )
+{
+ if ( element.tagName().lower() == d->tagSeparator )
+ {
+ if ( ::qt_cast<QPopupMenu *>( parent ) )
+ {
+ // Don't insert multiple separators in a row
+ QPopupMenu *menu = static_cast<QPopupMenu *>(parent);
+ int count = menu->count();
+ if (count)
+ {
+ int previousId = -1;
+ if ((index == -1) || (index > count))
+ previousId = menu->idAt(count-1);
+ else if (index > 0)
+ previousId = menu->idAt(index-1);
+ if (previousId != -1)
+ {
+ if (menu->text(previousId).isEmpty() &&
+ !menu->iconSet(previousId) &&
+ !menu->pixmap(previousId))
+ return 0;
+ }
+ }
+ // Don't insert a separator at the top of the menu
+ if(count == 0)
+ return 0;
+ else
+ return menu->insertSeparator( index );
+ }
+ else if ( ::qt_cast<QMenuBar *>( parent ) )
+ return static_cast<QMenuBar *>(parent)->insertSeparator( index );
+ else if ( ::qt_cast<KToolBar *>( parent ) )
+ {
+ KToolBar *bar = static_cast<KToolBar *>( parent );
+
+ bool isLineSep = true;
+
+ QDomNamedNodeMap attributes = element.attributes();
+ unsigned int i = 0;
+ for (; i < attributes.length(); i++ )
+ {
+ QDomAttr attr = attributes.item( i ).toAttr();
+
+ if ( attr.name().lower() == d->attrLineSeparator &&
+ attr.value().lower() == QString::fromLatin1("false") )
+ {
+ isLineSep = false;
+ break;
+ }
+ }
+
+ int id = KAction::getToolButtonID();
+
+ if ( isLineSep )
+ bar->insertLineSeparator( index, id );
+ else
+ bar->insertSeparator( index, id );
+
+ return id;
+ }
+ }
+ else if ( element.tagName().lower() == d->tagTearOffHandle )
+ {
+ if ( ::qt_cast<QPopupMenu *>( parent ) && KGlobalSettings::insertTearOffHandle())
+ return static_cast<QPopupMenu *>(parent)->insertTearOffHandle( -1, index );
+ }
+ else if ( element.tagName().lower() == d->tagMenuTitle )
+ {
+ if ( ::qt_cast<KPopupMenu *>( parent ) )
+ {
+ QString i18nText;
+ QCString text = element.text().utf8();
+
+ if ( text.isEmpty() )
+ i18nText = i18n( "No text!" );
+ else
+ i18nText = i18n( text );
+
+ QString icon = element.attribute( d->attrIcon );
+ QPixmap pix;
+
+ if ( !icon.isEmpty() )
+ {
+ KInstance *instance = d->m_instance;
+ if ( !instance )
+ instance = KGlobal::instance();
+
+ pix = SmallIcon( icon, instance );
+ }
+
+ if ( !icon.isEmpty() )
+ return static_cast<KPopupMenu *>(parent)->insertTitle( pix, i18nText, -1, index );
+ else
+ return static_cast<KPopupMenu *>(parent)->insertTitle( i18nText, -1, index );
+ }
+ }
+ return 0;
+}
+
+void KXMLGUIBuilder::removeCustomElement( QWidget *parent, int id )
+{
+ if ( ::qt_cast<QPopupMenu *>( parent ) )
+ static_cast<QPopupMenu *>(parent)->removeItem( id );
+ else if ( ::qt_cast<QMenuBar *>( parent ) )
+ static_cast<QMenuBar *>(parent)->removeItem( id );
+ else if ( ::qt_cast<KToolBar *>( parent ) )
+ static_cast<KToolBar *>(parent)->removeItemDelayed( id );
+}
+
+KXMLGUIClient *KXMLGUIBuilder::builderClient() const
+{
+ return d->m_client;
+}
+
+void KXMLGUIBuilder::setBuilderClient( KXMLGUIClient *client )
+{
+ d->m_client = client;
+ if ( client )
+ setBuilderInstance( client->instance() );
+}
+
+KInstance *KXMLGUIBuilder::builderInstance() const
+{
+ return d->m_instance;
+}
+
+void KXMLGUIBuilder::setBuilderInstance( KInstance *instance )
+{
+ d->m_instance = instance;
+}
+
+void KXMLGUIBuilder::finalizeGUI( KXMLGUIClient * )
+{
+ if ( !d->m_widget || !::qt_cast<KMainWindow *>( d->m_widget ) )
+ return;
+#if 0
+ KToolBar *toolbar = 0;
+ QListIterator<KToolBar> it( ( (KMainWindow*)d->m_widget )->toolBarIterator() );
+ while ( ( toolbar = it.current() ) ) {
+ kdDebug() << "KXMLGUIBuilder::finalizeGUI toolbar=" << (void*)toolbar << endl;
+ ++it;
+ toolbar->positionYourself();
+ }
+#else
+ static_cast<KMainWindow *>(d->m_widget)->finalizeGUI( false );
+#endif
+}
+
+void KXMLGUIBuilder::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
diff --git a/kdeui/kxmlguibuilder.h b/kdeui/kxmlguibuilder.h
new file mode 100644
index 000000000..22f0cd6fd
--- /dev/null
+++ b/kdeui/kxmlguibuilder.h
@@ -0,0 +1,96 @@
+/* This file is part of the KDE project
+ Copyright (C) 2000 Simon Hausmann <hausmann@kde.org>
+ David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef __kxmlguibuilder_h__
+#define __kxmlguibuilder_h__
+
+#include <qdom.h>
+#include <qstringlist.h>
+
+#include <kdelibs_export.h>
+
+class KXMLGUIBuilderPrivate;
+class QWidget;
+class KInstance;
+class KXMLGUIClient;
+
+/**
+ * Abstract interface for a "GUI builder", used by the GUIFactory
+ * This interface is implemented by KMainWindow for the case where
+ * the toplevel widget is a KMainWindow. Other implementations may appear
+ * in the future (dialogs for instance)
+ */
+class KDEUI_EXPORT KXMLGUIBuilder
+{
+ public:
+
+ KXMLGUIBuilder( QWidget *widget );
+ virtual ~KXMLGUIBuilder();
+
+ /* @internal */
+ KXMLGUIClient *builderClient() const;
+ /* @internal */
+ void setBuilderClient( KXMLGUIClient *client );
+ /* @internal */
+ KInstance *builderInstance() const;
+ /* @internal */
+ void setBuilderInstance( KInstance *instance );
+ /* @internal */
+ QWidget *widget();
+
+ virtual QStringList containerTags() const;
+
+ /**
+ * Creates a container (menubar/menu/toolbar/statusbar/separator/...)
+ * from an element in the XML file
+ *
+ * @param parent The parent for the container
+ * @param index The index where the container should be inserted
+ * into the parent container/widget
+ * @param element The element from the DOM tree describing the
+ * container (use it to access container specified
+ * attributes or child elements)
+ * @param id The id to be used for this container
+ */
+ virtual QWidget *createContainer( QWidget *parent, int index,
+ const QDomElement &element, int &id );
+
+ /**
+ * Removes the given (and previously via createContainer )
+ * created container.
+ *
+ */
+ virtual void removeContainer( QWidget *container, QWidget *parent,
+ QDomElement &element, int id );
+
+ virtual QStringList customTags() const;
+
+ virtual int createCustomElement( QWidget *parent, int index, const QDomElement &element );
+
+ virtual void removeCustomElement( QWidget *parent, int id );
+
+ virtual void finalizeGUI( KXMLGUIClient *client );
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KXMLGUIBuilderPrivate *d;
+};
+
+#endif
diff --git a/kdeui/kxmlguiclient.cpp b/kdeui/kxmlguiclient.cpp
new file mode 100644
index 000000000..ef14c2f49
--- /dev/null
+++ b/kdeui/kxmlguiclient.cpp
@@ -0,0 +1,951 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Simon Hausmann <hausmann@kde.org>
+ Copyright (C) 2000 Kurt Granroth <granroth@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kxmlguiclient.h"
+#include "kxmlguifactory.h"
+#include "kxmlguibuilder.h"
+
+#include <qdir.h>
+#include <qfile.h>
+#include <qdom.h>
+#include <qtextstream.h>
+#include <qregexp.h>
+#include <qguardedptr.h>
+
+#include <kinstance.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+#include <kaction.h>
+#include <kapplication.h>
+
+#include <assert.h>
+
+class KXMLGUIClientPrivate
+{
+public:
+ KXMLGUIClientPrivate()
+ {
+ m_instance = KGlobal::instance();
+ m_parent = 0L;
+ m_builder = 0L;
+ m_actionCollection = 0;
+ }
+ ~KXMLGUIClientPrivate()
+ {
+ }
+
+ KInstance *m_instance;
+
+ QDomDocument m_doc;
+ KActionCollection *m_actionCollection;
+ QDomDocument m_buildDocument;
+ QGuardedPtr<KXMLGUIFactory> m_factory;
+ KXMLGUIClient *m_parent;
+ //QPtrList<KXMLGUIClient> m_supers;
+ QPtrList<KXMLGUIClient> m_children;
+ KXMLGUIBuilder *m_builder;
+ QString m_xmlFile;
+ QString m_localXMLFile;
+};
+
+KXMLGUIClient::KXMLGUIClient()
+{
+ d = new KXMLGUIClientPrivate;
+}
+
+KXMLGUIClient::KXMLGUIClient( KXMLGUIClient *parent )
+{
+ d = new KXMLGUIClientPrivate;
+ parent->insertChildClient( this );
+}
+
+KXMLGUIClient::~KXMLGUIClient()
+{
+ if ( d->m_parent )
+ d->m_parent->removeChildClient( this );
+
+ QPtrListIterator<KXMLGUIClient> it( d->m_children );
+ for ( ; it.current(); ++it ) {
+ assert( it.current()->d->m_parent == this );
+ it.current()->d->m_parent = 0;
+ }
+
+ delete d->m_actionCollection;
+ delete d;
+}
+
+KAction *KXMLGUIClient::action( const char *name ) const
+{
+ KAction* act = actionCollection()->action( name );
+ if ( !act ) {
+ QPtrListIterator<KXMLGUIClient> childIt( d->m_children );
+ for (; childIt.current(); ++childIt ) {
+ act = childIt.current()->actionCollection()->action( name );
+ if ( act )
+ break;
+ }
+ }
+ return act;
+}
+
+KActionCollection *KXMLGUIClient::actionCollection() const
+{
+ if ( !d->m_actionCollection )
+ {
+ d->m_actionCollection = new KActionCollection(
+ "KXMLGUIClient-KActionCollection", this );
+ }
+ return d->m_actionCollection;
+}
+
+KAction *KXMLGUIClient::action( const QDomElement &element ) const
+{
+ static const QString &attrName = KGlobal::staticQString( "name" );
+ return actionCollection()->action( element.attribute( attrName ).latin1() );
+}
+
+KInstance *KXMLGUIClient::instance() const
+{
+ return d->m_instance;
+}
+
+QDomDocument KXMLGUIClient::domDocument() const
+{
+ return d->m_doc;
+}
+
+QString KXMLGUIClient::xmlFile() const
+{
+ return d->m_xmlFile;
+}
+
+QString KXMLGUIClient::localXMLFile() const
+{
+ if ( !d->m_localXMLFile.isEmpty() )
+ return d->m_localXMLFile;
+
+ if ( !QDir::isRelativePath(d->m_xmlFile) )
+ return QString::null; // can't save anything here
+
+ return locateLocal( "data", QString::fromLatin1( instance()->instanceName() + '/' ) + d->m_xmlFile );
+}
+
+
+void KXMLGUIClient::reloadXML()
+{
+ QString file( xmlFile() );
+ if ( !file.isEmpty() )
+ setXMLFile( file );
+}
+
+void KXMLGUIClient::setInstance( KInstance *instance )
+{
+ d->m_instance = instance;
+ actionCollection()->setInstance( instance );
+ if ( d->m_builder )
+ d->m_builder->setBuilderClient( this );
+}
+
+void KXMLGUIClient::setXMLFile( const QString& _file, bool merge, bool setXMLDoc )
+{
+ // store our xml file name
+ if ( !_file.isNull() ) {
+ d->m_xmlFile = _file;
+ actionCollection()->setXMLFile( _file );
+ }
+
+ if ( !setXMLDoc )
+ return;
+
+ QString file = _file;
+ if ( QDir::isRelativePath(file) )
+ {
+ QString doc;
+
+ QString filter = QString::fromLatin1( instance()->instanceName() + '/' ) + _file;
+
+ QStringList allFiles = instance()->dirs()->findAllResources( "data", filter ) + instance()->dirs()->findAllResources( "data", _file );
+
+ file = findMostRecentXMLFile( allFiles, doc );
+
+ if ( file.isEmpty() )
+ {
+ // this might or might not be an error. for the time being,
+ // let's treat this as if it isn't a problem and the user just
+ // wants the global standards file
+
+ // however if a non-empty file gets passed and we can't find it we might
+ // inform the developer using some debug output
+ if ( !_file.isEmpty() )
+ kdWarning() << "KXMLGUIClient::setXMLFile: cannot find .rc file " << _file << endl;
+
+ setXML( QString::null, true );
+ return;
+ }
+ else if ( !doc.isEmpty() )
+ {
+ setXML( doc, merge );
+ return;
+ }
+ }
+
+ QString xml = KXMLGUIFactory::readConfigFile( file );
+ setXML( xml, merge );
+}
+
+void KXMLGUIClient::setLocalXMLFile( const QString &file )
+{
+ d->m_localXMLFile = file;
+}
+
+void KXMLGUIClient::setXML( const QString &document, bool merge )
+{
+ QDomDocument doc;
+ doc.setContent( document );
+ setDOMDocument( doc, merge );
+}
+
+void KXMLGUIClient::setDOMDocument( const QDomDocument &document, bool merge )
+{
+ if ( merge )
+ {
+ QDomElement base = d->m_doc.documentElement();
+
+ QDomElement e = document.documentElement();
+
+ // merge our original (global) xml with our new one
+ mergeXML(base, e, actionCollection());
+
+ // reassign our pointer as mergeXML might have done something
+ // strange to it
+ base = d->m_doc.documentElement();
+
+ // we want some sort of failsafe.. just in case
+ if ( base.isNull() )
+ d->m_doc = document;
+ }
+ else
+ {
+ d->m_doc = document;
+ }
+
+ setXMLGUIBuildDocument( QDomDocument() );
+}
+
+bool KXMLGUIClient::mergeXML( QDomElement &base, const QDomElement &additive, KActionCollection *actionCollection )
+{
+ static const QString &tagAction = KGlobal::staticQString( "Action" );
+ static const QString &tagMerge = KGlobal::staticQString( "Merge" );
+ static const QString &tagSeparator = KGlobal::staticQString( "Separator" );
+ static const QString &attrName = KGlobal::staticQString( "name" );
+ static const QString &attrAppend = KGlobal::staticQString( "append" );
+ static const QString &attrWeakSeparator = KGlobal::staticQString( "weakSeparator" );
+ static const QString &tagMergeLocal = KGlobal::staticQString( "MergeLocal" );
+ static const QString &tagText = KGlobal::staticQString( "text" );
+ static const QString &attrAlreadyVisited = KGlobal::staticQString( "alreadyVisited" );
+ static const QString &attrNoMerge = KGlobal::staticQString( "noMerge" );
+ static const QString &attrOne = KGlobal::staticQString( "1" );
+
+ // there is a possibility that we don't want to merge in the
+ // additive.. rather, we might want to *replace* the base with the
+ // additive. this can be for any container.. either at a file wide
+ // level or a simple container level. we look for the 'noMerge'
+ // tag, in any event and just replace the old with the new
+ if ( additive.attribute(attrNoMerge) == attrOne ) // ### use toInt() instead? (Simon)
+ {
+ base.parentNode().replaceChild(additive, base);
+ return true;
+ }
+
+ QString tag;
+
+ // iterate over all elements in the container (of the global DOM tree)
+ QDomNode n = base.firstChild();
+ while ( !n.isNull() )
+ {
+ QDomElement e = n.toElement();
+ n = n.nextSibling(); // Advance now so that we can safely delete e
+ if (e.isNull())
+ continue;
+
+ tag = e.tagName();
+
+ // if there's an action tag in the global tree and the action is
+ // not implemented, then we remove the element
+ if ( tag == tagAction )
+ {
+ QCString name = e.attribute( attrName ).utf8(); // WABA
+ if ( !actionCollection->action( name ) ||
+ (kapp && !kapp->authorizeKAction(name)))
+ {
+ // remove this child as we aren't using it
+ base.removeChild( e );
+ continue;
+ }
+ }
+
+ // if there's a separator defined in the global tree, then add an
+ // attribute, specifying that this is a "weak" separator
+ else if ( tag == tagSeparator )
+ {
+ e.setAttribute( attrWeakSeparator, (uint)1 );
+
+ // okay, hack time. if the last item was a weak separator OR
+ // this is the first item in a container, then we nuke the
+ // current one
+ QDomElement prev = e.previousSibling().toElement();
+ if ( prev.isNull() ||
+ ( prev.tagName() == tagSeparator && !prev.attribute( attrWeakSeparator ).isNull() ) ||
+ ( prev.tagName() == tagText ) )
+ {
+ // the previous element was a weak separator or didn't exist
+ base.removeChild( e );
+ continue;
+ }
+ }
+
+ // the MergeLocal tag lets us specify where non-standard elements
+ // of the local tree shall be merged in. After inserting the
+ // elements we delete this element
+ else if ( tag == tagMergeLocal )
+ {
+ QDomNode it = additive.firstChild();
+ while ( !it.isNull() )
+ {
+ QDomElement newChild = it.toElement();
+ it = it.nextSibling();
+ if (newChild.isNull() )
+ continue;
+
+ if ( newChild.tagName() == tagText )
+ continue;
+
+ if ( newChild.attribute( attrAlreadyVisited ) == attrOne )
+ continue;
+
+ QString itAppend( newChild.attribute( attrAppend ) );
+ QString elemName( e.attribute( attrName ) );
+
+ if ( ( itAppend.isNull() && elemName.isEmpty() ) ||
+ ( itAppend == elemName ) )
+ {
+ // first, see if this new element matches a standard one in
+ // the global file. if it does, then we skip it as it will
+ // be merged in, later
+ QDomElement matchingElement = findMatchingElement( newChild, base );
+ if ( matchingElement.isNull() || newChild.tagName() == tagSeparator )
+ base.insertBefore( newChild, e );
+ }
+ }
+
+ base.removeChild( e );
+ continue;
+ }
+
+ // in this last case we check for a separator tag and, if not, we
+ // can be sure that its a container --> proceed with child nodes
+ // recursively and delete the just proceeded container item in
+ // case its empty (if the recursive call returns true)
+ else if ( tag != tagMerge )
+ {
+ // handle the text tag
+ if ( tag == tagText )
+ continue;
+
+ QDomElement matchingElement = findMatchingElement( e, additive );
+
+ if ( !matchingElement.isNull() )
+ {
+ matchingElement.setAttribute( attrAlreadyVisited, (uint)1 );
+
+ if ( mergeXML( e, matchingElement, actionCollection ) )
+ {
+ base.removeChild( e );
+ continue;
+ }
+
+ // Merge attributes
+ const QDomNamedNodeMap attribs = matchingElement.attributes();
+ const uint attribcount = attribs.count();
+
+ for(uint i = 0; i < attribcount; ++i)
+ {
+ const QDomNode node = attribs.item(i);
+ e.setAttribute(node.nodeName(), node.nodeValue());
+ }
+
+ continue;
+ }
+ else
+ {
+ // this is an important case here! We reach this point if the
+ // "local" tree does not contain a container definition for
+ // this container. However we have to call mergeXML recursively
+ // and make it check if there are actions implemented for this
+ // container. *If* none, then we can remove this container now
+ if ( mergeXML( e, QDomElement(), actionCollection ) )
+ base.removeChild( e );
+ continue;
+ }
+ }
+ }
+
+ //here we append all child elements which were not inserted
+ //previously via the LocalMerge tag
+ n = additive.firstChild();
+ while ( !n.isNull() )
+ {
+ QDomElement e = n.toElement();
+ n = n.nextSibling(); // Advance now so that we can safely delete e
+ if (e.isNull())
+ continue;
+
+ QDomElement matchingElement = findMatchingElement( e, base );
+
+ if ( matchingElement.isNull() )
+ {
+ base.appendChild( e );
+ }
+ }
+
+ // do one quick check to make sure that the last element was not
+ // a weak separator
+ QDomElement last = base.lastChild().toElement();
+ if ( (last.tagName() == tagSeparator) && (!last.attribute( attrWeakSeparator ).isNull()) )
+ {
+ base.removeChild( last );
+ }
+
+ // now we check if we are empty (in which case we return "true", to
+ // indicate the caller that it can delete "us" (the base element
+ // argument of "this" call)
+ bool deleteMe = true;
+
+ n = base.firstChild();
+ while ( !n.isNull() )
+ {
+ QDomElement e = n.toElement();
+ n = n.nextSibling(); // Advance now so that we can safely delete e
+ if (e.isNull())
+ continue;
+
+ tag = e.tagName();
+
+ if ( tag == tagAction )
+ {
+ // if base contains an implemented action, then we must not get
+ // deleted (note that the actionCollection contains both,
+ // "global" and "local" actions
+ if ( actionCollection->action( e.attribute( attrName ).utf8() ) )
+ {
+ deleteMe = false;
+ break;
+ }
+ }
+ else if ( tag == tagSeparator )
+ {
+ // if we have a separator which has *not* the weak attribute
+ // set, then it must be owned by the "local" tree in which case
+ // we must not get deleted either
+ QString weakAttr = e.attribute( attrWeakSeparator );
+ if ( weakAttr.isEmpty() || weakAttr.toInt() != 1 )
+ {
+ deleteMe = false;
+ break;
+ }
+ }
+
+ // in case of a merge tag we have unlimited lives, too ;-)
+ else if ( tag == tagMerge )
+ {
+// deleteMe = false;
+// break;
+ continue;
+ }
+
+ // a text tag is NOT enough to spare this container
+ else if ( tag == tagText )
+ {
+ continue;
+ }
+
+ // what's left are non-empty containers! *don't* delete us in this
+ // case (at this position we can be *sure* that the container is
+ // *not* empty, as the recursive call for it was in the first loop
+ // which deleted the element in case the call returned "true"
+ else
+ {
+ deleteMe = false;
+ break;
+ }
+ }
+
+ return deleteMe;
+}
+
+QDomElement KXMLGUIClient::findMatchingElement( const QDomElement &base, const QDomElement &additive )
+{
+ static const QString &tagAction = KGlobal::staticQString( "Action" );
+ static const QString &tagMergeLocal = KGlobal::staticQString( "MergeLocal" );
+ static const QString &attrName = KGlobal::staticQString( "name" );
+
+ QDomNode n = additive.firstChild();
+ while ( !n.isNull() )
+ {
+ QDomElement e = n.toElement();
+ n = n.nextSibling(); // Advance now so that we can safely delete e
+ if (e.isNull())
+ continue;
+
+ // skip all action and merge tags as we will never use them
+ if ( ( e.tagName() == tagAction ) || ( e.tagName() == tagMergeLocal ) )
+ {
+ continue;
+ }
+
+ // now see if our tags are equivalent
+ if ( ( e.tagName() == base.tagName() ) &&
+ ( e.attribute( attrName ) == base.attribute( attrName ) ) )
+ {
+ return e;
+ }
+ }
+
+ // nope, return a (now) null element
+ return QDomElement();
+}
+
+void KXMLGUIClient::conserveMemory()
+{
+ d->m_doc = QDomDocument();
+ d->m_buildDocument = QDomDocument();
+}
+
+void KXMLGUIClient::setXMLGUIBuildDocument( const QDomDocument &doc )
+{
+ d->m_buildDocument = doc;
+}
+
+QDomDocument KXMLGUIClient::xmlguiBuildDocument() const
+{
+ return d->m_buildDocument;
+}
+
+void KXMLGUIClient::setFactory( KXMLGUIFactory *factory )
+{
+ d->m_factory = factory;
+}
+
+KXMLGUIFactory *KXMLGUIClient::factory() const
+{
+ return d->m_factory;
+}
+
+KXMLGUIClient *KXMLGUIClient::parentClient() const
+{
+ return d->m_parent;
+}
+
+void KXMLGUIClient::insertChildClient( KXMLGUIClient *child )
+{
+ if ( child->d->m_parent )
+ child->d->m_parent->removeChildClient( child );
+ d->m_children.append( child );
+ child->d->m_parent = this;
+}
+
+void KXMLGUIClient::removeChildClient( KXMLGUIClient *child )
+{
+ assert( d->m_children.containsRef( child ) );
+ d->m_children.removeRef( child );
+ child->d->m_parent = 0;
+}
+
+/*bool KXMLGUIClient::addSuperClient( KXMLGUIClient *super )
+{
+ if ( d->m_supers.contains( super ) )
+ return false;
+ d->m_supers.append( super );
+ return true;
+}*/
+
+const QPtrList<KXMLGUIClient> *KXMLGUIClient::childClients()
+{
+ return &d->m_children;
+}
+
+void KXMLGUIClient::setClientBuilder( KXMLGUIBuilder *builder )
+{
+ d->m_builder = builder;
+ if ( builder )
+ builder->setBuilderInstance( instance() );
+}
+
+KXMLGUIBuilder *KXMLGUIClient::clientBuilder() const
+{
+ return d->m_builder;
+}
+
+void KXMLGUIClient::plugActionList( const QString &name, const QPtrList<KAction> &actionList )
+{
+ if ( !d->m_factory )
+ return;
+
+ d->m_factory->plugActionList( this, name, actionList );
+}
+
+void KXMLGUIClient::unplugActionList( const QString &name )
+{
+ if ( !d->m_factory )
+ return;
+
+ d->m_factory->unplugActionList( this, name );
+}
+
+QString KXMLGUIClient::findMostRecentXMLFile( const QStringList &files, QString &doc )
+{
+
+ QValueList<DocStruct> allDocuments;
+
+ QStringList::ConstIterator it = files.begin();
+ QStringList::ConstIterator end = files.end();
+ for (; it != end; ++it )
+ {
+ //kdDebug() << "KXMLGUIClient::findMostRecentXMLFile " << *it << endl;
+ QString data = KXMLGUIFactory::readConfigFile( *it );
+ DocStruct d;
+ d.file = *it;
+ d.data = data;
+ allDocuments.append( d );
+ }
+
+ QValueList<DocStruct>::Iterator best = allDocuments.end();
+ uint bestVersion = 0;
+
+ QValueList<DocStruct>::Iterator docIt = allDocuments.begin();
+ QValueList<DocStruct>::Iterator docEnd = allDocuments.end();
+ for (; docIt != docEnd; ++docIt )
+ {
+ QString versionStr = findVersionNumber( (*docIt).data );
+ if ( versionStr.isEmpty() )
+ continue;
+
+ bool ok = false;
+ uint version = versionStr.toUInt( &ok );
+ if ( !ok )
+ continue;
+ //kdDebug() << "FOUND VERSION " << version << endl;
+
+ if ( version > bestVersion )
+ {
+ best = docIt;
+ //kdDebug() << "best version is now " << version << endl;
+ bestVersion = version;
+ }
+ }
+
+ if ( best != docEnd )
+ {
+ if ( best != allDocuments.begin() )
+ {
+ QValueList<DocStruct>::Iterator local = allDocuments.begin();
+
+ // load the local document and extract the action properties
+ QDomDocument document;
+ document.setContent( (*local).data );
+
+ ActionPropertiesMap properties = extractActionProperties( document );
+
+ // in case the document has a ActionProperties section
+ // we must not delete it but copy over the global doc
+ // to the local and insert the ActionProperties section
+ if ( !properties.isEmpty() )
+ {
+ // now load the global one with the higher version number
+ // into memory
+ document.setContent( (*best).data );
+ // and store the properties in there
+ storeActionProperties( document, properties );
+
+ (*local).data = document.toString();
+ // make sure we pick up the new local doc, when we return later
+ best = local;
+
+ // write out the new version of the local document
+ QFile f( (*local).file );
+ if ( f.open( IO_WriteOnly ) )
+ {
+ QCString utf8data = (*local).data.utf8();
+ f.writeBlock( utf8data.data(), utf8data.length() );
+ f.close();
+ }
+ }
+ else
+ {
+ QString f = (*local).file;
+ QString backup = f + QString::fromLatin1( ".backup" );
+ QDir dir;
+ dir.rename( f, backup );
+ }
+ }
+ doc = (*best).data;
+ return (*best).file;
+ }
+ else if ( files.count() > 0 )
+ {
+ //kdDebug() << "returning first one..." << endl;
+ doc = (*allDocuments.begin()).data;
+ return (*allDocuments.begin()).file;
+ }
+
+ return QString::null;
+}
+
+
+
+QString KXMLGUIClient::findVersionNumber( const QString &xml )
+{
+ enum { ST_START, ST_AFTER_OPEN, ST_AFTER_GUI,
+ ST_EXPECT_VERSION, ST_VERSION_NUM} state = ST_START;
+ for (unsigned int pos = 0; pos < xml.length(); pos++)
+ {
+ switch (state)
+ {
+ case ST_START:
+ if (xml[pos] == '<')
+ state = ST_AFTER_OPEN;
+ break;
+ case ST_AFTER_OPEN:
+ {
+ //Jump to gui..
+ int guipos = xml.find("gui", pos, false /*case-insensitive*/);
+ if (guipos == -1)
+ return QString::null; //Reject
+
+ pos = guipos + 2; //Position at i, so we're moved ahead to the next character by the ++;
+ state = ST_AFTER_GUI;
+ break;
+ }
+ case ST_AFTER_GUI:
+ state = ST_EXPECT_VERSION;
+ break;
+ case ST_EXPECT_VERSION:
+ {
+ int verpos = xml.find("version=\"", pos, false /*case-insensitive*/);
+ if (verpos == -1)
+ return QString::null; //Reject
+
+ pos = verpos + 8; //v = 0, e = +1, r = +2, s = +3 , i = +4, o = +5, n = +6, = = +7, " = + 8
+ state = ST_VERSION_NUM;
+ break;
+ }
+ case ST_VERSION_NUM:
+ {
+ unsigned int endpos;
+ for (endpos = pos; endpos < xml.length(); endpos++)
+ {
+ if (xml[endpos].unicode() >= '0' && xml[endpos].unicode() <= '9')
+ continue; //Number..
+ if (xml[endpos].unicode() == '"') //End of parameter
+ break;
+ else //This shouldn't be here..
+ {
+ endpos = xml.length();
+ }
+ }
+
+ if (endpos != pos && endpos < xml.length() )
+ {
+ QString matchCandidate = xml.mid(pos, endpos - pos); //Don't include " ".
+ return matchCandidate;
+ }
+
+ state = ST_EXPECT_VERSION; //Try to match a well-formed version..
+ break;
+ } //case..
+ } //switch
+ } //for
+
+ return QString::null;
+}
+
+KXMLGUIClient::ActionPropertiesMap KXMLGUIClient::extractActionProperties( const QDomDocument &doc )
+{
+ ActionPropertiesMap properties;
+
+ QDomElement actionPropElement = doc.documentElement().namedItem( "ActionProperties" ).toElement();
+
+ if ( actionPropElement.isNull() )
+ return properties;
+
+ QDomNode n = actionPropElement.firstChild();
+ while(!n.isNull())
+ {
+ QDomElement e = n.toElement();
+ n = n.nextSibling(); // Advance now so that we can safely delete e
+ if ( e.isNull() )
+ continue;
+
+ if ( e.tagName().lower() != "action" )
+ continue;
+
+ QString actionName = e.attribute( "name" );
+
+ if ( actionName.isEmpty() )
+ continue;
+
+ QMap<QString, QMap<QString, QString> >::Iterator propIt = properties.find( actionName );
+ if ( propIt == properties.end() )
+ propIt = properties.insert( actionName, QMap<QString, QString>() );
+
+ const QDomNamedNodeMap attributes = e.attributes();
+ const uint attributeslength = attributes.length();
+
+ for ( uint i = 0; i < attributeslength; ++i )
+ {
+ const QDomAttr attr = attributes.item( i ).toAttr();
+
+ if ( attr.isNull() )
+ continue;
+
+ const QString name = attr.name();
+
+ if ( name == "name" || name.isEmpty() )
+ continue;
+
+ (*propIt)[ name ] = attr.value();
+ }
+
+ }
+
+ return properties;
+}
+
+void KXMLGUIClient::storeActionProperties( QDomDocument &doc, const ActionPropertiesMap &properties )
+{
+ QDomElement actionPropElement = doc.documentElement().namedItem( "ActionProperties" ).toElement();
+
+ if ( actionPropElement.isNull() )
+ {
+ actionPropElement = doc.createElement( "ActionProperties" );
+ doc.documentElement().appendChild( actionPropElement );
+ }
+
+ while ( !actionPropElement.firstChild().isNull() )
+ actionPropElement.removeChild( actionPropElement.firstChild() );
+
+ ActionPropertiesMap::ConstIterator it = properties.begin();
+ ActionPropertiesMap::ConstIterator end = properties.end();
+ for (; it != end; ++it )
+ {
+ QDomElement action = doc.createElement( "Action" );
+ action.setAttribute( "name", it.key() );
+ actionPropElement.appendChild( action );
+
+ QMap<QString, QString> attributes = (*it);
+ QMap<QString, QString>::ConstIterator attrIt = attributes.begin();
+ QMap<QString, QString>::ConstIterator attrEnd = attributes.end();
+ for (; attrIt != attrEnd; ++attrIt )
+ action.setAttribute( attrIt.key(), attrIt.data() );
+ }
+}
+
+void KXMLGUIClient::addStateActionEnabled(const QString& state,
+ const QString& action)
+{
+ StateChange stateChange = getActionsToChangeForState(state);
+
+ stateChange.actionsToEnable.append( action );
+ //kdDebug() << "KXMLGUIClient::addStateActionEnabled( " << state << ", " << action << ")" << endl;
+
+ m_actionsStateMap.replace( state, stateChange );
+}
+
+
+void KXMLGUIClient::addStateActionDisabled(const QString& state,
+ const QString& action)
+{
+ StateChange stateChange = getActionsToChangeForState(state);
+
+ stateChange.actionsToDisable.append( action );
+ //kdDebug() << "KXMLGUIClient::addStateActionDisabled( " << state << ", " << action << ")" << endl;
+
+ m_actionsStateMap.replace( state, stateChange );
+}
+
+
+KXMLGUIClient::StateChange KXMLGUIClient::getActionsToChangeForState(const QString& state)
+{
+ return m_actionsStateMap[state];
+}
+
+
+void KXMLGUIClient::stateChanged(const QString &newstate, KXMLGUIClient::ReverseStateChange reverse)
+{
+ StateChange stateChange = getActionsToChangeForState(newstate);
+
+ bool setTrue = (reverse == StateNoReverse);
+ bool setFalse = !setTrue;
+
+ // Enable actions which need to be enabled...
+ //
+ for ( QStringList::Iterator it = stateChange.actionsToEnable.begin();
+ it != stateChange.actionsToEnable.end(); ++it ) {
+
+ KAction *action = actionCollection()->action((*it).latin1());
+ if (action) action->setEnabled(setTrue);
+ }
+
+ // and disable actions which need to be disabled...
+ //
+ for ( QStringList::Iterator it = stateChange.actionsToDisable.begin();
+ it != stateChange.actionsToDisable.end(); ++it ) {
+
+ KAction *action = actionCollection()->action((*it).latin1());
+ if (action) action->setEnabled(setFalse);
+ }
+
+}
+
+void KXMLGUIClient::beginXMLPlug( QWidget *w )
+{
+ actionCollection()->beginXMLPlug( w );
+ QPtrListIterator<KXMLGUIClient> childIt( d->m_children );
+ for (; childIt.current(); ++childIt )
+ childIt.current()->actionCollection()->beginXMLPlug( w );
+}
+
+void KXMLGUIClient::endXMLPlug()
+{
+ actionCollection()->endXMLPlug();
+ QPtrListIterator<KXMLGUIClient> childIt( d->m_children );
+ for (; childIt.current(); ++childIt )
+ childIt.current()->actionCollection()->endXMLPlug();
+}
+
+void KXMLGUIClient::prepareXMLUnplug( QWidget * )
+{
+ actionCollection()->prepareXMLUnplug();
+ QPtrListIterator<KXMLGUIClient> childIt( d->m_children );
+ for (; childIt.current(); ++childIt )
+ childIt.current()->actionCollection()->prepareXMLUnplug();
+}
+
+void KXMLGUIClient::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
diff --git a/kdeui/kxmlguiclient.h b/kdeui/kxmlguiclient.h
new file mode 100644
index 000000000..c3d377c91
--- /dev/null
+++ b/kdeui/kxmlguiclient.h
@@ -0,0 +1,367 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2000 Simon Hausmann <hausmann@kde.org>
+ Copyright (C) 2000 Kurt Granroth <granroth@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef _KXMLGUICLIENT_H
+#define _KXMLGUICLIENT_H
+
+#include <qdom.h>
+#include <qptrlist.h>
+#include <qmap.h>
+#include <qstringlist.h>
+
+#include <kdelibs_export.h>
+
+class QWidget;
+class KAction;
+class KActionCollection;
+class KInstance;
+class KXMLGUIClientPrivate;
+class KXMLGUIFactory;
+class KXMLGUIBuilder;
+
+/**
+ *
+ * A KXMLGUIClient can be used with KXMLGUIFactory to create a
+ * GUI from actions and an XML document, and can be dynamically merged
+ * with other KXMLGUIClients.
+ */
+class KDEUI_EXPORT KXMLGUIClient
+{
+ friend class KEditToolbarWidget; // for setXMLFile(3 args)
+public:
+ /**
+ * Constructs a KXMLGUIClient which can be used with a
+ * KXMLGUIFactory to create a GUI from actions and an XML document, and
+ * which can be dynamically merged with other KXMLGUIClients.
+ */
+ KXMLGUIClient();
+
+ /**
+ * Constructs a KXMLGUIClient which can be used with a KXMLGUIFactory
+ * to create a GUI from actions and an XML document,
+ * and which can be dynamically merged with other KXMLGUIClients.
+ *
+ * This constructor takes an additional @p parent argument, which makes
+ * the client a child client of the parent.
+ *
+ * Child clients are automatically added to the GUI if the parent is added.
+ *
+ */
+ KXMLGUIClient( KXMLGUIClient *parent );
+
+ /**
+ * Destructs the KXMLGUIClient.
+ */
+ virtual ~KXMLGUIClient();
+
+ /**
+ * Retrieves an action of the client by name. If not found, it looks in its child clients.
+ * This method is provided for convenience, as it uses actionCollection()
+ * to get the action object.
+ */
+ KAction* action( const char* name ) const;
+
+ /**
+ * Retrieves an action for a given QDomElement. The default
+ * implementation uses the "name" attribute to query the action
+ * object via the other action() method.
+ */
+ virtual KAction *action( const QDomElement &element ) const;
+
+ /**
+ * Retrieves the entire action collection for the GUI client. If
+ * you subclass KXMLGUIClient you should call
+ * KActionCollection::setWidget( QWidget* ) with this object, or
+ * you will encounter subtle bugs with KAction keyboard shortcuts.
+ * This is not necessary if your KXMLGUIClient is a KMainWindow.
+ *
+ * @see KActionCollection::setWidget( QWidget* )
+ */
+ virtual KActionCollection* actionCollection() const;
+
+ /**
+ * @return The instance ( KInstance ) for this GUI client.
+ */
+ virtual KInstance *instance() const;
+
+ /**
+ * @return The parsed XML in a QDomDocument, set by
+ * setXMLFile() or setXML().
+ * This document describes the layout of the GUI.
+ */
+ virtual QDomDocument domDocument() const;
+
+ /**
+ * This will return the name of the XML file as set by setXMLFile().
+ * If setXML() is used directly, then this will return NULL.
+ *
+ * The filename that this returns is obvious for components as each
+ * component has exactly one XML file. In non-components, however,
+ * there are usually two: the global file and the local file. This
+ * function doesn't really care about that, though. It will always
+ * return the last XML file set. This, in almost all cases, will
+ * be the local XML file.
+ *
+ * @return The name of the XML file or QString::null
+ */
+ virtual QString xmlFile() const;
+
+ virtual QString localXMLFile() const;
+
+ /**
+ * @internal
+ */
+ void setXMLGUIBuildDocument( const QDomDocument &doc );
+ /**
+ * @internal
+ */
+ QDomDocument xmlguiBuildDocument() const;
+
+ /**
+ * This method is called by the KXMLGUIFactory as soon as the client
+ * is added to the KXMLGUIFactory's GUI.
+ */
+ void setFactory( KXMLGUIFactory *factory );
+ /**
+ * Retrieves a pointer to the KXMLGUIFactory this client is
+ * associated with (will return 0L if the client's GUI has not been built
+ * by a KXMLGUIFactory.
+ */
+ KXMLGUIFactory *factory() const;
+
+ /**
+ * KXMLGUIClients can form a simple child/parent object tree. This
+ * method returns a pointer to the parent client or 0L if it has no
+ * parent client assigned.
+ */
+ KXMLGUIClient *parentClient() const;
+
+ /**
+ * Use this method to make a client a child client of another client.
+ * Usually you don't need to call this method, as it is called
+ * automatically when using the second constructor, which takes a
+ * parent argument.
+ */
+ void insertChildClient( KXMLGUIClient *child );
+
+ /**
+ * Removes the given @p child from the client's children list.
+ */
+ void removeChildClient( KXMLGUIClient *child );
+
+ /**
+ * Retrieves a list of all child clients.
+ */
+ const QPtrList<KXMLGUIClient> *childClients();
+
+ /**
+ * A client can have an own KXMLGUIBuilder.
+ * Use this method to assign your builder instance to the client (so that the
+ * KXMLGUIFactory can use it when building the client's GUI)
+ *
+ * Client specific guibuilders are useful if you want to create
+ * custom container widgets for your GUI.
+ */
+ void setClientBuilder( KXMLGUIBuilder *builder );
+
+ /**
+ * Retrieves the client's GUI builder or 0L if no client specific
+ * builder has been assigned via setClientBuilder()
+ */
+ KXMLGUIBuilder *clientBuilder() const;
+
+ /**
+ * Forces this client to re-read its XML resource file. This is
+ * intended to be used when you know that the resource file has
+ * changed and you will soon be rebuilding the GUI. It has no
+ * useful effect with non-KParts GUIs, so don't bother using it
+ * unless your app is component based.
+ */
+ void reloadXML();
+
+ /**
+ * ActionLists are a way for XMLGUI to support dynamic lists of
+ * actions. E.g. if you are writing a file manager, and there is a
+ * menu file whose contents depend on the mimetype of the file that
+ * is selected, then you can achieve this using ActionLists. It
+ * works as follows:
+ * In your xxxui.rc file ( the one that you set in setXMLFile()
+ * ), you put an <p>\<ActionList name="xxx"\></p> tag. E.g.
+ * \verbatim
+ * <kpartgui name="xxx_part" version="1">
+ * <MenuBar>
+ * <Menu name="file">
+ * ... <!-- some useful actions-->
+ * <ActionList name="xxx_file_actionlist" />
+ * ... <!-- even more useful actions-->
+ * </Menu>
+ * ...
+ * </MenuBar>
+ * </kpartgui>
+ * \endverbatim
+ *
+ * This tag will get expanded to a list of actions. In the example
+ * above ( a file manager with a dynamic file menu ), you would call
+ * \code
+ * QPtrList<KAction> file_actions;
+ * for( ... )
+ * if( ... )
+ * file_actions.append( cool_action );
+ * unplugActionList( "xxx_file_actionlist" );
+ * plugActionList( "xxx_file_actionlist", file_actions );
+ * \endcode
+ * every time a file is selected, unselected or ...
+ *
+ * \note You should not call createGUI() after calling this
+ * function. In fact, that would remove the newly added
+ * actionlists again...
+ * \note Forgetting to call unplugActionList() before
+ * plugActionList() would leave the previous actions in the
+ * menu too..
+ */
+ void plugActionList( const QString &name, const QPtrList<KAction> &actionList );
+
+ /**
+ * The complement of plugActionList() ...
+ */
+ void unplugActionList( const QString &name );
+
+ static QString findMostRecentXMLFile( const QStringList &files, QString &doc );
+
+ void addStateActionEnabled(const QString& state, const QString& action);
+
+ void addStateActionDisabled(const QString& state, const QString& action);
+
+ enum ReverseStateChange { StateNoReverse, StateReverse };
+ struct StateChange
+ {
+ QStringList actionsToEnable;
+ QStringList actionsToDisable;
+ };
+
+ StateChange getActionsToChangeForState(const QString& state);
+
+ /// @since 3.1
+ void beginXMLPlug( QWidget * );
+ /// @since 3.1
+ void endXMLPlug();
+ /// @since 3.1
+ void prepareXMLUnplug( QWidget * );
+
+protected:
+ /**
+ * Returns true if client was added to super client list.
+ * Returns false if client was already in list.
+ */
+ //bool addSuperClient( KXMLGUIClient * );
+
+ /**
+ * Sets the instance ( KInstance) for this part.
+ *
+ * Call this first in the inherited class constructor.
+ * (At least before setXMLFile().)
+ */
+ virtual void setInstance( KInstance *instance );
+
+ /**
+ * Sets the name of the rc file containing the XML for the part.
+ *
+ * Call this in the Part-inherited class constructor.
+ *
+ * @param file Either an absolute path for the file, or simply the
+ * filename, which will then be assumed to be installed
+ * in the "data" resource, under a directory named like
+ * the instance.
+ * @param merge Whether to merge with the global document.
+ * @param setXMLDoc Specify whether to call setXML. Default is true.
+ * and the DOM document at once.
+ **/
+ virtual void setXMLFile( const QString& file, bool merge = false, bool setXMLDoc = true );
+
+ virtual void setLocalXMLFile( const QString &file );
+
+ /**
+ * Sets the XML for the part.
+ *
+ * Call this in the Part-inherited class constructor if you
+ * don't call setXMLFile().
+ **/
+ virtual void setXML( const QString &document, bool merge = false );
+
+ /**
+ * Sets the Document for the part, describing the layout of the GUI.
+ *
+ * Call this in the Part-inherited class constructor if you don't call
+ * setXMLFile or setXML .
+ */
+ virtual void setDOMDocument( const QDomDocument &document, bool merge = false );
+
+ /**
+ * This function will attempt to give up some memory after the GUI
+ * is built. It should never be used in apps where the GUI may be
+ * rebuilt at some later time (components, for instance).
+ */
+ virtual void conserveMemory();
+
+ /**
+ * Actions can collectively be assigned a "State". To accomplish this
+ * the respective actions are tagged as \<enable\> or \<disable\> in
+ * a \<State\> \</State\> group of the XMLfile. During program execution the
+ * programmer can call stateChanged() to set actions to a defined state.
+ *
+ * @param newstate Name of a State in the XMLfile.
+ * @param reverse If the flag reverse is set to StateReverse, the State is reversed.
+ * (actions to be enabled will be disabled and action to be disabled will be enabled)
+ * Default is reverse=false.
+ */
+ virtual void stateChanged(const QString &newstate, ReverseStateChange reverse = StateNoReverse);
+
+ // Use this one for KDE 4.0
+ //virtual void stateChanged(const QString &newstate, bool reverse = false);
+
+private:
+ struct DocStruct
+ {
+ QString file;
+ QString data;
+ };
+
+ bool mergeXML( QDomElement &base, const QDomElement &additive,
+ KActionCollection *actionCollection );
+
+ QDomElement findMatchingElement( const QDomElement &base,
+ const QDomElement &additive );
+
+ typedef QMap<QString, QMap<QString, QString> > ActionPropertiesMap;
+
+ static ActionPropertiesMap extractActionProperties( const QDomDocument &doc );
+
+ static void storeActionProperties( QDomDocument &doc, const ActionPropertiesMap &properties );
+
+ static QString findVersionNumber( const QString &_xml );
+
+ // Actions to enable/disable on a state change
+ QMap<QString,StateChange> m_actionsStateMap;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KXMLGUIClientPrivate *d;
+};
+
+#endif
diff --git a/kdeui/kxmlguifactory.cpp b/kdeui/kxmlguifactory.cpp
new file mode 100644
index 000000000..1dbab4ddf
--- /dev/null
+++ b/kdeui/kxmlguifactory.cpp
@@ -0,0 +1,614 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999,2000 Simon Hausmann <hausmann@kde.org>
+ Copyright (C) 2000 Kurt Granroth <granroth@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kxmlguifactory.h"
+#include "kxmlguifactory_p.h"
+#include "kxmlguiclient.h"
+#include "kxmlguibuilder.h"
+
+#include <assert.h>
+
+#include <qdir.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qwidget.h>
+#include <qdatetime.h>
+#include <qvariant.h>
+
+#include <kaction.h>
+#include <kdebug.h>
+#include <kinstance.h>
+#include <kglobal.h>
+#include <kshortcut.h>
+#include <kstandarddirs.h>
+#include <kkeydialog.h>
+
+using namespace KXMLGUI;
+
+/*
+ * TODO: - make more use of QValueList instead of QPtrList
+ */
+
+class KXMLGUIFactoryPrivate : public BuildState
+{
+public:
+ KXMLGUIFactoryPrivate()
+ {
+ static const QString &defaultMergingName = KGlobal::staticQString( "<default>" );
+ static const QString &actionList = KGlobal::staticQString( "actionlist" );
+ static const QString &name = KGlobal::staticQString( "name" );
+
+ m_rootNode = new ContainerNode( 0L, QString::null, 0L );
+ m_defaultMergingName = defaultMergingName;
+ tagActionList = actionList;
+ attrName = name;
+ }
+ ~KXMLGUIFactoryPrivate()
+ {
+ delete m_rootNode;
+ }
+
+ void pushState()
+ {
+ m_stateStack.push( *this );
+ }
+
+ void popState()
+ {
+ BuildState::operator=( m_stateStack.pop() );
+ }
+
+ ContainerNode *m_rootNode;
+
+ QString m_defaultMergingName;
+
+ /*
+ * Contains the container which is searched for in ::container .
+ */
+ QString m_containerName;
+
+ /*
+ * List of all clients
+ */
+ QPtrList<KXMLGUIClient> m_clients;
+
+ QString tagActionList;
+
+ QString attrName;
+
+ BuildStateStack m_stateStack;
+};
+
+QString KXMLGUIFactory::readConfigFile( const QString &filename, const KInstance *instance )
+{
+ return readConfigFile( filename, false, instance );
+}
+
+QString KXMLGUIFactory::readConfigFile( const QString &filename, bool never_null, const KInstance *_instance )
+{
+ const KInstance *instance = _instance ? _instance : KGlobal::instance();
+ QString xml_file;
+
+ if (!QDir::isRelativePath(filename))
+ xml_file = filename;
+ else
+ {
+ xml_file = locate("data", QString::fromLatin1(instance->instanceName() + '/' ) + filename);
+ if ( !QFile::exists( xml_file ) )
+ xml_file = locate( "data", filename );
+ }
+
+ QFile file( xml_file );
+ if ( !file.open( IO_ReadOnly ) )
+ {
+ kdError(240) << "No such XML file " << filename << endl;
+ if ( never_null )
+ return QString::fromLatin1( "<!DOCTYPE kpartgui>\n<kpartgui name=\"empty\">\n</kpartgui>" );
+ else
+ return QString::null;
+ }
+
+#if QT_VERSION <= 0x030302
+ // Work around bug in QString::fromUtf8 (which calls strlen).
+ QByteArray buffer(file.size() + 1);
+ buffer = file.readAll();
+ if(!buffer.isEmpty())
+ buffer[ buffer.size() - 1 ] = '\0';
+ else
+ return QString::null;
+#else
+ QByteArray buffer(file.readAll());
+#endif
+ return QString::fromUtf8(buffer.data(), buffer.size());
+}
+
+bool KXMLGUIFactory::saveConfigFile( const QDomDocument& doc,
+ const QString& filename, const KInstance *_instance )
+{
+ const KInstance *instance = _instance ? _instance : KGlobal::instance();
+ QString xml_file(filename);
+
+ if (QDir::isRelativePath(xml_file))
+ xml_file = locateLocal("data", QString::fromLatin1( instance->instanceName() + '/' )
+ + filename);
+
+ QFile file( xml_file );
+ if ( !file.open( IO_WriteOnly ) )
+ {
+ kdError(240) << "Could not write to " << filename << endl;
+ return false;
+ }
+
+ // write out our document
+ QTextStream ts(&file);
+ ts.setEncoding( QTextStream::UnicodeUTF8 );
+ ts << doc;
+
+ file.close();
+ return true;
+}
+
+QString KXMLGUIFactory::documentToXML( const QDomDocument& doc )
+{
+ QString str;
+ QTextStream ts(&str, IO_WriteOnly);
+ ts.setEncoding( QTextStream::UnicodeUTF8 );
+ ts << doc;
+ return str;
+}
+
+QString KXMLGUIFactory::elementToXML( const QDomElement& elem )
+{
+ QString str;
+ QTextStream ts(&str, IO_WriteOnly);
+ ts.setEncoding( QTextStream::UnicodeUTF8 );
+ ts << elem;
+ return str;
+}
+
+void KXMLGUIFactory::removeDOMComments( QDomNode &node )
+{
+ QDomNode n = node.firstChild();
+ while ( !n.isNull() )
+ {
+ if ( n.nodeType() == QDomNode::CommentNode )
+ {
+ QDomNode tmp = n;
+ n = n.nextSibling();
+ node.removeChild( tmp );
+ }
+ else
+ {
+ QDomNode tmp = n;
+ n = n.nextSibling();
+ removeDOMComments( tmp );
+ }
+ }
+}
+
+KXMLGUIFactory::KXMLGUIFactory( KXMLGUIBuilder *builder, QObject *parent, const char *name )
+ : QObject( parent, name )
+{
+ d = new KXMLGUIFactoryPrivate;
+ d->builder = builder;
+ d->guiClient = 0;
+ if ( d->builder )
+ {
+ d->builderContainerTags = d->builder->containerTags();
+ d->builderCustomTags = d->builder->customTags();
+ }
+}
+
+KXMLGUIFactory::~KXMLGUIFactory()
+{
+ delete d;
+}
+
+void KXMLGUIFactory::addClient( KXMLGUIClient *client )
+{
+ kdDebug(1002) << "KXMLGUIFactory::addClient( " << client << " )" << endl; // ellis
+ static const QString &actionPropElementName = KGlobal::staticQString( "ActionProperties" );
+
+ if ( client->factory() ) {
+ if ( client->factory() == this )
+ return;
+ else
+ client->factory()->removeClient( client ); //just in case someone does stupid things ;-)
+ }
+
+ d->pushState();
+
+// QTime dt; dt.start();
+
+ d->guiClient = client;
+
+ // add this client to our client list
+ if ( !d->m_clients.containsRef( client ) )
+ d->m_clients.append( client );
+ else
+ kdDebug(1002) << "XMLGUI client already added " << client << endl;
+
+ // Tell the client that plugging in is process and
+ // let it know what builder widget its mainwindow shortcuts
+ // should be attached to.
+ client->beginXMLPlug( d->builder->widget() );
+
+ // try to use the build document for building the client's GUI, as the build document
+ // contains the correct container state information (like toolbar positions, sizes, etc.) .
+ // if there is non available, then use the "real" document.
+ QDomDocument doc = client->xmlguiBuildDocument();
+ if ( doc.documentElement().isNull() )
+ doc = client->domDocument();
+
+ QDomElement docElement = doc.documentElement();
+
+ d->m_rootNode->index = -1;
+
+ // cache some variables
+
+ d->clientName = docElement.attribute( d->attrName );
+ d->clientBuilder = client->clientBuilder();
+
+ if ( d->clientBuilder )
+ {
+ d->clientBuilderContainerTags = d->clientBuilder->containerTags();
+ d->clientBuilderCustomTags = d->clientBuilder->customTags();
+ }
+ else
+ {
+ d->clientBuilderContainerTags.clear();
+ d->clientBuilderCustomTags.clear();
+ }
+
+ // process a possibly existing actionproperties section
+
+ QDomElement actionPropElement = docElement.namedItem( actionPropElementName ).toElement();
+ if ( actionPropElement.isNull() )
+ actionPropElement = docElement.namedItem( actionPropElementName.lower() ).toElement();
+
+ if ( !actionPropElement.isNull() )
+ applyActionProperties( actionPropElement );
+
+ BuildHelper( *d, d->m_rootNode ).build( docElement );
+
+ // let the client know that we built its GUI.
+ client->setFactory( this );
+
+ // call the finalizeGUI method, to fix up the positions of toolbars for example.
+ // ### FIXME : obey client builder
+ // --- Well, toolbars have a bool "positioned", so it doesn't really matter,
+ // if we call positionYourself on all of them each time. (David)
+ d->builder->finalizeGUI( d->guiClient );
+
+ // reset some variables, for safety
+ d->BuildState::reset();
+
+ client->endXMLPlug();
+
+ d->popState();
+
+ emit clientAdded( client );
+
+ // build child clients
+ if ( client->childClients()->count() > 0 )
+ {
+ const QPtrList<KXMLGUIClient> *children = client->childClients();
+ QPtrListIterator<KXMLGUIClient> childIt( *children );
+ for (; childIt.current(); ++childIt )
+ addClient( childIt.current() );
+ }
+
+// kdDebug() << "addClient took " << dt.elapsed() << endl;
+}
+
+void KXMLGUIFactory::removeClient( KXMLGUIClient *client )
+{
+ kdDebug(1002) << "KXMLGUIFactory::removeClient( " << client << " )" << endl; // ellis
+
+ // don't try to remove the client's GUI if we didn't build it
+ if ( !client || client->factory() != this )
+ return;
+
+ // remove this client from our client list
+ d->m_clients.removeRef( client );
+
+ // remove child clients first
+ if ( client->childClients()->count() > 0 )
+ {
+ const QPtrList<KXMLGUIClient> *children = client->childClients();
+ QPtrListIterator<KXMLGUIClient> childIt( *children );
+ childIt.toLast();
+ for (; childIt.current(); --childIt )
+ removeClient( childIt.current() );
+ }
+
+ kdDebug(1002) << "KXMLGUIFactory::removeServant, calling removeRecursive" << endl;
+
+ d->pushState();
+
+ // cache some variables
+
+ d->guiClient = client;
+ d->clientName = client->domDocument().documentElement().attribute( d->attrName );
+ d->clientBuilder = client->clientBuilder();
+
+ client->setFactory( 0L );
+
+ // if we don't have a build document for that client, yet, then create one by
+ // cloning the original document, so that saving container information in the
+ // DOM tree does not touch the original document.
+ QDomDocument doc = client->xmlguiBuildDocument();
+ if ( doc.documentElement().isNull() )
+ {
+ doc = client->domDocument().cloneNode( true ).toDocument();
+ client->setXMLGUIBuildDocument( doc );
+ }
+
+ d->m_rootNode->destruct( doc.documentElement(), *d );
+
+ d->builder->finalizeGUI( d->guiClient ); //JoWenn
+
+ // reset some variables
+ d->BuildState::reset();
+
+ // This will destruct the KAccel object built around the given widget.
+ client->prepareXMLUnplug( d->builder->widget() );
+
+ d->popState();
+
+ emit clientRemoved( client );
+}
+
+QPtrList<KXMLGUIClient> KXMLGUIFactory::clients() const
+{
+ return d->m_clients;
+}
+
+QWidget *KXMLGUIFactory::container( const QString &containerName, KXMLGUIClient *client,
+ bool useTagName )
+{
+ d->pushState();
+ d->m_containerName = containerName;
+ d->guiClient = client;
+
+ QWidget *result = findRecursive( d->m_rootNode, useTagName );
+
+ d->guiClient = 0L;
+ d->m_containerName = QString::null;
+
+ d->popState();
+
+ return result;
+}
+
+QPtrList<QWidget> KXMLGUIFactory::containers( const QString &tagName )
+{
+ return findRecursive( d->m_rootNode, tagName );
+}
+
+void KXMLGUIFactory::reset()
+{
+ d->m_rootNode->reset();
+
+ d->m_rootNode->clearChildren();
+}
+
+void KXMLGUIFactory::resetContainer( const QString &containerName, bool useTagName )
+{
+ if ( containerName.isEmpty() )
+ return;
+
+ ContainerNode *container = d->m_rootNode->findContainer( containerName, useTagName );
+
+ if ( !container )
+ return;
+
+ ContainerNode *parent = container->parent;
+ if ( !parent )
+ return;
+
+ // resetInternal( container );
+
+ parent->removeChild( container );
+}
+
+QWidget *KXMLGUIFactory::findRecursive( KXMLGUI::ContainerNode *node, bool tag )
+{
+ if ( ( ( !tag && node->name == d->m_containerName ) ||
+ ( tag && node->tagName == d->m_containerName ) ) &&
+ ( !d->guiClient || node->client == d->guiClient ) )
+ return node->container;
+
+ QPtrListIterator<ContainerNode> it( node->children );
+ for (; it.current(); ++it )
+ {
+ QWidget *cont = findRecursive( it.current(), tag );
+ if ( cont )
+ return cont;
+ }
+
+ return 0L;
+}
+
+QPtrList<QWidget> KXMLGUIFactory::findRecursive( KXMLGUI::ContainerNode *node,
+ const QString &tagName )
+{
+ QPtrList<QWidget> res;
+
+ if ( node->tagName == tagName.lower() )
+ res.append( node->container );
+
+ QPtrListIterator<KXMLGUI::ContainerNode> it( node->children );
+ for (; it.current(); ++it )
+ {
+ QPtrList<QWidget> lst = findRecursive( it.current(), tagName );
+ QPtrListIterator<QWidget> wit( lst );
+ for (; wit.current(); ++wit )
+ res.append( wit.current() );
+ }
+
+ return res;
+}
+
+void KXMLGUIFactory::plugActionList( KXMLGUIClient *client, const QString &name,
+ const QPtrList<KAction> &actionList )
+{
+ d->pushState();
+ d->guiClient = client;
+ d->actionListName = name;
+ d->actionList = actionList;
+ d->clientName = client->domDocument().documentElement().attribute( d->attrName );
+
+ d->m_rootNode->plugActionList( *d );
+
+ d->BuildState::reset();
+ d->popState();
+}
+
+void KXMLGUIFactory::unplugActionList( KXMLGUIClient *client, const QString &name )
+{
+ d->pushState();
+ d->guiClient = client;
+ d->actionListName = name;
+ d->clientName = client->domDocument().documentElement().attribute( d->attrName );
+
+ d->m_rootNode->unplugActionList( *d );
+
+ d->BuildState::reset();
+ d->popState();
+}
+
+void KXMLGUIFactory::applyActionProperties( const QDomElement &actionPropElement )
+{
+ static const QString &tagAction = KGlobal::staticQString( "action" );
+
+ for (QDomNode n = actionPropElement.firstChild();
+ !n.isNull(); n = n.nextSibling() )
+ {
+ QDomElement e = n.toElement();
+ if ( e.tagName().lower() != tagAction )
+ continue;
+
+ KAction *action = d->guiClient->action( e );
+ if ( !action )
+ continue;
+
+ configureAction( action, e.attributes() );
+ }
+}
+
+void KXMLGUIFactory::configureAction( KAction *action, const QDomNamedNodeMap &attributes )
+{
+ for ( uint i = 0; i < attributes.length(); i++ )
+ {
+ QDomAttr attr = attributes.item( i ).toAttr();
+ if ( attr.isNull() )
+ continue;
+
+ configureAction( action, attr );
+ }
+}
+
+void KXMLGUIFactory::configureAction( KAction *action, const QDomAttr &attribute )
+{
+ static const QString &attrShortcut = KGlobal::staticQString( "shortcut" );
+
+ QString attrName = attribute.name();
+ // If the attribute is a deprecated "accel", change to "shortcut".
+ if ( attrName.lower() == "accel" )
+ attrName = attrShortcut;
+
+ QVariant propertyValue;
+
+ QVariant::Type propertyType = action->property( attrName.latin1() ).type();
+
+ if ( propertyType == QVariant::Int )
+ propertyValue = QVariant( attribute.value().toInt() );
+ else if ( propertyType == QVariant::UInt )
+ propertyValue = QVariant( attribute.value().toUInt() );
+ else
+ propertyValue = QVariant( attribute.value() );
+
+ action->setProperty( attrName.latin1(), propertyValue );
+}
+
+
+int KXMLGUIFactory::configureShortcuts(bool bAllowLetterShortcuts , bool bSaveSettings )
+{
+ KKeyDialog dlg( bAllowLetterShortcuts, dynamic_cast<QWidget*>(parent()) );
+ QPtrListIterator<KXMLGUIClient> it( d->m_clients );
+ KXMLGUIClient *client;
+ while( (client=it.current()) !=0 )
+ {
+ ++it;
+ if(!client->xmlFile().isEmpty())
+ dlg.insert( client->actionCollection() );
+ }
+ return dlg.configure(bSaveSettings);
+}
+
+QDomElement KXMLGUIFactory::actionPropertiesElement( QDomDocument& doc )
+{
+ const QString tagActionProp = QString::fromLatin1("ActionProperties");
+ // first, lets see if we have existing properties
+ QDomElement elem;
+ QDomNode it = doc.documentElement().firstChild();
+ for( ; !it.isNull(); it = it.nextSibling() ) {
+ QDomElement e = it.toElement();
+ if( e.tagName() == tagActionProp ) {
+ elem = e;
+ break;
+ }
+ }
+
+ // if there was none, create one
+ if( elem.isNull() ) {
+ elem = doc.createElement( tagActionProp );
+ doc.documentElement().appendChild( elem );
+ }
+ return elem;
+}
+
+QDomElement KXMLGUIFactory::findActionByName( QDomElement& elem, const QString& sName, bool create )
+{
+ static const QString& attrName = KGlobal::staticQString( "name" );
+ static const QString& tagAction = KGlobal::staticQString( "Action" );
+ for( QDomNode it = elem.firstChild(); !it.isNull(); it = it.nextSibling() ) {
+ QDomElement e = it.toElement();
+ if( e.attribute( attrName ) == sName )
+ return e;
+ }
+
+ if( create ) {
+ QDomElement act_elem = elem.ownerDocument().createElement( tagAction );
+ act_elem.setAttribute( attrName, sName );
+ elem.appendChild( act_elem );
+ return act_elem;
+ }
+ return QDomElement();
+}
+
+void KXMLGUIFactory::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "kxmlguifactory.moc"
+
+/* vim: et sw=4
+ */
diff --git a/kdeui/kxmlguifactory.h b/kdeui/kxmlguifactory.h
new file mode 100644
index 000000000..cb4a86ef3
--- /dev/null
+++ b/kdeui/kxmlguifactory.h
@@ -0,0 +1,220 @@
+// -*- mode: c++; c-basic-offset: 2 -*-
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Simon Hausmann <hausmann@kde.org>
+ Copyright (C) 2000 Kurt Granroth <granroth@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __kxmlguifactory_h__
+#define __kxmlguifactory_h__
+
+#include <qobject.h>
+#include <qptrlist.h>
+#include <qdom.h>
+#include <qvaluelist.h>
+
+#include <kdelibs_export.h>
+
+class KAction;
+class KXMLGUIFactoryPrivate;
+class KXMLGUIClient;
+class KXMLGUIBuilder;
+class KInstance;
+
+namespace KXMLGUI
+{
+struct MergingIndex;
+struct ContainerNode;
+struct ContainerClient;
+class BuildHelper;
+}
+
+/**
+ * KXMLGUIFactory, together with KXMLGUIClient objects, can be used to create
+ * a GUI of container widgets (like menus, toolbars, etc.) and container items
+ * (menu items, toolbar buttons, etc.) from an XML document and action objects.
+ *
+ * Each KXMLGUIClient represents a part of the GUI, composed from containers and
+ * actions. KXMLGUIFactory takes care of building (with the help of a KXMLGUIBuilder)
+ * and merging the GUI from an unlimited number of clients.
+ *
+ * Each client provides XML through a QDomDocument and actions through a
+ * KActionCollection . The XML document contains the rules for how to merge the
+ * GUI.
+ *
+ * KXMLGUIFactory processes the DOM tree provided by a client and plugs in the client's actions,
+ * according to the XML and the merging rules of previously inserted clients. Container widgets
+ * are built via a KXMLGUIBuilder , which has to be provided with the KXMLGUIFactory constructor.
+ */
+class KDEUI_EXPORT KXMLGUIFactory : public QObject
+{
+ friend class KXMLGUI::BuildHelper;
+ Q_OBJECT
+ public:
+ /**
+ * Constructs a KXMLGUIFactory. The provided @p builder KXMLGUIBuilder will be called
+ * for creating and removing container widgets, when clients are added/removed from the GUI.
+ *
+ * Note that the ownership of the given KXMLGUIBuilder object won't be transferred to this
+ * KXMLGUIFactory, so you have to take care of deleting it properly.
+ */
+ KXMLGUIFactory( KXMLGUIBuilder *builder, QObject *parent = 0, const char *name = 0 );
+
+ /**
+ * Destructor
+ */
+ ~KXMLGUIFactory();
+
+ // XXX move to somewhere else? (Simon)
+ static QString readConfigFile( const QString &filename, bool never_null, const KInstance *instance = 0 );
+ static QString readConfigFile( const QString &filename, const KInstance *instance = 0 );
+ static bool saveConfigFile( const QDomDocument& doc, const QString& filename,
+ const KInstance *instance = 0 );
+
+ static QString documentToXML( const QDomDocument& doc );
+ static QString elementToXML( const QDomElement& elem );
+
+ /**
+ * Removes all QDomComment objects from the specified node and all its children.
+ */
+ static void removeDOMComments( QDomNode &node );
+
+ /**
+ * @internal
+ * Find or create the ActionProperties element, used when saving custom action properties
+ */
+ static QDomElement actionPropertiesElement( QDomDocument& doc );
+
+ /**
+ * @internal
+ * Find or create the element for a given action, by name.
+ * Used when saving custom action properties
+ */
+ static QDomElement findActionByName( QDomElement& elem, const QString& sName, bool create );
+
+ /**
+ * Creates the GUI described by the QDomDocument of the client,
+ * using the client's actions, and merges it with the previously
+ * created GUI.
+ * This also means that the order in which clients are added to the factory
+ * is relevant; assuming that your application supports plugins, you should
+ * first add your application to the factory and then the plugin, so that the
+ * plugin's UI is merged into the UI of your application, and not the other
+ * way round.
+ */
+ void addClient( KXMLGUIClient *client );
+
+ /**
+ * Removes the GUI described by the client, by unplugging all
+ * provided actions and removing all owned containers (and storing
+ * container state information in the given client)
+ */
+ void removeClient( KXMLGUIClient *client );
+
+ void plugActionList( KXMLGUIClient *client, const QString &name, const QPtrList<KAction> &actionList );
+ void unplugActionList( KXMLGUIClient *client, const QString &name );
+
+ /**
+ * Returns a list of all clients currently added to this factory
+ */
+ QPtrList<KXMLGUIClient> clients() const;
+
+ /**
+ * Use this method to get access to a container widget with the name specified with @p containerName
+ * and which is owned by the @p client. The container name is specified with a "name" attribute in the
+ * XML document.
+ *
+ * This function is particularly useful for getting hold of a popupmenu defined in an XMLUI file.
+ * For instance:
+ * \code
+ * QPopupMenu *popup = static_cast<QPopupMenu*>(factory()->container("my_popup",this));
+ * \endcode
+ * where @p "my_popup" is the name of the menu in the XMLUI file, and
+ * @p "this" is XMLGUIClient which owns the popupmenu (e.g. the mainwindow, or the part, or the plugin...)
+ *
+ * @param containerName Name of the container widget
+ * @param client Owner of the container widget
+ * @param useTagName Specifies whether to compare the specified name with the name attribute or
+ * the tag name.
+ *
+ * This method may return 0L if no container with the given name exists or is not owned by the client.
+ */
+ QWidget *container( const QString &containerName, KXMLGUIClient *client, bool useTagName = false );
+
+ QPtrList<QWidget> containers( const QString &tagName );
+
+ /**
+ * Use this method to free all memory allocated by the KXMLGUIFactory. This deletes the internal node
+ * tree and therefore resets the internal state of the class. Please note that the actual GUI is
+ * NOT touched at all, meaning no containers are deleted nor any actions unplugged. That is
+ * something you have to do on your own. So use this method only if you know what you are doing :-)
+ *
+ * (also note that this will call KXMLGUIClient::setFactory( 0L ) for all inserted clients)
+ */
+ void reset();
+
+ /**
+ * Use this method to free all memory allocated by the KXMLGUIFactory for a specific container,
+ * including all child containers and actions. This deletes the internal node subtree for the
+ * specified container. The actual GUI is not touched, no containers are deleted or any actions
+ * unplugged. Use this method only if you know what you are doing :-)
+ *
+ * (also note that this will call KXMLGUIClient::setFactory( 0L ) for all clients of the
+ * container)
+ */
+ void resetContainer( const QString &containerName, bool useTagName = false );
+
+ public slots:
+ /**
+ * Show a standard configure shortcut for every action in this factory.
+ *
+ * This slot can be connected dirrectly to the action to configure shortcuts. This is very simple to
+ * do that by adding a single line
+ * \code
+ * KStdAction::keyBindings( guiFactory(), SLOT( configureShortcuts() ), actionCollection() );
+ * \endcode
+ *
+ * @param bAllowLetterShortcuts Set to false if unmodified alphanumeric
+ * keys ('A', '1', etc.) are not permissible shortcuts.
+ * @param bSaveSettings if true, the settings will also be saved back to
+ * the *uirc file which they were intially read from.
+ * @since 3.3
+ */
+ int configureShortcuts(bool bAllowLetterShortcuts = true, bool bSaveSettings = true);
+
+ signals:
+ void clientAdded( KXMLGUIClient *client );
+ void clientRemoved( KXMLGUIClient *client );
+
+ private:
+
+ QWidget *findRecursive( KXMLGUI::ContainerNode *node, bool tag );
+
+ QPtrList<QWidget> findRecursive( KXMLGUI::ContainerNode *node, const QString &tagName );
+
+ void applyActionProperties( const QDomElement &element );
+ void configureAction( KAction *action, const QDomNamedNodeMap &attributes );
+ void configureAction( KAction *action, const QDomAttr &attribute );
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KXMLGUIFactoryPrivate *d;
+};
+
+#endif
+/* vim: et sw=4
+ */
diff --git a/kdeui/kxmlguifactory_p.cpp b/kdeui/kxmlguifactory_p.cpp
new file mode 100644
index 000000000..329b11881
--- /dev/null
+++ b/kdeui/kxmlguifactory_p.cpp
@@ -0,0 +1,836 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2001 Simon Hausmann <hausmann@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kxmlguifactory_p.h"
+#include "kxmlguiclient.h"
+#include "kxmlguibuilder.h"
+
+#include <qwidget.h>
+
+#include <kglobal.h>
+#include <kdebug.h>
+
+#include <assert.h>
+
+using namespace KXMLGUI;
+
+void ActionList::plug( QWidget *container, int index ) const
+{
+ ActionListIt it( *this );
+ for (; it.current(); ++it )
+ it.current()->plug( container, index++ );
+}
+
+void ActionList::unplug( QWidget *container ) const
+{
+ ActionListIt it( *this );
+ for (; it.current(); ++it )
+ it.current()->unplug( container );
+}
+
+ContainerNode::ContainerNode( QWidget *_container, const QString &_tagName,
+ const QString &_name, ContainerNode *_parent,
+ KXMLGUIClient *_client, KXMLGUIBuilder *_builder,
+ int id, const QString &_mergingName,
+ const QString &_groupName, const QStringList &customTags,
+ const QStringList &containerTags )
+ : parent( _parent ), client( _client ), builder( _builder ),
+ builderCustomTags( customTags ), builderContainerTags( containerTags ),
+ container( _container ), containerId( id ), tagName( _tagName ), name( _name ),
+ groupName( _groupName ), index( 0 ), mergingName( _mergingName )
+{
+ children.setAutoDelete( true );
+ clients.setAutoDelete( true );
+
+ if ( parent )
+ parent->children.append( this );
+}
+
+void ContainerNode::removeChild( ContainerNode *child )
+{
+ MergingIndexList::Iterator mergingIt = findIndex( child->mergingName );
+ adjustMergingIndices( -1, mergingIt );
+ children.removeRef( child );
+}
+
+/*
+ * Find a merging index with the given name. Used to find an index defined by <Merge name="blah"/>
+ * or by a <DefineGroup name="foo" /> tag.
+ */
+MergingIndexList::Iterator ContainerNode::findIndex( const QString &name )
+{
+ MergingIndexList::Iterator it( mergingIndices.begin() );
+ MergingIndexList::Iterator end( mergingIndices.end() );
+ for (; it != end; ++it )
+ if ( (*it).mergingName == name )
+ return it;
+ return it;
+}
+
+/*
+ * Check if the given container widget is a child of this node and return the node structure
+ * if fonud.
+ */
+ContainerNode *ContainerNode::findContainerNode( QWidget *container )
+{
+ ContainerNodeListIt it( children );
+
+ for (; it.current(); ++it )
+ if ( it.current()->container == container )
+ return it.current();
+
+ return 0L;
+}
+
+/*
+ * Find a container recursively with the given name. Either compares _name with the
+ * container's tag name or the value of the container's name attribute. Specified by
+ * the tag bool .
+ */
+ContainerNode *ContainerNode::findContainer( const QString &_name, bool tag )
+{
+ if ( ( tag && tagName == _name ) ||
+ ( !tag && name == _name ) )
+ return this;
+
+ ContainerNodeListIt it( children );
+ for (; it.current(); ++it )
+ {
+ ContainerNode *res = it.current()->findContainer( _name, tag );
+ if ( res )
+ return res;
+ }
+
+ return 0;
+}
+
+/*
+ * Finds a child container node (not recursively) with the given name and tagname. Explicitly
+ * leaves out container widgets specified in the exludeList . Also ensures that the containers
+ * belongs to currClient.
+ */
+ContainerNode *ContainerNode::findContainer( const QString &name, const QString &tagName,
+ const QPtrList<QWidget> *excludeList,
+ KXMLGUIClient * /*currClient*/ )
+{
+ ContainerNode *res = 0L;
+ ContainerNodeListIt nIt( children );
+
+ if ( !name.isEmpty() )
+ {
+ for (; nIt.current(); ++nIt )
+ if ( nIt.current()->name == name &&
+ !excludeList->containsRef( nIt.current()->container ) )
+ {
+ res = nIt.current();
+ break;
+ }
+
+ return res;
+ }
+
+ if ( !tagName.isEmpty() )
+ for (; nIt.current(); ++nIt )
+ {
+ if ( nIt.current()->tagName == tagName &&
+ !excludeList->containsRef( nIt.current()->container )
+ /*
+ * It is a bad idea to also compare the client, because
+ * we don't want to do so in situations like these:
+ *
+ * <MenuBar>
+ * <Menu>
+ * ...
+ *
+ * other client:
+ * <MenuBar>
+ * <Menu>
+ * ...
+ *
+ && nIt.current()->client == currClient )
+ */
+ )
+ {
+ res = nIt.current();
+ break;
+ }
+ }
+
+ return res;
+}
+
+ContainerClient *ContainerNode::findChildContainerClient( KXMLGUIClient *currentGUIClient,
+ const QString &groupName,
+ const MergingIndexList::Iterator &mergingIdx )
+{
+ if ( !clients.isEmpty() )
+ {
+ ContainerClientListIt clientIt( clients );
+
+ for (; clientIt.current(); ++clientIt )
+ if ( clientIt.current()->client == currentGUIClient )
+ {
+ if ( groupName.isEmpty() )
+ return clientIt.current();
+
+ if ( groupName == clientIt.current()->groupName )
+ return clientIt.current();
+ }
+ }
+
+ ContainerClient *client = new ContainerClient;
+ client->client = currentGUIClient;
+ client->groupName = groupName;
+
+ if ( mergingIdx != mergingIndices.end() )
+ client->mergingName = (*mergingIdx).mergingName;
+
+ clients.append( client );
+
+ return client;
+}
+
+void ContainerNode::plugActionList( BuildState &state )
+{
+ MergingIndexList::Iterator mIt( mergingIndices.begin() );
+ MergingIndexList::Iterator mEnd( mergingIndices.end() );
+ for (; mIt != mEnd; ++mIt )
+ plugActionList( state, mIt );
+
+ QPtrListIterator<ContainerNode> childIt( children );
+ for (; childIt.current(); ++childIt )
+ childIt.current()->plugActionList( state );
+}
+
+void ContainerNode::plugActionList( BuildState &state, const MergingIndexList::Iterator &mergingIdxIt )
+{
+ static const QString &tagActionList = KGlobal::staticQString( "actionlist" );
+
+ MergingIndex mergingIdx = *mergingIdxIt;
+
+ QString k( mergingIdx.mergingName );
+
+ if ( k.find( tagActionList ) == -1 )
+ return;
+
+ k = k.mid( tagActionList.length() );
+
+ if ( mergingIdx.clientName != state.clientName )
+ return;
+
+ if ( k != state.actionListName )
+ return;
+
+ ContainerClient *client = findChildContainerClient( state.guiClient,
+ QString::null,
+ mergingIndices.end() );
+
+ client->actionLists.insert( k, state.actionList );
+
+ state.actionList.plug( container, mergingIdx.value );
+
+ adjustMergingIndices( state.actionList.count(), mergingIdxIt );
+}
+
+void ContainerNode::unplugActionList( BuildState &state )
+{
+ MergingIndexList::Iterator mIt( mergingIndices.begin() );
+ MergingIndexList::Iterator mEnd( mergingIndices.end() );
+ for (; mIt != mEnd; ++mIt )
+ unplugActionList( state, mIt );
+
+ QPtrListIterator<ContainerNode> childIt( children );
+ for (; childIt.current(); ++childIt )
+ childIt.current()->unplugActionList( state );
+}
+
+void ContainerNode::unplugActionList( BuildState &state, const MergingIndexList::Iterator &mergingIdxIt )
+{
+ static const QString &tagActionList = KGlobal::staticQString( "actionlist" );
+
+ MergingIndex mergingIdx = *mergingIdxIt;
+
+ QString k = mergingIdx.mergingName;
+
+ if ( k.find( tagActionList ) == -1 )
+ return;
+
+ k = k.mid( tagActionList.length() );
+
+ if ( mergingIdx.clientName != state.clientName )
+ return;
+
+ if ( k != state.actionListName )
+ return;
+
+ ContainerClient *client = findChildContainerClient( state.guiClient,
+ QString::null,
+ mergingIndices.end() );
+
+ ActionListMap::Iterator lIt( client->actionLists.find( k ) );
+ if ( lIt == client->actionLists.end() )
+ return;
+
+ lIt.data().unplug( container );
+
+ adjustMergingIndices( -int(lIt.data().count()), mergingIdxIt );
+
+ client->actionLists.remove( lIt );
+}
+
+void ContainerNode::adjustMergingIndices( int offset,
+ const MergingIndexList::Iterator &it )
+{
+ MergingIndexList::Iterator mergingIt = it;
+ MergingIndexList::Iterator mergingEnd = mergingIndices.end();
+
+ for (; mergingIt != mergingEnd; ++mergingIt )
+ (*mergingIt).value += offset;
+
+ index += offset;
+}
+
+bool ContainerNode::destruct( QDomElement element, BuildState &state )
+{
+ destructChildren( element, state );
+
+ unplugActions( state );
+
+ // remove all merging indices the client defined
+ MergingIndexList::Iterator cmIt = mergingIndices.begin();
+ while ( cmIt != mergingIndices.end() )
+ if ( (*cmIt).clientName == state.clientName )
+ cmIt = mergingIndices.remove( cmIt );
+ else
+ ++cmIt;
+
+ // ### check for merging index count, too?
+ if ( clients.count() == 0 && children.count() == 0 && container &&
+ client == state.guiClient )
+ {
+ QWidget *parentContainer = 0L;
+
+ if ( parent && parent->container )
+ parentContainer = parent->container;
+
+ assert( builder );
+
+ builder->removeContainer( container, parentContainer, element, containerId );
+
+ client = 0L;
+
+ return true;
+ }
+
+ if ( client == state.guiClient )
+ client = 0L;
+
+ return false;
+
+}
+
+void ContainerNode::destructChildren( const QDomElement &element, BuildState &state )
+{
+ QPtrListIterator<ContainerNode> childIt( children );
+ while ( childIt.current() )
+ {
+ ContainerNode *childNode = childIt.current();
+
+ QDomElement childElement = findElementForChild( element, childNode );
+
+ // destruct returns true in case the container really got deleted
+ if ( childNode->destruct( childElement, state ) )
+ removeChild( childNode );
+ else
+ ++childIt;
+ }
+}
+
+QDomElement ContainerNode::findElementForChild( const QDomElement &baseElement,
+ ContainerNode *childNode )
+{
+ static const QString &attrName = KGlobal::staticQString( "name" );
+
+ // ### slow
+ for ( QDomNode n = baseElement.firstChild(); !n.isNull();
+ n = n.nextSibling() )
+ {
+ QDomElement e = n.toElement();
+ if ( e.tagName().lower() == childNode->tagName &&
+ e.attribute( attrName ) == childNode->name )
+ return e;
+ }
+
+ return QDomElement();
+}
+
+void ContainerNode::unplugActions( BuildState &state )
+{
+ if ( !container )
+ return;
+
+ ContainerClientListIt clientIt( clients );
+
+ /*
+ Disabled because it means in KToolBar::saveState isHidden is always true then,
+ which is clearly wrong.
+
+ if ( clients.count() == 1 && clientIt.current()->client == client &&
+ client == state.guiClient )
+ container->hide(); // this container is going to die, that's for sure.
+ // in this case let's just hide it, which makes the
+ // destruction faster
+ */
+
+ while ( clientIt.current() )
+ //only unplug the actions of the client we want to remove, as the container might be owned
+ //by a different client
+ if ( clientIt.current()->client == state.guiClient )
+ {
+ unplugClient( clientIt.current() );
+ clients.removeRef( clientIt.current() );
+ }
+ else
+ ++clientIt;
+}
+
+void ContainerNode::unplugClient( ContainerClient *client )
+{
+ static const QString &tagActionList = KGlobal::staticQString( "actionlist" );
+
+ assert( builder );
+
+ // now quickly remove all custom elements (i.e. separators) and unplug all actions
+
+ QValueList<int>::ConstIterator custIt = client->customElements.begin();
+ QValueList<int>::ConstIterator custEnd = client->customElements.end();
+ for (; custIt != custEnd; ++custIt )
+ builder->removeCustomElement( container, *custIt );
+
+ client->actions.unplug( container );
+
+ // now adjust all merging indices
+
+ MergingIndexList::Iterator mergingIt = findIndex( client->mergingName );
+
+ adjustMergingIndices( - int( client->actions.count()
+ + client->customElements.count() ),
+ mergingIt );
+
+ // unplug all actionslists
+
+ ActionListMap::ConstIterator alIt = client->actionLists.begin();
+ ActionListMap::ConstIterator alEnd = client->actionLists.end();
+ for (; alIt != alEnd; ++alIt )
+ {
+ alIt.data().unplug( container );
+
+ // construct the merging index key (i.e. like named merging) , find the
+ // corresponding merging index and adjust all indices
+ QString mergingKey = alIt.key();
+ mergingKey.prepend( tagActionList );
+
+ MergingIndexList::Iterator mIt = findIndex( mergingKey );
+ if ( mIt == mergingIndices.end() )
+ continue;
+
+ adjustMergingIndices( -int(alIt.data().count()), mIt );
+
+ // remove the actionlists' merging index
+ // ### still needed? we clean up below anyway?
+ mergingIndices.remove( mIt );
+ }
+}
+
+void ContainerNode::reset()
+{
+ QPtrListIterator<ContainerNode> childIt( children );
+ for (; childIt.current(); ++childIt )
+ childIt.current()->reset();
+
+ if ( client )
+ client->setFactory( 0L );
+}
+
+int ContainerNode::calcMergingIndex( const QString &mergingName,
+ MergingIndexList::Iterator &it,
+ BuildState &state,
+ bool ignoreDefaultMergingIndex )
+{
+ MergingIndexList::Iterator mergingIt;
+
+ if ( mergingName.isEmpty() )
+ mergingIt = findIndex( state.clientName );
+ else
+ mergingIt = findIndex( mergingName );
+
+ MergingIndexList::Iterator mergingEnd = mergingIndices.end();
+ it = mergingEnd;
+
+ if ( ( mergingIt == mergingEnd && state.currentDefaultMergingIt == mergingEnd ) ||
+ ignoreDefaultMergingIndex )
+ return index;
+
+ if ( mergingIt != mergingEnd )
+ it = mergingIt;
+ else
+ it = state.currentDefaultMergingIt;
+
+ return (*it).value;
+}
+
+int BuildHelper::calcMergingIndex( const QDomElement &element, MergingIndexList::Iterator &it, QString &group )
+{
+ static const QString &attrGroup = KGlobal::staticQString( "group" );
+
+ bool haveGroup = false;
+ group = element.attribute( attrGroup );
+ if ( !group.isEmpty() ) {
+ group.prepend( attrGroup );
+ haveGroup = true;
+ }
+
+ int idx;
+ if ( haveGroup )
+ idx = parentNode->calcMergingIndex( group, it, m_state, ignoreDefaultMergingIndex );
+ else if ( m_state.currentClientMergingIt == parentNode->mergingIndices.end() )
+ idx = parentNode->index;
+ else
+ idx = (*m_state.currentClientMergingIt).value;
+
+ return idx;
+}
+
+BuildHelper::BuildHelper( BuildState &state, ContainerNode *node )
+ : containerClient( 0 ), ignoreDefaultMergingIndex( false ), m_state( state ),
+ parentNode( node )
+{
+ static const QString &defaultMergingName = KGlobal::staticQString( "<default>" );
+
+ // create a list of supported container and custom tags
+ customTags = m_state.builderCustomTags;
+ containerTags = m_state.builderContainerTags;
+
+ if ( parentNode->builder != m_state.builder )
+ {
+ customTags += parentNode->builderCustomTags;
+ containerTags += parentNode->builderContainerTags;
+ }
+
+ if ( m_state.clientBuilder ) {
+ customTags = m_state.clientBuilderCustomTags + customTags;
+ containerTags = m_state.clientBuilderContainerTags + containerTags;
+ }
+
+ m_state.currentDefaultMergingIt = parentNode->findIndex( defaultMergingName );
+ parentNode->calcMergingIndex( QString::null, m_state.currentClientMergingIt,
+ m_state, /*ignoreDefaultMergingIndex*/ false );
+}
+
+void BuildHelper::build( const QDomElement &element )
+{
+ for (QDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling() )
+ {
+ QDomElement e = n.toElement();
+ if (e.isNull()) continue;
+ processElement( e );
+ }
+}
+
+void BuildHelper::processElement( const QDomElement &e )
+{
+ // some often used QStrings
+ static const QString &tagAction = KGlobal::staticQString( "action" );
+ static const QString &tagMerge = KGlobal::staticQString( "merge" );
+ static const QString &tagState = KGlobal::staticQString( "state" );
+ static const QString &tagDefineGroup = KGlobal::staticQString( "definegroup" );
+ static const QString &tagActionList = KGlobal::staticQString( "actionlist" );
+ static const QString &attrName = KGlobal::staticQString( "name" );
+
+ QString tag( e.tagName().lower() );
+ QString currName( e.attribute( attrName ) );
+
+ bool isActionTag = ( tag == tagAction );
+
+ if ( isActionTag || customTags.findIndex( tag ) != -1 )
+ processActionOrCustomElement( e, isActionTag );
+ else if ( containerTags.findIndex( tag ) != -1 )
+ processContainerElement( e, tag, currName );
+ else if ( tag == tagMerge || tag == tagDefineGroup || tag == tagActionList )
+ processMergeElement( tag, currName, e );
+ else if ( tag == tagState )
+ processStateElement( e );
+}
+
+void BuildHelper::processActionOrCustomElement( const QDomElement &e, bool isActionTag )
+{
+ if ( !parentNode->container )
+ return;
+
+ MergingIndexList::Iterator it( m_state.currentClientMergingIt );
+
+ QString group;
+ int idx = calcMergingIndex( e, it, group );
+
+ containerClient = parentNode->findChildContainerClient( m_state.guiClient, group, it );
+
+ bool guiElementCreated = false;
+ if ( isActionTag )
+ guiElementCreated = processActionElement( e, idx );
+ else
+ guiElementCreated = processCustomElement( e, idx );
+
+ if ( guiElementCreated )
+ // adjust any following merging indices and the current running index for the container
+ parentNode->adjustMergingIndices( 1, it );
+}
+
+bool BuildHelper::processActionElement( const QDomElement &e, int idx )
+{
+ assert( m_state.guiClient );
+
+ // look up the action and plug it in
+ KAction *action = m_state.guiClient->action( e );
+
+ //kdDebug() << "BuildHelper::processActionElement " << e.attribute( "name" ) << " -> " << action << " (in " << m_state.guiClient->actionCollection() << ")" << endl;
+ if ( !action )
+ return false;
+
+ action->plug( parentNode->container, idx );
+
+ // save a reference to the plugged action, in order to properly unplug it afterwards.
+ containerClient->actions.append( action );
+
+ return true;
+}
+
+bool BuildHelper::processCustomElement( const QDomElement &e, int idx )
+{
+ assert( parentNode->builder );
+
+ int id = parentNode->builder->createCustomElement( parentNode->container, idx, e );
+ if ( id == 0 )
+ return false;
+
+ containerClient->customElements.append( id );
+ return true;
+}
+
+void BuildHelper::processStateElement( const QDomElement &element )
+{
+ QString stateName = element.attribute( "name" );
+
+ if ( !stateName || !stateName.length() ) return;
+
+ for (QDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling() )
+ {
+ QDomElement e = n.toElement();
+ if (e.isNull()) continue;
+
+ QString tagName = e.tagName().lower();
+
+ if ( tagName != "enable" && tagName != "disable" )
+ continue;
+
+ bool processingActionsToEnable = (tagName == "enable");
+
+ // process action names
+ for (QDomNode n2 = n.firstChild(); !n2.isNull(); n2 = n2.nextSibling() )
+ {
+ QDomElement actionEl = n2.toElement();
+ if ( actionEl.tagName().lower() != "action" ) continue;
+
+ QString actionName = actionEl.attribute( "name" );
+ if ( !actionName || !actionName.length() ) return;
+
+ if ( processingActionsToEnable )
+ m_state.guiClient->addStateActionEnabled( stateName, actionName );
+ else
+ m_state.guiClient->addStateActionDisabled( stateName, actionName );
+
+ }
+ }
+}
+
+void BuildHelper::processMergeElement( const QString &tag, const QString &name, const QDomElement &e )
+{
+ static const QString &tagDefineGroup = KGlobal::staticQString( "definegroup" );
+ static const QString &tagActionList = KGlobal::staticQString( "actionlist" );
+ static const QString &defaultMergingName = KGlobal::staticQString( "<default>" );
+ static const QString &attrGroup = KGlobal::staticQString( "group" );
+
+ QString mergingName( name );
+ if ( mergingName.isEmpty() )
+ {
+ if ( tag == tagDefineGroup )
+ {
+ kdError(1000) << "cannot define group without name!" << endl;
+ return;
+ }
+ if ( tag == tagActionList )
+ {
+ kdError(1000) << "cannot define actionlist without name!" << endl;
+ return;
+ }
+ mergingName = defaultMergingName;
+ }
+
+ if ( tag == tagDefineGroup )
+ mergingName.prepend( attrGroup ); //avoid possible name clashes by prepending
+ // "group" to group definitions
+ else if ( tag == tagActionList )
+ mergingName.prepend( tagActionList );
+
+ if ( parentNode->findIndex( mergingName ) != parentNode->mergingIndices.end() )
+ return; //do not allow the redefinition of merging indices!
+
+ MergingIndexList::Iterator mIt( parentNode->mergingIndices.end() );
+
+ QString group( e.attribute( attrGroup ) );
+ if ( !group.isEmpty() )
+ group.prepend( attrGroup );
+
+ // calculate the index of the new merging index. Usually this does not need any calculation,
+ // we just want the last available index (i.e. append) . But in case the <Merge> tag appears
+ // "inside" another <Merge> tag from a previously build client, then we have to use the
+ // "parent's" index. That's why we call calcMergingIndex here.
+ MergingIndex newIdx;
+ newIdx.value = parentNode->calcMergingIndex( group, mIt, m_state, ignoreDefaultMergingIndex );
+ newIdx.mergingName = mergingName;
+ newIdx.clientName = m_state.clientName;
+
+ // if that merging index is "inside" another one, then append it right after the "parent" .
+ if ( mIt != parentNode->mergingIndices.end() )
+ parentNode->mergingIndices.insert( ++mIt, newIdx );
+ else
+ parentNode->mergingIndices.append( newIdx );
+
+ if ( mergingName == defaultMergingName )
+
+ ignoreDefaultMergingIndex = true;
+
+ // re-calculate the running default and client merging indices.
+ m_state.currentDefaultMergingIt = parentNode->findIndex( defaultMergingName );
+ parentNode->calcMergingIndex( QString::null, m_state.currentClientMergingIt,
+ m_state, ignoreDefaultMergingIndex );
+}
+
+void BuildHelper::processContainerElement( const QDomElement &e, const QString &tag,
+ const QString &name )
+{
+ static const QString &defaultMergingName = KGlobal::staticQString( "<default>" );
+
+ ContainerNode *containerNode = parentNode->findContainer( name, tag,
+ &containerList,
+ m_state.guiClient );
+
+ if ( !containerNode )
+ {
+ MergingIndexList::Iterator it( m_state.currentClientMergingIt );
+ QString group;
+
+ int idx = calcMergingIndex( e, it, group );
+
+ int id;
+
+ KXMLGUIBuilder *builder;
+
+ QWidget *container = createContainer( parentNode->container, idx, e, id, &builder );
+
+ // no container? (probably some <text> tag or so ;-)
+ if ( !container )
+ return;
+
+ parentNode->adjustMergingIndices( 1, it );
+
+ assert( !parentNode->findContainerNode( container ) );
+
+ containerList.append( container );
+
+ QString mergingName;
+ if ( it != parentNode->mergingIndices.end() )
+ mergingName = (*it).mergingName;
+
+ QStringList cusTags = m_state.builderCustomTags;
+ QStringList conTags = m_state.builderContainerTags;
+ if ( builder != m_state.builder )
+ {
+ cusTags = m_state.clientBuilderCustomTags;
+ conTags = m_state.clientBuilderContainerTags;
+ }
+
+ containerNode = new ContainerNode( container, tag, name, parentNode,
+ m_state.guiClient, builder, id,
+ mergingName, group, cusTags, conTags );
+ }
+
+ BuildHelper( m_state, containerNode ).build( e );
+
+ // and re-calculate running values, for better performance
+ m_state.currentDefaultMergingIt = parentNode->findIndex( defaultMergingName );
+ parentNode->calcMergingIndex( QString::null, m_state.currentClientMergingIt,
+ m_state, ignoreDefaultMergingIndex );
+}
+
+QWidget *BuildHelper::createContainer( QWidget *parent, int index,
+ const QDomElement &element, int &id,
+ KXMLGUIBuilder **builder )
+{
+ QWidget *res = 0L;
+
+ if ( m_state.clientBuilder )
+ {
+ res = m_state.clientBuilder->createContainer( parent, index, element, id );
+
+ if ( res )
+ {
+ *builder = m_state.clientBuilder;
+ return res;
+ }
+ }
+
+ KInstance *oldInstance = m_state.builder->builderInstance();
+ KXMLGUIClient *oldClient = m_state.builder->builderClient();
+
+ m_state.builder->setBuilderClient( m_state.guiClient );
+
+ res = m_state.builder->createContainer( parent, index, element, id );
+
+ m_state.builder->setBuilderInstance( oldInstance );
+ m_state.builder->setBuilderClient( oldClient );
+
+ if ( res )
+ *builder = m_state.builder;
+
+ return res;
+}
+
+void BuildState::reset()
+{
+ clientName = QString::null;
+ actionListName = QString::null;
+ actionList.clear();
+ guiClient = 0;
+ clientBuilder = 0;
+
+ currentDefaultMergingIt = currentClientMergingIt = MergingIndexList::Iterator();
+}
+
+/* vim: et sw=4
+ */
diff --git a/kdeui/kxmlguifactory_p.h b/kdeui/kxmlguifactory_p.h
new file mode 100644
index 000000000..6e7f8f15a
--- /dev/null
+++ b/kdeui/kxmlguifactory_p.h
@@ -0,0 +1,254 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2001 Simon Hausmann <hausmann@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef __kxmlguifactory_p_h__
+#define __kxmlguifactory_p_h__
+
+#include <qstringlist.h>
+#include <qmap.h>
+#include <qdom.h>
+#include <qvaluestack.h>
+
+#include <kaction.h>
+
+class QWidget;
+class KXMLGUIClient;
+class KXMLGUIBuilder;
+class KXMLGUIFactory;
+
+namespace KXMLGUI
+{
+
+struct BuildState;
+
+class KDEUI_EXPORT ActionList : public QPtrList<KAction>
+{
+public:
+ ActionList() {}
+ ActionList( const QPtrList<KAction> &rhs )
+ : QPtrList<KAction>( rhs )
+ {}
+ ActionList &operator=( const QPtrList<KAction> &rhs )
+ { QPtrList<KAction>::operator=( rhs ); return *this; }
+
+ void plug( QWidget *container, int index ) const;
+ void unplug( QWidget *container ) const;
+};
+
+typedef QPtrListIterator<KAction> ActionListIt;
+typedef QMap< QString, ActionList > ActionListMap;
+
+/*
+ * This structure is used to know to which client certain actions and custom elements
+ * (i.e. menu separators) belong.
+ * We do not only use a ContainerClient per GUIClient but also per merging group.
+ *
+ * groupName : Used for grouped merging. Specifies the group name to which these actions/elements
+ * belong to.
+ * actionLists : maps from action list name to action list.
+ * mergingName : The (named) merging point.
+ *
+ * A ContainerClient always belongs to a ContainerNode.
+ */
+struct ContainerClient
+{
+ KXMLGUIClient *client;
+ ActionList actions;
+ QValueList<int> customElements;
+ QString groupName; //is empty if no group client
+ ActionListMap actionLists;
+ QString mergingName;
+};
+typedef QPtrList<ContainerClient> ContainerClientList;
+typedef QPtrListIterator<ContainerClient> ContainerClientListIt;
+
+struct ContainerNode;
+
+struct MergingIndex
+{
+ int value; // the actual index value, used as index for plug() or createContainer() calls
+ QString mergingName; // the name of the merging index (i.e. the name attribute of the
+ // Merge or DefineGroup tag)
+ QString clientName; // the name of the client that defined this index
+};
+typedef QValueList<MergingIndex> MergingIndexList;
+
+/*
+ * Here we store detailed information about a container, its clients (client=a guiclient having actions
+ * plugged into the container), child nodes, naming information (tagname and name attribute) and
+ * merging index information, to plug/insert new actions/items a the correct position.
+ *
+ * The builder variable is needed for using the proper GUIBuilder for destruction ( to use the same for
+ * con- and destruction ). The builderCustomTags and builderContainerTags variables are cached values
+ * of what the corresponding methods of the GUIBuilder which built the container return. The stringlists
+ * is shared all over the place, so there's no need to worry about memory consumption for these
+ * variables :-)
+ *
+ * The mergingIndices list contains the merging indices ;-) , as defined by <Merge>, <DefineGroup>
+ * or by <ActionList> tags. The order of these index structures within the mergingIndices list
+ * is (and has to be) identical with the order in the DOM tree.
+ *
+ * Beside the merging indices we have the "real" index of the container. It points to the next free
+ * position.
+ * (used when no merging index is used for a certain action, custom element or sub-container)
+ */
+struct KDEUI_EXPORT ContainerNode
+{
+ ContainerNode( QWidget *_container, const QString &_tagName, const QString &_name,
+ ContainerNode *_parent = 0L, KXMLGUIClient *_client = 0L,
+ KXMLGUIBuilder *_builder = 0L, int id = -1,
+ const QString &_mergingName = QString::null,
+ const QString &groupName = QString::null,
+ const QStringList &customTags = QStringList(),
+ const QStringList &containerTags = QStringList() );
+
+ ContainerNode *parent;
+ KXMLGUIClient *client;
+ KXMLGUIBuilder *builder;
+ QStringList builderCustomTags;
+ QStringList builderContainerTags;
+ QWidget *container;
+ int containerId;
+
+ QString tagName;
+ QString name;
+
+ QString groupName; //is empty if the container is in no group
+
+ ContainerClientList clients;
+ QPtrList<ContainerNode> children;
+
+ int index;
+ MergingIndexList mergingIndices;
+
+ QString mergingName;
+
+ void clearChildren() { children.clear(); }
+ void removeChild( ContainerNode *child );
+
+ MergingIndexList::Iterator findIndex( const QString &name );
+ ContainerNode *findContainerNode( QWidget *container );
+ ContainerNode *findContainer( const QString &_name, bool tag );
+ ContainerNode *findContainer( const QString &name, const QString &tagName,
+ const QPtrList<QWidget> *excludeList,
+ KXMLGUIClient *currClient );
+
+ ContainerClient *findChildContainerClient( KXMLGUIClient *currentGUIClient,
+ const QString &groupName,
+ const MergingIndexList::Iterator &mergingIdx );
+
+ void plugActionList( BuildState &state );
+ void plugActionList( BuildState &state, const MergingIndexList::Iterator &mergingIdxIt );
+
+ void unplugActionList( BuildState &state );
+ void unplugActionList( BuildState &state, const MergingIndexList::Iterator &mergingIdxIt );
+
+ void adjustMergingIndices( int offset, const MergingIndexList::Iterator &it );
+
+ bool destruct( QDomElement element, BuildState &state );
+ void destructChildren( const QDomElement &element, BuildState &state );
+ static QDomElement findElementForChild( const QDomElement &baseElement,
+ ContainerNode *childNode );
+ void unplugActions( BuildState &state );
+ void unplugClient( ContainerClient *client );
+
+ void reset();
+
+ int calcMergingIndex( const QString &mergingName,
+ MergingIndexList::Iterator &it,
+ BuildState &state,
+ bool ignoreDefaultMergingIndex );
+};
+
+typedef QPtrList<ContainerNode> ContainerNodeList;
+typedef QPtrListIterator<ContainerNode> ContainerNodeListIt;
+
+class KDEUI_EXPORT BuildHelper
+{
+public:
+ BuildHelper( BuildState &state,
+ ContainerNode *node );
+
+ void build( const QDomElement &element );
+
+private:
+ void processElement( const QDomElement &element );
+
+ void processActionOrCustomElement( const QDomElement &e, bool isActionTag );
+ bool processActionElement( const QDomElement &e, int idx );
+ bool processCustomElement( const QDomElement &e, int idx );
+
+ void processStateElement( const QDomElement &element );
+
+ void processMergeElement( const QString &tag, const QString &name, const QDomElement &e );
+
+ void processContainerElement( const QDomElement &e, const QString &tag,
+ const QString &name );
+
+
+ QWidget *createContainer( QWidget *parent, int index, const QDomElement &element,
+ int &id, KXMLGUIBuilder **builder );
+
+ int calcMergingIndex( const QDomElement &element, MergingIndexList::Iterator &it, QString &group );
+
+ QStringList customTags;
+ QStringList containerTags;
+
+ QPtrList<QWidget> containerList;
+
+ ContainerClient *containerClient;
+
+ bool ignoreDefaultMergingIndex;
+
+ BuildState &m_state;
+
+ ContainerNode *parentNode;
+};
+
+struct KDEUI_EXPORT BuildState
+{
+ BuildState() : guiClient( 0 ), builder( 0 ), clientBuilder( 0 ) {}
+
+ void reset();
+
+ QString clientName;
+
+ QString actionListName;
+ ActionList actionList;
+
+ KXMLGUIClient *guiClient;
+
+ MergingIndexList::Iterator currentDefaultMergingIt;
+ MergingIndexList::Iterator currentClientMergingIt;
+
+ KXMLGUIBuilder *builder;
+ QStringList builderCustomTags;
+ QStringList builderContainerTags;
+
+ KXMLGUIBuilder *clientBuilder;
+ QStringList clientBuilderCustomTags;
+ QStringList clientBuilderContainerTags;
+};
+
+typedef QValueStack<BuildState> BuildStateStack;
+
+}
+
+#endif
+/* vim: et sw=4
+ */
diff --git a/kdeui/libkdeui.nmcheck b/kdeui/libkdeui.nmcheck
new file mode 100644
index 000000000..8f9ee9237
--- /dev/null
+++ b/kdeui/libkdeui.nmcheck
@@ -0,0 +1,5 @@
+# KDE namespace check file
+
+# kdeui classes
+K*::*
+QXEmbed::*
diff --git a/kdeui/libkdeui_weak.nmcheck b/kdeui/libkdeui_weak.nmcheck
new file mode 100644
index 000000000..6fa8e9176
--- /dev/null
+++ b/kdeui/libkdeui_weak.nmcheck
@@ -0,0 +1,2 @@
+# KDE namespace check file
+
diff --git a/kdeui/preparetips b/kdeui/preparetips
new file mode 100755
index 000000000..baeaaf3b4
--- /dev/null
+++ b/kdeui/preparetips
@@ -0,0 +1,66 @@
+#! /usr/bin/perl
+# little script to extract the text from the tips file
+# and output it, so xgettext can add the tips to the po file
+#
+# 2000 by Matthias Kiefer <matthias.kiefer@gmx.de>
+
+# IMPORTANT NOTE: Do not change the output without checking if
+# translations still work!
+
+sub printText
+{
+ my $text = $_[0];
+
+ if ( $text cmp "" )
+ {
+
+ # replace \ with \\
+ $text =~ s/\\/\\\\/g;
+
+ # replace " with \"
+ $text =~ s/"/\\"/g;
+
+ print "\"$text\\n\"\n";
+ }
+}
+
+open(FILE,"<","tips") or die "unable to open tips file";
+if ( $^V ge v5.8.0 )
+{
+ binmode(FILE,":utf8");
+ binmode(STDOUT,":utf8");
+}
+
+$inTip=0;
+
+while(<FILE>)
+{
+ chomp;
+
+ # tip starts with <html>
+ if(/^\s*<html>(.*)/io)
+ {
+ $inTip=1;
+ print "//i18n file tips.cpp line $.\n";
+ print "i18n(\n";
+ printText($1);
+ next;
+ }
+
+ if($inTip!=0)
+ {
+ # tip ends with </html>
+ if(/^(.*)\s*<\/html>/io)
+ {
+ printText($1);
+ print ");\n\n";
+ $inTip=0;
+ }
+ else
+ {
+ printText($_);
+ }
+ }
+}
+
+close(FILE);
diff --git a/kdeui/qxembed.cpp b/kdeui/qxembed.cpp
new file mode 100644
index 000000000..19b4a3d19
--- /dev/null
+++ b/kdeui/qxembed.cpp
@@ -0,0 +1,1385 @@
+/****************************************************************************
+ Implementation of QXEmbed class
+
+ Copyright (C) 1999-2002 Trolltech AS
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*****************************************************************************/
+
+
+// L-000: About comments marked with Lxxxx.
+//
+// These comments represent an attempt to provide a more adequate
+// documentation to KDE developpers willing to modify QXEmbed. Keep in
+// mind that these comments were written long after most of the code.
+// Please improve them if you spot something wrong or missing
+// (Leon Bottou, 26-10-2003).
+//
+// Relevant documents:
+// - QXEmbed developper documentation
+// (see comments in qxembed.h)
+// - Xlib Reference Manual
+// (sections about focus, reparenting, window management)
+// - ICCCM Manual
+// (window management)
+// - XEMBED specification
+// (http://www.freedesktop.org/Standards/xembed-spec)
+// - XPLAIN and XEMBED.
+// <http://lists.kde.org/?w=2&r=1&s=qxembed+variants&q=t>
+// - Accumulated community knowledge.
+// <http://lists.kde.org/?w=2&r=1&s=qxembed&q=t>
+// <http://lists.kde.org/?l=kde-devel&w=2&r=1&s=qxembed&q=b>
+// <http://lists.kde.org/?l=kfm-devel&w=2&r=1&s=qxembed&q=b>
+//
+
+
+#include <qapplication.h>
+#include <qptrlist.h>
+#include <qptrdict.h>
+#include <qguardedptr.h>
+#include <qwhatsthis.h>
+#include <qfocusdata.h>
+
+// L0001: QXEmbed works only under X windows.
+#ifdef Q_WS_X11
+
+# include <X11/X.h>
+# include <X11/Xlib.h>
+# include <X11/Xutil.h>
+# include <X11/Xatom.h>
+# define XK_MISCELLANY
+# define XK_LATIN1
+# include <X11/keysymdef.h>
+# include <kdebug.h>
+# include <kxerrorhandler.h>
+
+// L0002: Is file config.h KDE specific?
+# include <config.h>
+# ifdef HAVE_UNISTD_H
+# include <unistd.h>
+# ifdef HAVE_USLEEP
+# define USLEEP(x) usleep(x)
+# else
+# define USLEEP(x) sleep(0)
+# endif
+# else
+# define USLEEP(x) sleep(0)
+# endif
+
+# include "qxembed.h"
+
+// L0003: This keysym is used for focus navigation.
+# ifndef XK_ISO_Left_Tab
+# define XK_ISO_Left_Tab 0xFE20
+# endif
+
+// L0004: Conflicts between X11 and Qt definitions.
+const int XFocusOut = FocusOut;
+const int XFocusIn = FocusIn;
+const int XKeyPress = KeyPress;
+const int XKeyRelease = KeyRelease;
+# undef KeyRelease
+# undef KeyPress
+# undef FocusOut
+# undef FocusIn
+
+// L0005: Variables defined in qapplication_x11.cpp
+extern Atom qt_wm_protocols;
+extern Atom qt_wm_delete_window;
+extern Atom qt_wm_take_focus;
+extern Atom qt_wm_state;
+extern Time qt_x_time;
+
+// L0006: X11 atoms private to QXEmbed
+static Atom xembed = 0;
+static Atom context_help = 0;
+
+// L0007: Xembed message codes (see XEmbed spec)
+#define XEMBED_EMBEDDED_NOTIFY 0
+#define XEMBED_WINDOW_ACTIVATE 1
+#define XEMBED_WINDOW_DEACTIVATE 2
+#define XEMBED_REQUEST_FOCUS 3
+#define XEMBED_FOCUS_IN 4
+#define XEMBED_FOCUS_OUT 5
+#define XEMBED_FOCUS_NEXT 6
+#define XEMBED_FOCUS_PREV 7
+
+// L0008: Xembed message details (see XEmbed spec)
+// -- XEMBED_FOCUS_IN:
+#define XEMBED_FOCUS_CURRENT 0
+#define XEMBED_FOCUS_FIRST 1
+#define XEMBED_FOCUS_LAST 2
+
+
+// L0100: Private data held by the QXEmbed object.
+// This belongs to the embedder side.
+class QXEmbedData
+{
+public:
+ QXEmbedData(){
+ autoDelete = true;
+ xplain = false;
+ xgrab = false;
+ mapAfterRelease = false;
+ lastPos = QPoint(0,0);
+ }
+ ~QXEmbedData(){}
+
+ bool autoDelete; // L0101: See L2600
+ bool xplain; // L0102: See L1100
+ bool xgrab; // L0103: See L2800
+ bool mapAfterRelease;
+ QWidget* focusProxy; // L0104: See XEmbed spec
+ QPoint lastPos; // L0105: See L1390
+};
+
+namespace
+{
+ // L0200: This application wide event filter handles focus
+ // issues in the embedded client.
+ class QXEmbedAppFilter : public QObject
+ {
+ public:
+ QXEmbedAppFilter() { qApp->installEventFilter( this ); }
+ ~QXEmbedAppFilter() { }
+ bool eventFilter( QObject *, QEvent * );
+ };
+}
+
+// L0201: See L0200, L0740
+static QXEmbedAppFilter* filter = 0;
+// L0202: See L0610, L0730
+static QPtrDict<QGuardedPtr<QWidget> > *focusMap = 0;
+// L0203: See L0660, L1400, L1450
+static XKeyEvent last_key_event;
+
+// L0300: This class gives access protected members of class QWidget.
+// Function focusData() is useful to reimplement tab focus management
+// (L0620) Function topData() returns a structure QTLWExtra containing
+// information unique to toplevel windows. This structure contains two
+// members for the sole use of QXEmbed. Flag `embedded' indicates whether
+// the toplevel window is embedded using the XEMBED protocol (L0680).
+// Handle `parentWinId' then records the id of the embedding window.
+
+class QPublicWidget : public QWidget
+{
+public:
+ QTLWExtra* topData() { return QWidget::topData(); }
+ QFocusData *focusData(){ return QWidget::focusData(); }
+ bool focusNextPrev(bool b) { return focusNextPrevChild(b); }
+};
+
+// L0400: This sets a very low level filter for X11 messages.
+// See qapplication_x11.cpp
+typedef int (*QX11EventFilter) (XEvent*);
+extern QX11EventFilter qt_set_x11_event_filter (QX11EventFilter filter);
+static QX11EventFilter oldFilter = 0;
+
+
+// L0500: Helper to send XEmbed messages.
+static void sendXEmbedMessage( WId window, long message, long detail = 0,
+ long data1 = 0, long data2 = 0)
+{
+ if (!window) return;
+ XEvent ev;
+ memset(&ev, 0, sizeof(ev));
+ ev.xclient.type = ClientMessage;
+ ev.xclient.window = window;
+ ev.xclient.message_type = xembed;
+ ev.xclient.format = 32;
+ ev.xclient.data.l[0] = qt_x_time;
+ ev.xclient.data.l[1] = message;
+ ev.xclient.data.l[2] = detail;
+ ev.xclient.data.l[3] = data1;
+ ev.xclient.data.l[4] = data2;
+ XSendEvent(qt_xdisplay(), window, false, NoEventMask, &ev);
+}
+
+// L0501: Helper to send ICCCM Client messages.
+// See X11 ICCCM Specification.
+static void sendClientMessage(Window window, Atom a, long x)
+{
+ if (!window) return;
+ XEvent ev;
+ memset(&ev, 0, sizeof(ev));
+ ev.xclient.type = ClientMessage;
+ ev.xclient.window = window;
+ ev.xclient.message_type = a;
+ ev.xclient.format = 32;
+ ev.xclient.data.l[0] = x;
+ ev.xclient.data.l[1] = qt_x_time;
+ XSendEvent(qt_xdisplay(), window, false, NoEventMask, &ev);
+}
+
+// L0502: Helper to send fake X11 focus messages.
+// See X11 Reference Manual and Window Management stuff.
+static void sendFocusMessage(Window window, int type, int mode, int detail)
+{
+ if (!window) return;
+ XEvent ev;
+ memset(&ev, 0, sizeof(ev));
+ ev.xfocus.type = type;
+ ev.xfocus.window = window;
+ ev.xfocus.mode = mode;
+ ev.xfocus.detail = detail;
+ XSendEvent(qt_xdisplay(), window, false, FocusChangeMask, &ev);
+}
+
+
+// ------------------------------------------------------------
+// L0600: MOST OF WHAT FOLLOWS CONCERNS THE CLIENT SIDE.
+// The following code mostly executes inside a Qt application swallowed
+// by QXEmbed widget. It mostly consists of event filters that fight
+// the normal Qt mechanisms in order to implement the XEMBED protocol.
+// All this would be a lot simpler if it was implemented by Qt itself.
+
+
+
+// L0610: This event filter receives all Qt events. Its main purpose is to
+// capture the Qt focus events in the embedded client in order to
+// implement the XEMBED protocol.
+//
+// Let's start with a few reminders:
+//
+// - X11 only has the concept of the "X11 focus window". This window
+// basically receives all key events. The ICCCM conventions define
+// how the window manager and the applications must cooperate to
+// choose the X11 focus window.
+//
+// - Most toolkits, including Qt, maintain the concepts of 'active
+// widget' and 'Qt focus widget'. A toplevel widget is active when
+// the X11 focus is set to one of its children. By extension a
+// widget is active when its toplevel widget is active. There is one
+// Qt focus widget for each toplevel widget. When the toplevel
+// widget is active, all key events are sent to the Qt focus widget,
+// regardless of which descendant of the toplevel window has the X11
+// focus. Widgets can adjust their appearance according to both
+// their activation and focus states. The Qt FocusIn and FocusOut
+// events indicate when a widget simultaneously is active and has
+// the Qt focus.
+//
+// The XEMBED protocol defines ways to communicate abouth both
+// activation and focus. The embedded client is active as soon as the
+// embedding window is active (L0676, L0677). A widget in the embedded
+// client receives key events when (1) it has the Qt focus in the
+// embedded application, and (2) the QXEmbed widget in the embedding
+// application is active and has the Qt focus. The Qt library in the
+// embedded application is unaware of the focus status of the QXEmbed
+// widget. We must make sure it does the right thing regarding the
+// sending of focus events and the visual appearance of the focussed
+// widgets. When the QXEmbed widget looses the Qt focus, we clear the
+// focus in the embedded client (L1570, L0688). Conversely, when
+// the QXEmbed widget gains the Qt focus, we restore the Qt focus
+// window in the embedded client (L1530, L0680, L0683).
+// Variable focusMap is used to remember which was the Qt focus
+// widget in the embedded application. All this would be a lot
+// simpler if it was implemented inside Qt...
+//
+// The XPLAIN protocol is much less refined in this respect.
+// The activation status of the embedded client simply reflect
+// the focus status of the QXEmbed widget. This is achieved
+// by sending fake X11 focus message to the client (L1521, L1561).
+// A passive button grab (L2800) intercepts mouse activity in the
+// embedded client and sets the Qt focus to the QXEmbed widget
+// when this happens (L2060). This can be achieved without
+// cooperation from the client.
+
+bool QXEmbedAppFilter::eventFilter( QObject *o, QEvent * e)
+{
+ static bool obeyFocus = false;
+ switch ( e->type() ) {
+ case QEvent::MouseButtonPress:
+ // L0612: This will become clear with L0614
+ if ( !((QWidget*)o)->isActiveWindow() )
+ obeyFocus = true;
+ break;
+ case QEvent::FocusIn:
+ // L0613: FocusIn events either occur because the widget already was
+ // active and has just been given the Qt focus (L0614) or
+ // because the widget already had the Qt focus and just became
+ // active (L0615).
+ if ( qApp->focusWidget() == o &&
+ ((QPublicWidget*)qApp->focusWidget()->topLevelWidget())->topData()->embedded ) {
+ QFocusEvent* fe = (QFocusEvent*) e;
+ if ( obeyFocus || fe->reason() == QFocusEvent::Mouse ||
+ fe->reason() == QFocusEvent::Shortcut ) {
+ // L0614: A widget in the embedded client was just given the Qt focus.
+ // Variable `obeyFocus' suggests that this is the result of mouse
+ // activity in the client. The XEMBED_REQUEST_FOCUS message causes
+ // the embedding widget to take the Qt focus (L2085).
+ WId window = ((QPublicWidget*)qApp->focusWidget()->topLevelWidget())->topData()->parentWinId;
+ focusMap->remove( qApp->focusWidget()->topLevelWidget() );
+ sendXEmbedMessage( window, XEMBED_REQUEST_FOCUS );
+ } else if ( fe->reason() == QFocusEvent::ActiveWindow ) {
+ // L0615: Both the embedder and the embedded client became active.
+ // But we do not know whether the QXEmbed widget has the Qt focus.
+ // So we clear the Qt focus for now. If indeed the QXEmbed widget
+ // has the focus, it will receive a FocusIn message (L1530) and
+ // tell us to restore the focus (L0680, L0683).
+ focusMap->remove( qApp->focusWidget()->topLevelWidget() );
+ focusMap->insert( qApp->focusWidget()->topLevelWidget(),
+ new QGuardedPtr<QWidget>(qApp->focusWidget()->topLevelWidget()->focusWidget() ) );
+ // L0616: qApp->focusWidget() might belong to a modal dialog and not be
+ // equal to qApp->focusWidget()->topLevelWidget()->focusWidget() !
+ qApp->focusWidget()->clearFocus();
+ // L0617: ??? [why not {obeyFocus=false; return true;} here?]
+ }
+ obeyFocus = false;
+ }
+ break;
+ case QEvent::KeyPress:
+ if (qApp->focusWidget() == o &&
+ ((QPublicWidget*)qApp->focusWidget()->topLevelWidget())->topData()->embedded ) {
+ // L0620: The following code replaces the Qt code that
+ // handles focus focus changes with the tab key. See the
+ // XEMBED specification for details. The keypress event
+ // arrives here after an interesting itinerary. It is first
+ // saved in the embedding application (L0660). After being
+ // rejected for tab navigation in the embedding application
+ // (L1901), it gets forwarded to the embedded client
+ // (L1400) and arrives here. Depending on the status of
+ // the tab chain in the embedded client, focus navigation
+ // messages are sent back to the embedding application
+ // (L0653, L0654) which then performs tab navigation
+ // (L2081).
+ QKeyEvent *k = (QKeyEvent *)e;
+ QWidget *w = qApp->focusWidget();
+ // L0621: The following tests are copied from QWidget::event().
+ bool res = false;
+ bool tabForward = true;
+ if ( !(k->state() & ControlButton || k->state() & AltButton) ) {
+ if ( k->key() == Key_Backtab || (k->key() == Key_Tab && (k->state() & ShiftButton)) ) {
+ QFocusEvent::setReason( QFocusEvent::Backtab );
+ res = ((QPublicWidget*)w)->focusNextPrev( tabForward = false );
+ QFocusEvent::resetReason();
+ } else if ( k->key() == Key_Tab ) {
+ QFocusEvent::setReason( QFocusEvent::Tab );
+ res = ((QPublicWidget*)w)->focusNextPrev( tabForward = true );
+ QFocusEvent::resetReason();
+ }
+ }
+ if (res) {
+ // L0625: We changed the focus because of tab/backtab key
+ // Now check whether we have been looping around.
+ QFocusData *fd = ((QPublicWidget*)w)->focusData();
+ WId window = ((QPublicWidget*)w->topLevelWidget())->topData()->parentWinId;
+ QWidget *cw = 0;
+ QWidget *fw = fd->home();
+ if (tabForward && window) {
+ while (cw != w && cw != fw && cw != w->topLevelWidget())
+ cw = fd->prev();
+ if (cw != w)
+ sendXEmbedMessage( window, XEMBED_FOCUS_NEXT );
+ } else if (window) {
+ while (cw != w && cw != fw && cw != w->topLevelWidget())
+ cw = fd->next();
+ if (cw != w)
+ sendXEmbedMessage( window, XEMBED_FOCUS_PREV );
+ }
+ // L0628: Qt should no longer process this event.
+ return true;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ // L0640: Application gets to see the events anyway.
+ return false;
+}
+
+// L0650: This filter receives all XEvents in both the client and the embedder.
+// Most of it involves the embedded client (except L0660, L0671).
+static int qxembed_x11_event_filter( XEvent* e)
+{
+ switch ( e->type ) {
+ case XKeyPress:
+ case XKeyRelease: {
+ // L0660: This is for the embedding side (L1450).
+ last_key_event = e->xkey;
+ break;
+ }
+ case ClientMessage:
+ if ( e->xclient.message_type == xembed ) {
+ // L0670: This is where the XEmbed messages are
+ // processed on the client side.
+ Time msgtime = (Time) e->xclient.data.l[0];
+ long message = e->xclient.data.l[1];
+ long detail = e->xclient.data.l[2];
+ // L0671: Keep Qt message time up to date
+ if ( msgtime > qt_x_time )
+ qt_x_time = msgtime;
+ QWidget* w = QWidget::find( e->xclient.window );
+ if ( !w )
+ break;
+ switch ( message) {
+ case XEMBED_EMBEDDED_NOTIFY: {
+ // L0675: We just have been embedded into a XEMBED aware widget.
+ QTLWExtra *extra = ((QPublicWidget*)w->topLevelWidget())->topData();
+ extra->embedded = 1;
+ extra->parentWinId = e->xclient.data.l[3];
+ w->topLevelWidget()->show();
+ break;
+ }
+ case XEMBED_WINDOW_ACTIVATE: {
+ // L0676: Embedding window becomes active. Send a fake XFocusIn
+ // to convince Qt that we are active as well. Qt will send
+ // us a focus notification (L0615) that we will intercept to
+ // ensure that we have no Qt focus widget yet. The Qt focus
+ // widget might later be set in L0680.
+ XEvent ev;
+ memset(&ev, 0, sizeof(ev));
+ ev.xfocus.display = qt_xdisplay();
+ ev.xfocus.type = XFocusIn;
+ ev.xfocus.window = w->topLevelWidget()->winId();
+ ev.xfocus.mode = NotifyNormal;
+ ev.xfocus.detail = NotifyAncestor;
+ qApp->x11ProcessEvent( &ev );
+ }
+ break;
+ case XEMBED_WINDOW_DEACTIVATE: {
+ // L0677: Embedding window becomes inactive. Send a fake XFocusOut
+ // event to convince Qt that we no longer are active. We will
+ // receive extra Qt FocusOut events but we do not care.
+ XEvent ev;
+ memset(&ev, 0, sizeof(ev));
+ ev.xfocus.display = qt_xdisplay();
+ ev.xfocus.type = XFocusOut;
+ ev.xfocus.window = w->topLevelWidget()->winId();
+ ev.xfocus.mode = NotifyNormal;
+ ev.xfocus.detail = NotifyAncestor;
+ qApp->x11ProcessEvent( &ev );
+ }
+ break;
+ case XEMBED_FOCUS_IN:
+ // L0680: Embedding application gives us the focus.
+ {
+ // L0681: Search saved focus widget.
+ QWidget* focusCurrent = 0;
+ QGuardedPtr<QWidget>* fw = focusMap->find( w->topLevelWidget() );
+ if ( fw ) {
+ focusCurrent = *fw;
+ // L0682: Remove it from the map
+ focusMap->remove( w->topLevelWidget() );
+ }
+ switch ( detail ) {
+ case XEMBED_FOCUS_CURRENT:
+ // L0683: Set focus on saved focus widget
+ if ( focusCurrent )
+ focusCurrent->setFocus();
+ else if ( !w->topLevelWidget()->focusWidget() )
+ w->topLevelWidget()->setFocus();
+ break;
+ case XEMBED_FOCUS_FIRST:
+ {
+ // L0684: Search first widget in tab chain
+ QFocusEvent::setReason( QFocusEvent::Tab );
+ w->topLevelWidget()->setFocus();
+ ((QPublicWidget*)w->topLevelWidget())->focusNextPrev(true);
+ QFocusEvent::resetReason();
+ }
+ break;
+ case XEMBED_FOCUS_LAST:
+ {
+ // L0686: Search last widget in tab chain
+ QFocusEvent::setReason( QFocusEvent::Backtab );
+ w->topLevelWidget()->setFocus();
+ ((QPublicWidget*)w->topLevelWidget())->focusNextPrev(false);
+ QFocusEvent::resetReason();
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case XEMBED_FOCUS_OUT:
+ // L0688: Embedding application takes the focus away
+ // We first record what the focus widget was
+ // and clear the Qt focus.
+ if ( w->topLevelWidget()->focusWidget() ) {
+ focusMap->insert( w->topLevelWidget(),
+ new QGuardedPtr<QWidget>(w->topLevelWidget()->focusWidget() ) );
+ w->topLevelWidget()->focusWidget()->clearFocus();
+ }
+ break;
+ default:
+ break;
+ }
+ } else if ( e->xclient.format == 32 && e->xclient.message_type ) {
+ if ( e->xclient.message_type == qt_wm_protocols ) {
+ QWidget* w = QWidget::find( e->xclient.window );
+ if ( !w )
+ break;
+ // L0690: This is for the embedding side!
+ // See L0902 for more information about the focus proxy.
+ // Window manager may send WM_TAKE_FOCUS messages to the
+ // embedding application to indicate that it becomes active.
+ // But this also suggests that the window manager has
+ // changed the X11 focus. We want to make sure it goes
+ // to the focus proxy window eventually.
+ Atom a = e->xclient.data.l[0];
+ if ( a == qt_wm_take_focus ) {
+ // L0695: update Qt message time variable
+ if ( (ulong) e->xclient.data.l[1] > qt_x_time )
+ qt_x_time = e->xclient.data.l[1];
+ // L0696: There is no problem when the window is not active.
+ // Qt will generate a WindowActivate event that will
+ // do the job (L1310). This does not happen if the
+ // window is already active. So we simulate it.
+ if ( w->isActiveWindow() ) {
+ QEvent e( QEvent::WindowActivate );
+ QApplication::sendEvent( w, &e );
+ }
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ // L0698: The next x11 filter
+ if ( oldFilter )
+ return oldFilter( e );
+ // L0699: Otherwise process the event as usual.
+ return false;
+}
+
+
+
+// L0700: Install the xembed filters in both client and embedder sides.
+// This function is called automatically when using
+// embedClientIntoWindow() or creating an instance of QXEmbed You may
+// have to call it manually for a client when using embedder-side
+// embedding, though.
+void QXEmbed::initialize()
+{
+ static bool is_initialized = false;
+ if ( is_initialized )
+ return;
+
+ // L0710: Atom used by the XEMBED protocol.
+ xembed = XInternAtom( qt_xdisplay(), "_XEMBED", false );
+ // L0720: Install low level filter for X11 events (L0650)
+ oldFilter = qt_set_x11_event_filter( qxembed_x11_event_filter );
+ // L0730: See L0610 for an explanation about focusMap.
+ focusMap = new QPtrDict<QGuardedPtr<QWidget> >;
+ focusMap->setAutoDelete( true );
+ // L0740: Create client side application wide event filter (L0610)
+ filter = new QXEmbedAppFilter;
+
+ is_initialized = true;
+}
+
+
+
+
+
+// ------------------------------------------------------------
+// L0800: MOST OF WHAT FOLLOWS CONCERNS THE EMBEDDER SIDE.
+// Things that happen inside a Qt application that contain
+// a QXEmbed widget for embedding other applications.
+// This applies to both the XEMBED and XPLAIN protocols.
+// Deviations are commented below.
+
+
+
+// L0810: Class QXEmbed.
+// A QXEmbed widget serves as an embedder that can manage one single
+// embedded X-window. These so-called client windows can be arbitrary
+// Qt or non Qt applications. There are two different ways of using
+// QXEmbed, from the client side or from the embedder's side.
+
+
+// L0900: Constructs a xembed widget.
+QXEmbed::QXEmbed(QWidget *parent, const char *name, WFlags f)
+ : QWidget(parent, name, f)
+{
+ // L0901: Create private data. See L0100.
+ d = new QXEmbedData;
+ // L0902: Create focus proxy widget. See XEmbed specification.
+ // Each QXEmbed widget has a focus proxy window. Every single
+ // QXEmbed widget tries to force its focus proxy window onto the
+ // whole embedding application. They compete between themselves and
+ // against Qt (L0690, L0914, L1040, L1310, L1510, L1580).
+ // This would be much simpler if implemented within Qt.
+ d->focusProxy = new QWidget( topLevelWidget(), "xembed_focus" );
+ d->focusProxy->setGeometry( -1, -1, 1, 1 );
+ d->focusProxy->show();
+ // make sure it's shown - for XSetInputFocus
+ QApplication::sendPostedEvents( d->focusProxy, 0 );
+ // L0903: Install the client side event filters
+ // because they also provide services for the embedder side
+ // See L0660, L0671, L0685.
+ initialize();
+ window = 0;
+ setFocusPolicy(StrongFocus);
+ setKeyCompression( false );
+
+ // L0910: Trick Qt to create extraData();
+ (void) topData();
+
+ // L0912: We are mostly interested in SubstructureNotify
+ // This is sent when something happens to the children of
+ // the X11 window associated with the QXEmbed widget.
+ XSelectInput(qt_xdisplay(), winId(),
+ KeyPressMask | KeyReleaseMask |
+ ButtonPressMask | ButtonReleaseMask |
+ KeymapStateMask |
+ ButtonMotionMask |
+ PointerMotionMask | // may need this, too
+ EnterWindowMask | LeaveWindowMask |
+ FocusChangeMask |
+ ExposureMask |
+ StructureNotifyMask |
+ SubstructureRedirectMask |
+ SubstructureNotifyMask
+ );
+ // L0913: all application events pass through eventFilter().
+ // This is mostly used to force the X11 focus on the
+ // proxy focus window. See L1300.
+ topLevelWidget()->installEventFilter( this );
+ qApp->installEventFilter( this );
+
+ // L0914: Start moving the X11 focus on the focus proxy window.
+ // See L1581 to know why we do not use isActiveWindow().
+ if ( qApp->activeWindow() == topLevelWidget() )
+ if ( !((QPublicWidget*) topLevelWidget())->topData()->embedded )
+ XSetInputFocus( qt_xdisplay(), d->focusProxy->winId(),
+ RevertToParent, qt_x_time );
+ // L0915: ??? [drag&drop?]
+ setAcceptDrops( true );
+}
+
+// L1000: Destructor must dispose of the embedded client window.
+QXEmbed::~QXEmbed()
+{
+ // L1010: Make sure no pointer grab is left.
+ if ( d && d->xgrab)
+ XUngrabButton( qt_xdisplay(), AnyButton, AnyModifier, winId() );
+ if ( window && ( autoDelete() || !d->xplain ))
+ {
+ // L1021: Hide the window and safely reparent it into the root,
+ // otherwise it would be destroyed by X11 together
+ // with this QXEmbed's window.
+#if 0
+// TODO: The proper XEmbed way would be to unmap the window, and the embedded
+// app would detect the embedding has ended, and do whatever it finds appropriate.
+// However, QXEmbed currently doesn't provide support for this detection,
+// so for the time being, it's better to leave the window mapped as toplevel window.
+// This will be ever more complicated with the systray windows, as the simple API
+// for them (KWin::setSystemTrayWindowFor()) doesn't make it possible to detect
+// themselves they have been released from systray, but KWin requires them
+// to be visible to allow next Kicker instance to swallow them.
+// See also below the L1022 comment.
+// XUnmapWindow( qt_xdisplay(), window );
+#else
+ if( autoDelete())
+ XUnmapWindow( qt_xdisplay(), window );
+#endif
+ XReparentWindow(qt_xdisplay(), window, qt_xrootwin(), 0, 0);
+ if( !d->xplain )
+ XRemoveFromSaveSet( qt_xdisplay(), window );
+ if( d->mapAfterRelease )
+ XMapWindow( qt_xdisplay(), window );
+ XSync(qt_xdisplay(), false);
+ // L1022: Send the WM_DELETE_WINDOW message
+ if( autoDelete() /*&& d->xplain*/ )
+ // This sendDelete should only apply to XPLAIN.
+ // XEMBED apps are supposed to detect when the embedding ends.
+ // ??? [We do not do this detection yet!
+ // So we sendDelete() instead.]
+ sendDelete();
+ }
+ window = 0;
+ // L01040: Our focus proxy window will be destroyed as well.
+ // Make sure that the X11 focus is not lost in the process.
+ Window focus;
+ int revert;
+ XGetInputFocus( qt_xdisplay(), &focus, &revert );
+ if( focus == d->focusProxy->winId())
+ XSetInputFocus( qt_xdisplay(), topLevelWidget()->winId(), RevertToParent, qt_x_time );
+ // L01045: Delete our private data.
+ delete d;
+}
+
+
+// L1050: Sends a WM_DELETE_WINDOW message to the embedded window. This is
+// what typically happens when you click on the close button of a
+// window manager decoration.
+void QXEmbed::sendDelete( void )
+{
+ if (window)
+ {
+ sendClientMessage(window, qt_wm_protocols, qt_wm_delete_window);
+ XFlush( qt_xdisplay() );
+ }
+}
+
+// L1100: Sets the protocol used for embedding windows.
+// This function must be called before embedding a window.
+// Protocol XEMBED provides maximal functionality (focus, tabs, etc)
+// but requires explicit cooperation from the embedded window.
+// Protocol XPLAIN provides maximal compatibility with
+// embedded applications that do not support the XEMBED protocol.
+// The default is XEMBED.
+void QXEmbed::setProtocol( Protocol proto )
+{
+ if (!window) {
+ d->xplain = false;
+ if (proto == XPLAIN)
+ d->xplain = true;
+ }
+}
+
+// L1150: Returns the protocol used for embedding the current window.
+QXEmbed::Protocol QXEmbed::protocol()
+{
+ if (d->xplain)
+ return XPLAIN;
+ return XEMBED;
+}
+
+
+// L1200: QXEmbed widget size changes: resize embedded window.
+void QXEmbed::resizeEvent(QResizeEvent*)
+{
+ if (window)
+ XResizeWindow(qt_xdisplay(), window, width(), height());
+}
+
+// L1250: QXEmbed widget is shown: make sure embedded window is visible.
+void QXEmbed::showEvent(QShowEvent*)
+{
+ if (window)
+ XMapRaised(qt_xdisplay(), window);
+}
+
+
+// L1300: This event filter sees all application events (L0913).
+bool QXEmbed::eventFilter( QObject *o, QEvent * e)
+{
+
+ switch ( e->type() ) {
+ case QEvent::WindowActivate:
+ if ( o == topLevelWidget() ) {
+ // L1310: Qt thinks the application window has just been activated.
+ // Make sure the X11 focus is on the focus proxy window. See L0686.
+ if ( !((QPublicWidget*) topLevelWidget())->topData()->embedded )
+ if (! hasFocus() )
+ XSetInputFocus( qt_xdisplay(), d->focusProxy->winId(),
+ RevertToParent, qt_x_time );
+ if (d->xplain)
+ // L1311: Activation has changed. Grab state might change. See L2800.
+ checkGrab();
+ else
+ // L1312: Let the client know that we just became active
+ sendXEmbedMessage( window, XEMBED_WINDOW_ACTIVATE );
+ }
+ break;
+ case QEvent::WindowDeactivate:
+ if ( o == topLevelWidget() ) {
+ if (d->xplain)
+ // L1321: Activation has changed. Grab state might change. See L2800.
+ checkGrab();
+ else
+ // L1322: Let the client know that we are no longer active
+ sendXEmbedMessage( window, XEMBED_WINDOW_DEACTIVATE );
+ }
+ break;
+ case QEvent::Move:
+ {
+ QWidget* pos = this;
+ while( pos != o && pos != topLevelWidget())
+ pos = pos->parentWidget();
+ if( pos == o ) {
+ // L1390: Send fake configure notify events whenever the
+ // global position of the client changes. See L2900.
+ QPoint globalPos = mapToGlobal(QPoint(0,0));
+ if (globalPos != d->lastPos) {
+ d->lastPos = globalPos;
+ sendSyntheticConfigureNotifyEvent();
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return false;
+}
+
+// L1350: ??? [why this?]
+bool QXEmbed::event( QEvent * e)
+{
+ return QWidget::event( e );
+}
+
+// L1400: Forward keypress event to the client
+// Receiving a Qt key event indicates that
+// the QXEmbed object has the Qt focus.
+// The X11 event that caused the Qt key event
+// must be forwarded to the client.
+// See L0660.
+void QXEmbed::keyPressEvent( QKeyEvent *)
+{
+ if (!window)
+ return;
+ last_key_event.window = window;
+ XSendEvent(qt_xdisplay(), window, false, KeyPressMask, (XEvent*)&last_key_event);
+
+}
+
+// L1450: Forward keyrelease event to the client.
+// See comment L1400.
+void QXEmbed::keyReleaseEvent( QKeyEvent *)
+{
+ if (!window)
+ return;
+ last_key_event.window = window;
+ XSendEvent(qt_xdisplay(), window, false, KeyReleaseMask, (XEvent*)&last_key_event);
+}
+
+// L1500: Handle Qt focus in event.
+void QXEmbed::focusInEvent( QFocusEvent * e ){
+ if (!window)
+ return;
+ // L1510: This is a good time to set the X11 focus on the focus proxy window.
+ // Except if the the embedding application itself is embedded into another.
+ if ( !((QPublicWidget*) topLevelWidget())->topData()->embedded )
+ if ( qApp->activeWindow() == topLevelWidget() )
+ // L1511: Alter X focus only when window is active.
+ // This is dual safety here because FocusIn implies this.
+ // But see L1581 for an example where this really matters.
+ XSetInputFocus( qt_xdisplay(), d->focusProxy->winId(),
+ RevertToParent, qt_x_time );
+ if (d->xplain) {
+ // L1520: Qt focus has changed. Grab state might change. See L2800.
+ checkGrab();
+ // L1521: Window managers activate applications by setting the X11 focus.
+ // We cannot do this (see L1510) but we can send a fake focus event
+ // and forward the X11 key events ourselves (see L1400, L1450).
+ sendFocusMessage(window, XFocusIn, NotifyNormal, NotifyPointer );
+ } else {
+ // L1530: No need for fake events with XEMBED.
+ // Just inform the client. It knows what to do.
+ int detail = XEMBED_FOCUS_CURRENT;
+ // L1531: When the focus change is caused by the tab key,
+ // the client must select the first (or last) widget of
+ // its own tab chain.
+ if ( e->reason() == QFocusEvent::Tab )
+ detail = XEMBED_FOCUS_FIRST;
+ else if ( e->reason() == QFocusEvent::Backtab )
+ detail = XEMBED_FOCUS_LAST;
+ sendXEmbedMessage( window, XEMBED_FOCUS_IN, detail);
+ }
+}
+
+// L1550: Handle Qt focus out event.
+void QXEmbed::focusOutEvent( QFocusEvent * ){
+ if (!window)
+ return;
+ if (d->xplain) {
+ // L1560: Qt focus has changed. Grab state might change. See L2800.
+ checkGrab();
+ // L1561: Send fake focus out message. See L1521.
+ sendFocusMessage(window, XFocusOut, NotifyNormal, NotifyPointer );
+ } else {
+ // L1570: Send XEMBED focus out message. See L1531.
+ sendXEmbedMessage( window, XEMBED_FOCUS_OUT );
+ }
+ // L1580: The QXEmbed object might loose the focus because its
+ // toplevel window looses the X11 focus and is no longer active,
+ // or simply because the Qt focus has been moved to another widget.
+ // In the latter case only, we want to make sure that the X11 focus
+ // is properly set to the X11 focus widget. We do this because
+ // the client application might have moved the X11 focus after
+ // receiving the fake focus messages.
+ if ( !((QPublicWidget*) topLevelWidget())->topData()->embedded )
+ if ( qApp->activeWindow() == topLevelWidget() )
+ // L1581: Alter X focus only when window is active.
+ // The test above is not the same as isActiveWindow().
+ // Function isActiveWindow() also returns true when a modal
+ // dialog child of this window is active.
+ XSetInputFocus( qt_xdisplay(), d->focusProxy->winId(),
+ RevertToParent, qt_x_time );
+}
+
+
+// L1600: Helper for QXEmbed::embed()
+// Check whether a window is in withdrawn state.
+static bool wstate_withdrawn( WId winid )
+{
+ Atom type;
+ int format;
+ unsigned long length, after;
+ unsigned char *data;
+ int r = XGetWindowProperty( qt_xdisplay(), winid, qt_wm_state, 0, 2,
+ false, AnyPropertyType, &type, &format,
+ &length, &after, &data );
+ bool withdrawn = true;
+ // L1610: Non managed windows have no WM_STATE property.
+ // Returning true ensures that the loop L1711 stops.
+ if ( r == Success && data && format == 32 ) {
+ Q_UINT32 *wstate = (Q_UINT32*)data;
+ withdrawn = (*wstate == WithdrawnState );
+ XFree( (char *)data );
+ }
+ return withdrawn;
+}
+
+// L1650: Helper for QXEmbed::embed()
+// Get the X11 id of the parent window.
+static int get_parent(WId winid, Window *out_parent)
+{
+ Window root, *children=0;
+ unsigned int nchildren;
+ int st = XQueryTree(qt_xdisplay(), winid, &root, out_parent, &children, &nchildren);
+ if (st && children)
+ XFree(children);
+ return st;
+}
+
+// L1700: Embeds the window w into this QXEmbed widget.
+// See doc in qxembed.h.
+void QXEmbed::embed(WId w)
+{
+ kdDebug() << "*** Embed " << w << " into " << winId() << ". window=" << window << endl;
+ if (!w)
+ return;
+ // L1701: The has_window variable prevents embedding a same window twice.
+ // ??? [what happens if one embed two windows into the same QXEmbed?]
+ bool has_window = (w == window);
+ window = w;
+ if ( !has_window ) {
+ KXErrorHandler errhandler; // make X BadWindow errors silent
+ // L1710: Try hard to withdraw the window.
+ // This makes sure that the window manager will
+ // no longer try to manage this window.
+ if ( !wstate_withdrawn(window) ) {
+ XWithdrawWindow(qt_xdisplay(), window, qt_xscreen());
+ QApplication::flushX();
+ // L1711: See L1610
+ for (int i=0; i < 10000; ++i) {
+ if (wstate_withdrawn(window)) {
+ Window parent = 0;
+ get_parent(w, &parent);
+ if (parent == qt_xrootwin()) break;
+ }
+ USLEEP(1000);
+ }
+ }
+ // L1710: It would be sufficient in principle to reparent
+ // window w into winId(). Everything else happens in L2020.
+ // The following code might be useful when the X11 server takes
+ // time to create the embedded application main window.
+ Window parent = 0;
+ get_parent(w, &parent);
+ kdDebug() << QString("> before reparent: parent=0x%1").arg(parent,0,16) << endl;
+ for (int i = 0; i < 50; i++) {
+ // this is done once more when finishing embedding, but it's done also here
+ // just in case we crash before reaching that place
+ if( !d->xplain )
+ XAddToSaveSet( qt_xdisplay(), w );
+ XReparentWindow(qt_xdisplay(), w, winId(), 0, 0);
+ if (get_parent(w, &parent) && parent == winId()) {
+ kdDebug() << QString("> Loop %1: ").arg(i)
+ << QString("> reparent of 0x%1").arg(w,0,16)
+ << QString(" into 0x%1").arg(winId(),0,16)
+ << QString(" successful") << endl;
+ break;
+ }
+ kdDebug() << QString("> Loop %1: ").arg(i)
+ << QString("> reparent of 0x%1").arg(w,0,16)
+ << QString(" into 0x%1").arg(winId(),0,16)
+ << QString(" failed") << endl;
+ USLEEP(1000);
+ }
+ if( parent != winId()) // failed
+ window = 0;
+ }
+}
+
+// When a window is reparented into QXEmbed (or created inside of it), this function
+// sets up the actual embedding.
+void QXEmbed::handleEmbed()
+{
+ // only XEMBED apps can survive crash,
+ // see http://lists.kde.org/?l=kfm-devel&m=106752026501968&w=2
+ if( !d->xplain )
+ XAddToSaveSet( qt_xdisplay(), window );
+ XResizeWindow(qt_xdisplay(), window, width(), height());
+ XMapRaised(qt_xdisplay(), window);
+ // L2024: see L2900.
+ sendSyntheticConfigureNotifyEvent();
+ // L2025: ??? [any idea about drag&drop?]
+ extraData()->xDndProxy = window;
+ if ( parent() ) {
+ // L2030: embedded window might have new size requirements.
+ // see L2500, L2520, L2550.
+ QEvent * layoutHint = new QEvent( QEvent::LayoutHint );
+ QApplication::postEvent( parent(), layoutHint );
+ }
+ windowChanged( window );
+ if (d->xplain) {
+ // L2040: Activation has changed. Grab state might change. See L2800.
+ checkGrab();
+ if ( hasFocus() )
+ // L2041: Send fake focus message to inform the client. See L1521.
+ sendFocusMessage(window, XFocusIn, NotifyNormal, NotifyPointer );
+ } else {
+ // L2050: Send XEMBED messages (see L0670, L1312, L1322, L1530)
+ sendXEmbedMessage( window, XEMBED_EMBEDDED_NOTIFY, 0, (long) winId() );
+ if (isActiveWindow())
+ sendXEmbedMessage( window, XEMBED_WINDOW_ACTIVATE);
+ else
+ sendXEmbedMessage( window, XEMBED_WINDOW_DEACTIVATE);
+ if ( hasFocus() )
+ sendXEmbedMessage( window, XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT );
+ }
+}
+
+// L1800: Returns the window identifier of the embedded window
+WId QXEmbed::embeddedWinId() const
+{
+ return window;
+}
+
+
+// L1900: Control Qt tab focus management.
+// See Qt documentation.
+bool QXEmbed::focusNextPrevChild( bool next )
+{
+ if ( window )
+ // L1901: Return false when there is an embedded window
+ // When the user presses TAB, Qt will not change
+ // the focus and pass the TAB key events to the QXEmbed widget.
+ // These key events will be forwarded to the client (L1400, L1450)
+ // who eventually will manage the tab focus (L0620) and possible
+ // instruct us to call QWidget::focusNextPrevChild (L2081).
+ return false;
+ else
+ // L1920: Default behavior otherwise.
+ return QWidget::focusNextPrevChild( next );
+}
+
+
+// L2000: Filter for X11 events sent to the QXEmbed window.
+bool QXEmbed::x11Event( XEvent* e)
+{
+ switch ( e->type ) {
+ case DestroyNotify:
+ if ( e->xdestroywindow.window == window ) {
+ // L2005: Client window is being destroyed.
+ window = 0;
+ windowChanged( window );
+ emit embeddedWindowDestroyed();
+ }
+ break;
+ case CreateNotify:
+ // A window was created inside of QXEmbed, handle it as embedded
+ if( window == 0 ) { // only one window
+ window = e->xcreatewindow.window;
+ handleEmbed();
+ }
+ break;
+ case ReparentNotify:
+ if ( e->xreparent.window == d->focusProxy->winId() )
+ break; // ignore proxy
+ if ( window && e->xreparent.window == window &&
+ e->xreparent.parent != winId() ) {
+ // L2010: We lost the window
+ window = 0;
+ windowChanged( window );
+ emit embeddedWindowDestroyed();
+ // L2011: Remove window from save set
+ // ??? [not sure it is good to touch this window since
+ // someone else has taken control of it already.]
+ if( !d->xplain )
+ XRemoveFromSaveSet( qt_xdisplay(), window );
+ } else if ( e->xreparent.parent == winId()){
+ if( window == 0 ) // something started embedding from the outside
+ window = e->xreparent.window;
+ // L2020: We got a window. Complete the embedding process.
+ if( e->xreparent.window == window )
+ handleEmbed();
+ }
+ break;
+ case ButtonPress:
+ if (d->xplain && d->xgrab) {
+ // L2060: The passive grab has intercepted a mouse click
+ // in the embedded client window. Take the focus.
+ QFocusEvent::setReason( QFocusEvent::Mouse );
+ setFocus();
+ QFocusEvent::resetReason();
+ // L2064: Resume X11 event processing.
+ XAllowEvents(qt_xdisplay(), ReplayPointer, CurrentTime);
+ // L2065: Qt should not know about this.
+ return true;
+ }
+ break;
+ case ButtonRelease:
+ if (d->xplain && d->xgrab) {
+ // L2064: Resume X11 event processing after passive grab (see L2060)
+ XAllowEvents(qt_xdisplay(), SyncPointer, CurrentTime);
+ return true;
+ }
+ break;
+ case MapRequest:
+ // L2070: Behave like a window manager.
+ if ( window && e->xmaprequest.window == window )
+ XMapRaised(qt_xdisplay(), window );
+ break;
+ case ClientMessage:
+ // L2080: This is where the QXEmbed object receives XEMBED
+ // messaged from the client application.
+ if ( e->xclient.format == 32 && e->xclient.message_type == xembed ) {
+ long message = e->xclient.data.l[1];
+ switch ( message ) {
+ // L2081: Tab focus management. It is very important to call the
+ // focusNextPrevChild() defined by QWidget (not QXEmbed).
+ // See L1901.
+ case XEMBED_FOCUS_NEXT:
+ QWidget::focusNextPrevChild( true );
+ break;
+ case XEMBED_FOCUS_PREV:
+ QWidget::focusNextPrevChild( false );
+ break;
+ // L2085: The client asks for the focus.
+ case XEMBED_REQUEST_FOCUS:
+ if( ((QPublicWidget*)topLevelWidget())->topData()->embedded ) {
+ WId window = ((QPublicWidget*)topLevelWidget())->topData()->parentWinId;
+ sendXEmbedMessage( window, XEMBED_REQUEST_FOCUS );
+ } else {
+ QFocusEvent::setReason( QFocusEvent::Mouse );
+ setFocus();
+ QFocusEvent::resetReason();
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+
+ case ConfigureRequest:
+ // L2090: Client wants to change its geometry.
+ // Just inform it that nothing has changed.
+ if (e->xconfigurerequest.window == window)
+ {
+ sendSyntheticConfigureNotifyEvent();
+ }
+ break;
+ case MotionNotify:
+ // fall through, workaround for Qt 3.0 < 3.0.3
+ case EnterNotify:
+ // L2095: See L2200.
+ if ( QWhatsThis::inWhatsThisMode() )
+ enterWhatsThisMode();
+ break;
+ default:
+ break;
+ }
+ return false;
+}
+
+
+// L2200: Try to handle Qt's "what's this" mode. Broken.
+// "temporary, fix in Qt (Matthias, Mon Jul 17 15:20:55 CEST 2000"
+void QXEmbed::enterWhatsThisMode()
+{
+ // L2210: When the what-s-this pointer enters the embedded window (L2095)
+ // cancel what-s-this mode, and use a non stantard _NET_WM_ message
+ // to instruct the embedded client to enter the "what's this" mode.
+ // This works only one way...
+ QWhatsThis::leaveWhatsThisMode();
+ if ( !context_help )
+ context_help = XInternAtom( x11Display(), "_NET_WM_CONTEXT_HELP", false );
+ sendClientMessage(window , qt_wm_protocols, context_help );
+}
+
+
+// L2300: indicates that the embedded window has been changed.
+void QXEmbed::windowChanged( WId )
+{
+}
+
+
+// L2400: Utility function for clients that embed themselves.
+// This is client side code.
+bool QXEmbed::processClientCmdline( QWidget* client, int& argc, char ** argv )
+{
+ int myargc = argc;
+ WId window = 0;
+ int i, j;
+
+ j = 1;
+ for ( i=1; i<myargc; i++ ) {
+ if ( argv[i] && *argv[i] != '-' ) {
+ argv[j++] = argv[i];
+ continue;
+ }
+ QCString arg = argv[i];
+ if ( !strcmp(arg,"-embed") && i < myargc-1 ) {
+ QCString s = argv[++i];
+ window = s.toInt();
+ } else
+ argv[j++] = argv[i];
+ }
+ argc = j;
+
+ if ( window ) {
+ embedClientIntoWindow( client, window );
+ return true;
+ }
+
+ return false;
+}
+
+
+// L2450: Utility function for clients that embed themselves.
+// This is client side code.
+void QXEmbed::embedClientIntoWindow(QWidget* client, WId window)
+{
+ initialize();
+ XReparentWindow(qt_xdisplay(), client->winId(), window, 0, 0);
+ // L2451: These two lines are redundant. See L0680.
+ ((QXEmbed*)client)->topData()->embedded = true;
+ ((QXEmbed*)client)->topData()->parentWinId = window;
+ // L2452: This seems redundant because L2020 maps the window.
+ // But calling show() might also set Qt internal flags.
+ client->show();
+}
+
+
+
+// L2500: Specifies that this widget can use additional space,
+// and that it can survive on less than sizeHint().
+QSizePolicy QXEmbed::sizePolicy() const
+{
+ return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
+}
+
+
+// L2520: Returns a size sufficient for the embedded window
+QSize QXEmbed::sizeHint() const
+{
+ return minimumSizeHint();
+}
+
+// L2550: Returns the minimum size specified by the embedded window.
+QSize QXEmbed::minimumSizeHint() const
+{
+ int minw = 0;
+ int minh = 0;
+ if ( window ) {
+ XSizeHints size;
+ long msize;
+ if (XGetWMNormalHints(qt_xdisplay(), window, &size, &msize)
+ && ( size.flags & PMinSize) ) {
+ minw = size.min_width;
+ minh = size.min_height;
+ }
+ }
+
+ return QSize( minw, minh );
+}
+
+// L2600: Tells what shoud be done with the embedded window when
+// the embedding window is destroyed.
+void QXEmbed::setAutoDelete( bool b)
+{
+ d->autoDelete = b;
+}
+
+// L2650: See L2600.
+bool QXEmbed::autoDelete() const
+{
+ return d->autoDelete;
+}
+
+// L2700: See L2200.
+bool QXEmbed::customWhatsThis() const
+{
+ return true;
+}
+
+// L2800: When using the XPLAIN protocol, this function maintains
+// a passive button grab when (1) the application is active
+// and (2) the Qt focus is not on the QXEmbed. This passive
+// grab intercepts button clicks in the client window and
+// give us chance to request the Qt focus (L2060).
+void QXEmbed::checkGrab()
+{
+ if (d->xplain && isActiveWindow() && !hasFocus()) {
+ if (! d->xgrab)
+ XGrabButton(qt_xdisplay(), AnyButton, AnyModifier, winId(),
+ false, ButtonPressMask, GrabModeSync, GrabModeAsync,
+ None, None );
+ d->xgrab = true;
+ } else {
+ if (d->xgrab)
+ XUngrabButton( qt_xdisplay(), AnyButton, AnyModifier, winId() );
+ d->xgrab = false;
+ }
+}
+
+// L2900: This sends fake configure notify events to inform
+// the client about its window geometry. See L1390, L2024 and L2090.
+void QXEmbed::sendSyntheticConfigureNotifyEvent()
+{
+ // L2910: It seems that the x and y coordinates are global.
+ // But this is what ICCCM section 4.1.5 wants.
+ // See http://lists.kde.org/?l=kfm-devel&m=107090222032378
+ QPoint globalPos = mapToGlobal(QPoint(0,0));
+ if (window) {
+#if 0
+ XConfigureEvent c;
+ memset(&c, 0, sizeof(c));
+ c.type = ConfigureNotify;
+ c.display = qt_xdisplay();
+ c.send_event = True;
+ c.event = window;
+ c.window = window;
+ c.x = globalPos.x();
+ c.y = globalPos.y();
+ c.width = width();
+ c.height = height();
+ c.border_width = 0;
+ c.above = None;
+ c.override_redirect = 0;
+ XSendEvent( qt_xdisplay(), c.event, true, StructureNotifyMask, (XEvent*)&c );
+#endif
+ // Yes, this doesn't make sense at all. See the commit message.
+ XSetWindowBorderWidth( qt_xdisplay(), window, 1 );
+ XSetWindowBorderWidth( qt_xdisplay(), window, 0 );
+ }
+}
+
+// L3000: One should not call QWidget::reparent after embedding a window.
+void QXEmbed::reparent( QWidget * parent, WFlags f, const QPoint & p, bool showIt )
+{
+ // QWidget::reparent() destroys the old X Window for the widget, and
+ // creates a new one, thus QXEmbed after reparenting is no longer the
+ // parent of the embedded window. I think reparenting of QXEmbed can be
+ // done only by a mistake, so just complain.
+ Q_ASSERT( !window );
+ QWidget::reparent( parent, f, p, showIt );
+}
+
+// for KDE
+#include "qxembed.moc"
+#endif // Q_WS_X11
diff --git a/kdeui/qxembed.h b/kdeui/qxembed.h
new file mode 100644
index 000000000..40772d801
--- /dev/null
+++ b/kdeui/qxembed.h
@@ -0,0 +1,234 @@
+/****************************************************************************
+ Definition of QXEmbed class
+
+ Copyright (C) 1999-2000 Troll Tech AS
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*****************************************************************************/
+
+#ifndef QXEMBED_H
+#define QXEMBED_H
+
+#include <qwidget.h>
+#include <kdelibs_export.h>
+
+#ifdef Q_WS_X11
+
+class QXEmbedData;
+
+/**
+ * A QXEmbed widget serves as an embedder that can manage one single embedded
+ * X-window. These so-called client windows can be arbitrary Qt or non Qt
+ * applications.
+ *
+ * There are two different ways of using QXEmbed,
+ * from the client side or from the embedder's side.
+ *
+ * Embedding from the client's side requires that the client knows the
+ * window identifier of the respective embedder widget. Use either
+ * embedClientIntoWindow() or the high-level wrapper processClientCmdline().
+ * This is only possible when the client is a Qt application.
+ *
+ * When using it from the embedder's side, you must know the window
+ * identifier of the window that should be embedded. Simply call embed()
+ * with this identifier as parameter. If the client is a Qt application,
+ * make sure it has called QXEmbed::initialize(). Otherwise you should
+ * probably call setProtocol(XPLAIN) before embed().
+ *
+ * Reimplement the change handler windowChanged() to catch embedding or
+ * the destruction of embedded windows. In the latter case, the
+ * embedder also emits a signal embeddedWindowDestroyed() for
+ * convenience.
+ *
+ * @short The QXEmbed widget is a graphical socket that can embed an external X-Window.
+*/
+class KDEUI_EXPORT QXEmbed : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ /**
+ *
+ * Constructs a xembed widget.
+ *
+ * The parent, name and f arguments are passed to the QFrame
+ * constructor.
+ */
+ QXEmbed( QWidget *parent=0, const char *name=0, WFlags f = 0 );
+
+ /**
+ * Destructor. Cleans up the focus if necessary.
+ */
+ ~QXEmbed();
+
+ /**
+ * Embedded applications should call this function to make sure
+ * they support the XEMBED protocol. It is called automatically
+ * when you use embedClientIntoWindow() or
+ * processClientCmdline(). Clients might have to call it
+ * manually when you use embed().
+ */
+ static void initialize();
+
+ enum Protocol { XEMBED, XPLAIN };
+
+ /**
+ * Sets the protocol used for embedding windows.
+ * This function must be called before embedding a window.
+ * Protocol XEMBED provides maximal functionality (focus, tabs, etc)
+ * but requires explicit cooperation from the embedded window.
+ * Protocol XPLAIN provides maximal compatibility with
+ * embedded applications that do not support the XEMBED protocol.
+ * The default is XEMBED.
+ *
+ * Non KDE applications should be embedded with protocol XPLAIN.
+ * This does not happen automatically yet.
+ * You must call setProtocol() explicitly.
+ */
+
+ void setProtocol( Protocol proto );
+
+ /**
+ * Returns the protocol used for embedding the current window.
+ *
+ * @return the protocol used by QXEmbed.
+ */
+
+ Protocol protocol();
+
+ /**
+ * Embeds the window with the identifier w into this xembed widget.
+ *
+ * This function is useful if the embedder knows about the client window
+ * that should be embedded. Often it is vice versa: the client knows
+ * about its target embedder. In that case, it is not necessary to call
+ * embed(). Instead, the client will call the static function
+ * embedClientIntoWindow().
+ *
+ * @param w the identifier of the window to embed
+ * @see embeddedWinId()
+ */
+ void embed( WId w );
+
+ /**
+ * Returns the window identifier of the embedded window, or 0 if no
+ * window is embedded yet.
+ *
+ * @return the id of the embedded window (0 if no window is embedded)
+ */
+ WId embeddedWinId() const;
+
+ /**
+ * A function for clients that embed themselves. The widget
+ * client will be embedded in the window window. The application has
+ * to ensure that window is the handle of the window identifier of
+ * an QXEmbed widget.
+ *
+ * @short #processClientCmdline()
+ */
+ static void embedClientIntoWindow( QWidget* client, WId window );
+
+ /**
+ * A utility function for clients that embed theirselves. The widget
+ * client will be embedded in the window that is passed as
+ * -embed command line argument.
+ *
+ * The function returns true on success or false if no such command line
+ * parameter is specified.
+ *
+ * @see embedClientIntoWindow()
+ */
+ static bool processClientCmdline( QWidget* client, int& argc, char ** argv );
+
+ /**
+ * Sends a WM_DELETE_WINDOW message to the embedded window. This is what
+ * typically happens when you click on the close button of a window
+ * manager decoration. This should cause the embedded application to
+ * cleanly close the window. Signal embeddedWindowDestroyed() can be used
+ * to monitor the status of the embedded window.
+ */
+ void sendDelete( void );
+
+ /**
+ * Selects what shoud be done with the embedded window when the embedding
+ * window is destroyed. When the argument is true, the embedded window is
+ * kept alive, is hidden, and receives a WM_DELETE_WINDOW message using
+ * sendDelete(). This is the default. Otherwise, the destruction of the
+ * QXEmbed object simply destroys the embedded window.
+ *
+ * @see sendDelete()
+ */
+ void setAutoDelete( bool );
+
+ /**
+ * Returns the value of flag indicating what shoud be done with the
+ * embedded window when the embedding window is destroyed.
+ *
+ * @see setAutoDelete()
+ */
+ bool autoDelete() const;
+
+ /* Reimp */
+ QSize sizeHint() const;
+ QSize minimumSizeHint() const;
+ QSizePolicy sizePolicy() const;
+ bool eventFilter( QObject *, QEvent * );
+ bool customWhatsThis() const;
+ void enterWhatsThisMode(); // temporary, fix in Qt (Matthias, Mon Jul 17 15:20:55 CEST 2000 )
+ virtual void reparent( QWidget * parent, WFlags f, const QPoint & p, bool showIt = false );
+
+signals:
+ /**
+ * This signal is emitted when the embedded window has been lost (destroyed or reparented away)
+ *
+ * @see embeddedWinId()
+ */
+ // KDE4 rename to embeddedWindowLost()
+ void embeddedWindowDestroyed();
+
+protected:
+ bool event( QEvent * );
+ void keyPressEvent( QKeyEvent * );
+ void keyReleaseEvent( QKeyEvent * );
+ void focusInEvent( QFocusEvent * );
+ void focusOutEvent( QFocusEvent * );
+ void resizeEvent(QResizeEvent *);
+ void showEvent( QShowEvent * );
+ bool x11Event( XEvent* );
+
+ /**
+ * A change handler that indicates that the embedded window has been
+ * changed. The window handle can also be retrieved with
+ * embeddedWinId().
+ *
+ * @param w the handle of the window that changed
+ */
+ virtual void windowChanged( WId w );
+
+ bool focusNextPrevChild( bool next );
+
+private:
+ WId window;
+ QXEmbedData* d;
+ void checkGrab();
+ void sendSyntheticConfigureNotifyEvent();
+ void handleEmbed();
+};
+
+
+#endif
+#endif
diff --git a/kdeui/tests/Makefile.am b/kdeui/tests/Makefile.am
new file mode 100644
index 000000000..560c9b6dc
--- /dev/null
+++ b/kdeui/tests/Makefile.am
@@ -0,0 +1,105 @@
+# This file is part of the KDE libraries
+# Copyright (C) 1996-1997 Matthias Kalle Dalheimer (kalle@kde.org)
+# (C) 1997-1998 Stephan Kulow (coolo@kde.org)
+
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+
+# You should have received a copy of the GNU Library General Public License
+# along with this library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+INCLUDES = -I$(top_srcdir)/kdefx -I$(top_srcdir)/kdecore -I$(top_srcdir)/kdeui \
+ $(all_includes)
+
+AM_LDFLAGS = $(QT_LDFLAGS) $(X_LDFLAGS) $(KDE_RPATH)
+
+check_PROGRAMS = kaboutdialogtest kblendtest kbuttonboxtest kcharselecttest \
+ kcolortest kcolordlgtest kcomboboxtest kcompletiontest \
+ kdatepicktest kdatewidgettest kdialogbasetest \
+ kdockwidgetdemo kdockwidgettest \
+ kdualcolortest keditlistboxtest kfontdialogtest \
+ kgradienttest khashtest kdesattest\
+ kledtest klineedittest klineeditdlgtest \
+ kmessageboxtest knuminputtest \
+ kpalettetest \
+ kpopuptest kprogresstest krulertest kseparatortest \
+ kstatusbartest ktabctltest \
+ kunbalancedgrdtest kwindowtest kwizardtest \
+ itemcontainertest kpanelmenutest kedittest \
+ kxmlguitest kaccelgentest ksystemtraytest klistviewtest \
+ ktextedittest kmainwindowtest kmainwindowrestoretest \
+ kactiontest kdatetimewidgettest ktimewidgettest \
+ kspelltest kinputdialogtest ktabwidgettest kwordwraptest \
+ kdocktest qxembedtest ksqueezedtextlabeltest \
+ kpixmapregionselectordialogtest kjanuswidgettest ktoolbarlabelactiontest
+
+METASOURCES = AUTO
+
+LDADD = ../libkdeui.la
+
+kaboutdialogtest_SOURCES = kaboutdialogtest.cpp
+kblendtest_SOURCES = kblendtest.cpp
+kdesattest_SOURCES = kdesattest.cpp
+kbuttonboxtest_SOURCES = kbuttonboxtest.cpp
+kcharselecttest_SOURCES = kcharselecttest.cpp
+kcolordlgtest_SOURCES = kcolordlgtest.cpp
+kcolortest_SOURCES = kcolortest.cpp
+kcomboboxtest_SOURCES = kcomboboxtest.cpp
+kcompletiontest_SOURCES = kcompletiontest.cpp
+kdatepicktest_SOURCES = kdatepicktest.cpp
+kdatetimewidgettest_SOURCES = kdatetimewidgettest.cpp
+kdatewidgettest_SOURCES = kdatewidgettest.cpp
+kdialogbasetest_SOURCES = kdialogbasetest.cpp
+kdualcolortest_SOURCES = kdualcolortest.cpp
+kedittest_SOURCES = kedittest.cpp
+keditlistboxtest_SOURCES = keditlistboxtest.cpp
+kfontdialogtest_SOURCES = kfontdialogtest.cpp
+kgradienttest_SOURCES = kgradienttest.cpp
+khashtest_SOURCES = khashtest.cpp
+kledtest_SOURCES = kledtest.cpp
+klineedittest_SOURCES = klineedittest.cpp
+klineeditdlgtest_SOURCES = klineeditdlgtest.cpp
+kmessageboxtest_SOURCES = kmessageboxtest.cpp
+knuminputtest_SOURCES = knuminputtest.cpp
+kpalettetest_SOURCES = kpalettetest.cpp
+kpopuptest_SOURCES = kpopuptest.cpp
+kprogresstest_SOURCES = kprogresstest.cpp
+krulertest_SOURCES = krulertest.cpp
+kseparatortest_SOURCES = kseparatortest.cpp
+kstatusbartest_SOURCES = kstatusbartest.cpp
+ktabctltest_SOURCES = ktabctltest.cpp
+ktimewidgettest_SOURCES = ktimewidgettest.cpp
+kunbalancedgrdtest_SOURCES = kunbalancedgrdtest.cpp
+kwindowtest_SOURCES = kwindowtest.cpp
+kwizardtest_SOURCES = kwizardtest.cpp
+itemcontainertest_SOURCES = itemcontainertest.cpp
+kpanelmenutest_SOURCES = kpanelmenutest.cpp
+kdockwidgetdemo_SOURCES = kdockwidgetdemo.cpp
+kdockwidgettest_SOURCES = kdockwidgettest.cpp
+kxmlguitest_SOURCES = kxmlguitest.cpp
+kaccelgentest_SOURCES = kaccelgentest.cpp
+ksystemtraytest_SOURCES = ksystemtraytest.cpp
+klistviewtest_SOURCES = klistviewtest.cpp
+ktextedittest_SOURCES = ktextedittest.cpp
+kmainwindowtest_SOURCES = kmainwindowtest.cpp
+kmainwindowrestoretest_SOURCES = kmainwindowrestoretest.cpp
+kactiontest_SOURCES = kactiontest.cpp
+kspelltest_SOURCES = kspelltest.cpp
+kinputdialogtest_SOURCES = kinputdialogtest.cpp
+ktabwidgettest_SOURCES = ktabwidgettest.cpp
+kwordwraptest_SOURCES = kwordwraptest.cpp
+kdocktest_SOURCES=kdocktest.cpp
+qxembedtest_SOURCES=qxembedtest.cpp
+ksqueezedtextlabeltest_SOURCES = ksqueezedtextlabeltest.cpp
+kjanuswidgettest_SOURCES = kjanuswidgettest.cpp
+kpixmapregionselectordialogtest_SOURCES = kpixmapregionselectordialogtest.cpp
+ktoolbarlabelactiontest_SOURCES = ktoolbarlabelactiontest.cpp
diff --git a/kdeui/tests/RayTracedGear.png b/kdeui/tests/RayTracedGear.png
new file mode 100644
index 000000000..03314ca53
--- /dev/null
+++ b/kdeui/tests/RayTracedGear.png
Binary files differ
diff --git a/kdeui/tests/background_1.png b/kdeui/tests/background_1.png
new file mode 100644
index 000000000..5723d3a46
--- /dev/null
+++ b/kdeui/tests/background_1.png
Binary files differ
diff --git a/kdeui/tests/go.png b/kdeui/tests/go.png
new file mode 100644
index 000000000..8b9eacceb
--- /dev/null
+++ b/kdeui/tests/go.png
Binary files differ
diff --git a/kdeui/tests/itemcontainertest.cpp b/kdeui/tests/itemcontainertest.cpp
new file mode 100644
index 000000000..7ad145c9e
--- /dev/null
+++ b/kdeui/tests/itemcontainertest.cpp
@@ -0,0 +1,225 @@
+/*
+* Tests the item container widgets KIconView, KListView, KListBox
+*
+* Copyright (c) 2000 by Michael Reiher <michael.reiher@gmx.de>
+*
+* License: GPL, version 2
+* Version: $Id:
+*
+*/
+
+#include <qlayout.h>
+#include <qvbox.h>
+#include <qhbox.h>
+#include <qbuttongroup.h>
+#include <qradiobutton.h>
+#include <qcheckbox.h>
+#include <qlabel.h>
+
+#include <kapplication.h>
+#include <kglobal.h>
+#include <kconfig.h>
+#include <kiconview.h>
+#include <klistview.h>
+#include <klistbox.h>
+
+#include "itemcontainertest.h"
+
+static const char * item_xpm[] = {
+"22 22 3 1",
+" c None",
+". c #000000",
+"+ c #FF0000",
+" ...... ",
+" ....++++.... ",
+" ..++++..++++.. ",
+" ..++++++++++++.. ",
+" ..++++++..++++++.. ",
+" ..++++++++++++++++.. ",
+" .++++++++..++++++++. ",
+" .++++++++++++++++++. ",
+"..++++++++..++++++++..",
+".++++++++++++++++++++.",
+".+.+.+.+.+..+.+.+.+.+.",
+".+.+.+.+.+..+.+.+.+.+.",
+".++++++++++++++++++++.",
+"..++++++++..++++++++..",
+" .++++++++++++++++++. ",
+" .++++++++..++++++++. ",
+" ..++++++++++++++++.. ",
+" ..++++++..++++++.. ",
+" ..++++++++++++.. ",
+" ..++++..++++.. ",
+" ....++++.... ",
+" ...... "};
+
+
+KApplication *app;
+
+TopLevel::TopLevel(QWidget *parent, const char *name)
+ : QWidget(parent, name)
+{
+ setCaption("Item container test application");
+
+ QHBoxLayout* hBox = new QHBoxLayout( this );
+ QVBoxLayout* vBox = new QVBoxLayout( hBox );
+ hBox->addSpacing( 5 );
+
+ //Selection mode selection
+ m_pbgMode = new QButtonGroup( 1, Qt::Horizontal, "Selection Mode", this);
+ m_pbgMode->insert(new QRadioButton("NoSlection", m_pbgMode), TopLevel::NoSelection );
+ m_pbgMode->insert(new QRadioButton("Single", m_pbgMode), TopLevel::Single );
+ m_pbgMode->insert(new QRadioButton("Multi", m_pbgMode), TopLevel::Multi );
+ m_pbgMode->insert(new QRadioButton("Extended", m_pbgMode), TopLevel::Extended );
+ m_pbgMode->setExclusive( true );
+ vBox->addWidget( m_pbgMode );
+
+ connect( m_pbgMode, SIGNAL( clicked( int ) ),
+ this, SLOT( slotSwitchMode( int ) ) );
+
+ //Signal labels
+ QGroupBox* gbWiget = new QGroupBox( 1, Qt::Horizontal, "Widget", this);
+ m_plblWidget = new QLabel( gbWiget );
+ vBox->addWidget( gbWiget );
+ QGroupBox* gbSignal = new QGroupBox( 1, Qt::Horizontal, "emitted Signal", this);
+ m_plblSignal = new QLabel( gbSignal );
+ vBox->addWidget( gbSignal );
+ QGroupBox* gbItem = new QGroupBox( 1, Qt::Horizontal, "on Item", this);
+ m_plblItem = new QLabel( gbItem );
+ vBox->addWidget( gbItem );
+
+ QButtonGroup* bgListView = new QButtonGroup( 1, Qt::Horizontal, "KListView", this);
+ QCheckBox* cbListView = new QCheckBox("Single Column", bgListView);
+ vBox->addWidget( bgListView );
+ connect( cbListView, SIGNAL( toggled( bool ) ),
+ this, SLOT( slotToggleSingleColumn( bool ) ) );
+
+ KGlobal::config()->reparseConfiguration();
+
+ //Create IconView
+ QGroupBox* gbIconView = new QGroupBox( 1, Qt::Horizontal, "KIconView", this);
+ m_pIconView = new KIconView( gbIconView );
+ hBox->addWidget( gbIconView );
+ hBox->addSpacing( 5 );
+ connect( m_pIconView, SIGNAL( executed( QIconViewItem* ) ),
+ this, SLOT( slotIconViewExec( QIconViewItem* ) ) );
+
+ //Create ListView
+ QGroupBox* gbListView = new QGroupBox( 1, Qt::Horizontal, "KListView", this);
+ m_pListView = new KListView( gbListView );
+ m_pListView->addColumn("Item");
+ m_pListView->addColumn("Text");
+ hBox->addWidget( gbListView );
+ hBox->addSpacing( 5 );
+ connect( m_pListView, SIGNAL( executed( QListViewItem* ) ),
+ this, SLOT( slotListViewExec( QListViewItem* ) ) );
+
+ //Create ListBox
+ QGroupBox* gbListBox = new QGroupBox( 1, Qt::Horizontal, "KListBox", this);
+ m_pListBox = new KListBox( gbListBox );
+ hBox->addWidget( gbListBox );
+ connect( m_pListBox, SIGNAL( executed( QListBoxItem* ) ),
+ this, SLOT( slotListBoxExec( QListBoxItem* ) ) );
+
+ //Initialize buttons
+ cbListView->setChecked( !m_pListView->allColumnsShowFocus() );
+ m_pbgMode->setButton( TopLevel::Extended );
+ slotSwitchMode( TopLevel::Extended );
+
+ //Fill container widgets
+ for( int i = 0; i < 10; i++ ) {
+ new QIconViewItem( m_pIconView, QString("Item%1").arg(i), QPixmap(item_xpm) );
+
+ QListViewItem* lv = new QListViewItem( m_pListView, QString("Item%1").arg(i), QString("Text%1").arg(i) );
+ lv->setPixmap( 0, QPixmap(item_xpm));
+ lv->setPixmap( 1, QPixmap(item_xpm));
+
+ new QListBoxPixmap( m_pListBox, QPixmap(item_xpm), QString("Item%1").arg(i));
+ }
+
+ connect( m_pIconView, SIGNAL( clicked( QIconViewItem* ) ),
+ this, SLOT( slotClicked( QIconViewItem* ) ) );
+ connect( m_pIconView, SIGNAL( doubleClicked( QIconViewItem* ) ),
+ this, SLOT( slotDoubleClicked( QIconViewItem* ) ) );
+}
+
+void TopLevel::slotSwitchMode( int id )
+{
+ m_pIconView->clearSelection();
+ m_pListView->clearSelection();
+ m_pListBox->clearSelection();
+
+ switch( id ) {
+ case TopLevel::NoSelection:
+ m_pIconView->setSelectionMode( KIconView::NoSelection );
+ m_pListView->setSelectionMode( QListView::NoSelection );
+ m_pListBox->setSelectionMode( KListBox::NoSelection );
+ break;
+ case TopLevel::Single:
+ m_pIconView->setSelectionMode( KIconView::Single );
+ m_pListView->setSelectionMode( QListView::Single );
+ m_pListBox->setSelectionMode( KListBox::Single );
+ break;
+ case TopLevel::Multi:
+ m_pIconView->setSelectionMode( KIconView::Multi );
+ m_pListView->setSelectionMode( QListView::Multi );
+ m_pListBox->setSelectionMode( KListBox::Multi );
+ break;
+ case TopLevel::Extended:
+ m_pIconView->setSelectionMode( KIconView::Extended );
+ m_pListView->setSelectionMode( QListView::Extended );
+ m_pListBox->setSelectionMode( KListBox::Extended );
+ break;
+ default:
+ Q_ASSERT(0);
+ }
+}
+
+void TopLevel::slotIconViewExec( QIconViewItem* item )
+{
+ m_plblWidget->setText("KIconView");
+ m_plblSignal->setText("executed");
+ if( item )
+ m_plblItem->setText( item->text() );
+ else
+ m_plblItem->setText("Viewport");
+}
+
+void TopLevel::slotListViewExec( QListViewItem* item )
+{
+ m_plblWidget->setText("KListView");
+ m_plblSignal->setText("executed");
+ if( item )
+ m_plblItem->setText( item->text(0) );
+ else
+ m_plblItem->setText("Viewport");
+}
+
+void TopLevel::slotListBoxExec( QListBoxItem* item )
+{
+ m_plblWidget->setText("KListBox");
+ m_plblSignal->setText("executed");
+ if( item )
+ m_plblItem->setText( item->text() );
+ else
+ m_plblItem->setText("Viewport");
+}
+
+void TopLevel::slotToggleSingleColumn( bool b )
+{
+ m_pListView->setAllColumnsShowFocus( !b );
+}
+
+int main( int argc, char ** argv )
+{
+ app = new KApplication ( argc, argv, "ItemContainerTest" );
+
+ TopLevel *toplevel = new TopLevel(0, "itemcontainertest");
+
+ toplevel->show();
+ toplevel->resize( 600, 300 );
+ app->setMainWidget(toplevel);
+ app->exec();
+}
+
+#include "itemcontainertest.moc"
diff --git a/kdeui/tests/itemcontainertest.h b/kdeui/tests/itemcontainertest.h
new file mode 100644
index 000000000..c6091f5e5
--- /dev/null
+++ b/kdeui/tests/itemcontainertest.h
@@ -0,0 +1,45 @@
+#ifndef _ITEMCONTAINERTEST_H
+#define _ITEMCONTAINERTEST_H
+
+#include <qwidget.h>
+
+class KIconView;
+class KListView;
+class KListBox;
+class QButtonGroup;
+class QLabel;
+
+class TopLevel : public QWidget
+{
+ Q_OBJECT
+public:
+
+ TopLevel( QWidget *parent=0, const char *name=0 );
+
+ enum ViewID { IconView, ListView, ListBox };
+ enum ModeID { NoSelection, Single, Multi, Extended };
+
+public slots:
+ //void slotSwitchView( int id );
+ void slotSwitchMode( int id );
+
+ void slotIconViewExec( QIconViewItem* item );
+ void slotListViewExec( QListViewItem* item );
+ void slotListBoxExec( QListBoxItem* item );
+ void slotToggleSingleColumn( bool b );
+
+ void slotClicked( QIconViewItem* ) { qDebug("CLICK");}
+ void slotDoubleClicked( QIconViewItem* ) { qDebug("DOUBLE CLICK");}
+protected:
+ KIconView* m_pIconView;
+ KListView* m_pListView;
+ KListBox* m_pListBox;
+
+ QButtonGroup* m_pbgView;
+ QButtonGroup* m_pbgMode;
+ QLabel* m_plblWidget;
+ QLabel* m_plblSignal;
+ QLabel* m_plblItem;
+};
+
+#endif
diff --git a/kdeui/tests/kaboutdialogtest.cpp b/kdeui/tests/kaboutdialogtest.cpp
new file mode 100644
index 000000000..89d25d531
--- /dev/null
+++ b/kdeui/tests/kaboutdialogtest.cpp
@@ -0,0 +1,72 @@
+/* -*- C++ -*-
+ * This file shows an example for the KDE about dialog.
+ *
+ * copyright: (C) Mirko Boehm, 1999
+ * license: GNU Public License, Version 2
+ * mail to: Mirko Boehm <mirko@kde.org>
+ * requires: recent C++-compiler, at least Qt 1.4
+ * $Revision$
+ */
+
+#include "kaboutdialog.h"
+// #include <kimgio.h>
+#include <qimage.h>
+#include <kapplication.h>
+#include <klocale.h>
+
+int main(int argc, char** argv)
+{
+ (void)new KApplication(argc, argv, "KAboutDialogTest");
+ QImage logo;
+ QImage bg;
+ QPixmap pix;
+ KAboutDialog about;
+ // -----
+ // kimgioRegister();
+ if(logo.load("RayTracedGear.png"))
+ {
+ pix=logo;
+ about.setLogo(pix);
+ } else {
+ qDebug("main: No logo loaded.");
+ }
+ if(bg.load("background_1.png"))
+ {
+ pix=bg;
+ about.setBackgroundTile(&pix);
+ about.showTile( true );
+ about.enableLinkedHelp( true );
+
+ //about.showBaseFrameTile(true);
+ } else {
+ qDebug("main: No tile loaded.");
+ }
+// about.setButtonOKText
+// ("Cl&ose", "Close this dialog.",
+// "<b>Close</b> the dialog<br>"
+// "<i>(there are no settings to save).</i>");
+ about.setCaption("KAboutDialog example");
+ about.setVersion("KAboutDialog, Draft Study");
+ about.setHelp("kdehelp/intro.html", "intro");
+ // ----- set the application author:
+ about.setAuthor
+ ("Mirko Boehm", "mirko@kde.org", "", "Initial developer.");
+ // ----- set the application maintainer:
+ about.setMaintainer("Any One", // name
+ "anyone@kde.org", // email address
+ "http://www.anyhere.com", // URL
+ "Current maintainer."); // description
+ // ----- add some contributors:
+ about.addContributor("Some One", "someone@kde.org", "http://www.somehere.com",
+ "Making coffee");
+ about.addContributor("Another One",
+ "anotherone@kde.org",
+ "http://www.blablax.com",
+ "Pizza donator");
+ // ----- contents of the dialog have changed, adapt sizes:
+ about.adjust();
+ about.exec();
+ // -----
+ return 0;
+}
+
diff --git a/kdeui/tests/kaccelgentest.cpp b/kdeui/tests/kaccelgentest.cpp
new file mode 100644
index 000000000..d619bdfba
--- /dev/null
+++ b/kdeui/tests/kaccelgentest.cpp
@@ -0,0 +1,51 @@
+#include "kaccelgen.h"
+
+#include <qstringlist.h>
+
+#include <iostream>
+
+using std::cout;
+using std::endl;
+
+void check( const QString &what, const QStringList &expected, const QStringList &received )
+{
+ cout << "Testing " << what.latin1() << ": ";
+ if ( expected == received ) {
+ cout << "ok" << endl;
+ } else {
+ cout << "ERROR!" << endl;
+ cout << "Expected: " << expected.join( "," ).latin1() << endl;
+ cout << "Received: " << received.join( "," ).latin1() << endl;
+ }
+}
+
+int main()
+{
+ QStringList input;
+ input << "foo" << "bar item" << "&baz" << "bif" << "boz" << "boz 2"
+ << "yoyo && dyne";
+
+ QStringList expected;
+ expected << "&foo" << "bar &item" << "&baz" << "bif" << "b&oz" << "boz &2"
+ << "&yoyo && dyne";
+
+ QStringList output;
+ KAccelGen::generate( input, output );
+ check( "QStringList value generation", expected, output );
+
+ QMap<QString,QString> map;
+ for (QStringList::ConstIterator it = input.begin(); it != input.end(); ++it) {
+ map.insert(*it, *it);
+ }
+ input.sort();
+ expected.clear();
+ KAccelGen::generate( input, expected );
+
+ output.clear();
+ KAccelGen::generateFromValues( map, output );
+ check( "map value generation", expected, output );
+
+ output.clear();
+ KAccelGen::generateFromKeys( map, output );
+ check( "map key generation", expected, output );
+}
diff --git a/kdeui/tests/kactiontest.cpp b/kdeui/tests/kactiontest.cpp
new file mode 100644
index 000000000..60fa334ee
--- /dev/null
+++ b/kdeui/tests/kactiontest.cpp
@@ -0,0 +1,38 @@
+
+#include <qguardedptr.h>
+
+#include <kapplication.h>
+#include <kaction.h>
+
+#include <assert.h>
+
+int main( int argc, char **argv )
+{
+ KApplication app( argc, argv, "kactiontest" );
+
+ KActionCollection coll( static_cast<QObject *>( 0 ) );
+
+ QGuardedPtr<KAction> action1 = new KRadioAction("test",0, &coll);
+ QGuardedPtr<KAction> action2 = new KRadioAction("test",0, &coll);
+ QGuardedPtr<KAction> action3 = new KRadioAction("test",0, &coll);
+ QGuardedPtr<KAction> action4 = new KRadioAction("test",0, &coll);
+ QGuardedPtr<KAction> action5 = new KRadioAction("test",0, &coll);
+ QGuardedPtr<KAction> action6 = new KRadioAction("test",0, &coll);
+ QGuardedPtr<KAction> action7 = new KRadioAction("test",0, &coll);
+
+ coll.clear();
+ assert( coll.isEmpty() );
+
+ assert( action1.isNull() );
+ assert( action2.isNull() );
+ assert( action3.isNull() );
+ assert( action4.isNull() );
+ assert( action5.isNull() );
+ assert( action6.isNull() );
+ assert( action7.isNull() );
+
+ return 0;
+}
+
+/* vim: et sw=4 ts=4
+ */
diff --git a/kdeui/tests/kalphaicontest.h b/kdeui/tests/kalphaicontest.h
new file mode 100644
index 000000000..66d26e6f3
--- /dev/null
+++ b/kdeui/tests/kalphaicontest.h
@@ -0,0 +1,24 @@
+#include <kdebug.h>
+#include <qwidget.h>
+#include <qimage.h>
+#include <qpixmap.h>
+#include <kimageeffect.h>
+#include <kalphapainter.h>
+
+class KAlphaTest : public QWidget
+{
+ public:
+ KAlphaTest();
+ protected:
+ void paintEvent(QPaintEvent *);
+ private:
+ QImage m_image;
+ QPixmap m_pixmap;
+ QImage m_bg;
+
+ public:
+ static bool m_useDblBuffer;
+ static bool m_usePixmap;
+ static bool m_correctOverlapping;
+};
+
diff --git a/kdeui/tests/kblendtest.cpp b/kdeui/tests/kblendtest.cpp
new file mode 100644
index 000000000..f12d65b2b
--- /dev/null
+++ b/kdeui/tests/kblendtest.cpp
@@ -0,0 +1,98 @@
+#include "kblendtest.h"
+#include <kapplication.h>
+#include <kimageeffect.h>
+#include <qpainter.h>
+#include <qdatetime.h>
+#include <qstring.h>
+
+int cols = 3, rows = 3; // how many
+
+KBlendWidget::KBlendWidget(QWidget *parent, const char *name)
+ :QWidget(parent, name)
+{
+
+ bgnd = qRgb(255, 255, 255);
+
+ image = QImage("testimage.png");
+
+ resize(image.width()*2+60, image.height()*3+80);
+ setBackgroundColor(bgnd);
+}
+
+void KBlendWidget::paintEvent(QPaintEvent */*ev*/)
+{
+ QTime time;
+ int it, ft;
+ QString say;
+
+ image = QImage("testimage.png");
+
+ QPainter p(this);
+ p.setPen(Qt::black);
+
+ // you see here use of anti_dir param (blend from down to up, here)
+ time.start();
+ it = time.elapsed();
+ KImageEffect::blend(image, 0.2, bgnd, KImageEffect::VerticalGradient,true);
+ ft = time.elapsed();
+ say.setNum( ft - it); say += " ms, Vertical";
+ p.drawImage(20, 20, image);
+ p.drawText(5 , 15, say);
+
+ image = QImage("testimage.png");
+
+ // here a negative initial intensity is used (1/2 of image is unaffected)
+ it = time.elapsed();
+ KImageEffect::blend(image, -0.5, bgnd, KImageEffect::HorizontalGradient);
+ ft = time.elapsed();
+ say.setNum( ft - it); say += " ms, Horizontal";
+ p.drawImage(40+image.width(), 20, image);
+ p.drawText(15+image.width() , 15, say);
+
+ image = QImage("testimage.png");
+
+ it = time.elapsed();
+ KImageEffect::blend(image, 0., bgnd, KImageEffect::DiagonalGradient,true);
+ ft = time.elapsed();
+ say.setNum( ft - it); say += " ms, Diagonal";
+ p.drawImage(20, 40+image.height(), image);
+ p.drawText(5 , 35+image.height(), say);
+
+ image = QImage("testimage.png");
+
+ it = time.elapsed();
+ KImageEffect::blend(image, 0.1, bgnd, KImageEffect::CrossDiagonalGradient);
+ ft = time.elapsed();
+ say.setNum( ft - it); say += " ms, CrossDiagonal";
+ p.drawImage(40+image.width(), 40+image.height(), image);
+ p.drawText(25+image.width() , 35 + image.height(), say);
+
+ image = QImage("testimage.png");
+
+ it = time.elapsed();
+ KImageEffect::blend(image, -0.6, bgnd, KImageEffect::RectangleGradient);
+ ft = time.elapsed();
+ say.setNum( ft - it); say += " ms, Rectangle";
+ p.drawImage(20, 60+2*image.height(), image);
+ p.drawText(5 , 55+2*image.height(), say);
+
+ image = QImage("testimage.png");
+
+ it = time.elapsed();
+ KImageEffect::blend(image, 0.2, bgnd, KImageEffect::EllipticGradient);
+ ft = time.elapsed();
+ say.setNum( ft - it); say += " ms, Elliptic";
+ p.drawImage(40+image.width(), 60+2*image.height(), image);
+ p.drawText(25+image.width(), 55+2*image.height(), say);
+ p.end();
+}
+
+int main(int argc, char **argv)
+{
+ KApplication app(argc, argv, "KBlendTest");
+ KBlendWidget w;
+ app.setMainWidget(&w);
+ w.show();
+ return(app.exec());
+}
+
diff --git a/kdeui/tests/kblendtest.h b/kdeui/tests/kblendtest.h
new file mode 100644
index 000000000..800f2d562
--- /dev/null
+++ b/kdeui/tests/kblendtest.h
@@ -0,0 +1,24 @@
+//
+// Simple little hack to show off blending effects.
+//
+// (C) KDE Artistic Cristian Tibirna <tibirna@kde.org>
+//
+
+#ifndef __KBLEND_TEST_H
+#define __KBLEND_TEST_H
+
+#include <qwidget.h>
+#include <qimage.h>
+
+class KBlendWidget : public QWidget
+{
+public:
+ KBlendWidget(QWidget *parent=0, const char *name=0);
+protected:
+ void paintEvent(QPaintEvent *ev);
+private:
+ QImage image, original;
+ QColor bgnd;
+};
+
+#endif
diff --git a/kdeui/tests/kbuttonboxtest.cpp b/kdeui/tests/kbuttonboxtest.cpp
new file mode 100644
index 000000000..d9b070bc0
--- /dev/null
+++ b/kdeui/tests/kbuttonboxtest.cpp
@@ -0,0 +1,205 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Mario Weilguni (mweilguni@sime.com)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#include <kapplication.h>
+#include "kbuttonbox.h"
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qdialog.h>
+#include <qpushbutton.h>
+
+int main(int argc, char **argv) {
+ KApplication a(argc, argv, "dummy");
+
+ // example 1
+ {
+ QDialog *w = new QDialog(0, "A common dialog", true);
+ w->setCaption("Example 1");
+ QVBoxLayout *tl = new QVBoxLayout(w, 5);
+ QLabel *l = new QLabel("A very common dialog\n\n"\
+ "OK and Cancel are left aligned, Help\n"\
+ "is right aligned. Try resizing\n"\
+ "the window!\n"
+ "Press OK or Cancel when done"
+ , w);
+ l->setAlignment(Qt::AlignVCenter|Qt::AlignLeft|Qt::WordBreak);
+ l->setMinimumSize(l->sizeHint());
+ tl->addWidget(l,1);
+ KButtonBox *bbox = new KButtonBox(w);
+ QPushButton *b = bbox->addButton("OK");
+ b->setDefault(true);
+ w->connect(b, SIGNAL(clicked()),
+ w, SLOT(accept()));
+ w->connect(bbox->addButton("Cancel"), SIGNAL(clicked()),
+ w, SLOT(accept()));
+
+ bbox->addStretch(1);
+ bbox->addButton("Help");
+ bbox->layout();
+ tl->addWidget(bbox,0);
+ tl->activate();
+ w->exec();
+ delete w;
+ }
+
+ // example 2
+ {
+ QDialog *w = new QDialog(0, "Right aligned buttons", true);
+ w->setCaption("Example 2");
+ QVBoxLayout *tl = new QVBoxLayout(w, 5);
+ QLabel *l = new QLabel("Another common dialog\n\n"\
+ "OK and Cancel are right aligned\n"\
+ "Try resizing the window!", w);
+ l->setAlignment(Qt::AlignVCenter|Qt::AlignLeft|Qt::WordBreak);
+ l->setMinimumSize(l->sizeHint());
+ tl->addWidget(l,1);
+ KButtonBox *bbox = new KButtonBox(w);
+ bbox->addStretch(1);
+ QPushButton *b = bbox->addButton("OK");
+ b->setDefault(true);
+ w->connect(b, SIGNAL(clicked()),
+ w, SLOT(accept()));
+ w->connect(bbox->addButton("Cancel"), SIGNAL(clicked()),
+ w, SLOT(accept()));
+ bbox->layout();
+ tl->addWidget(bbox,0);
+ tl->activate();
+ w->exec();
+ delete w;
+ }
+
+ // example 3
+ {
+ QDialog *w = new QDialog(0, "Middle aligned buttons", true);
+ w->setCaption("Example 3");
+ QVBoxLayout *tl = new QVBoxLayout(w, 5);
+ QLabel *l = new QLabel("Another common dialog\n\n"\
+ "OK and Cancel are middle aligned\n"\
+ "Try resizing the window!", w);
+ l->setAlignment(Qt::AlignVCenter|Qt::AlignLeft|Qt::WordBreak);
+ l->setMinimumSize(l->sizeHint());
+ tl->addWidget(l,1);
+ KButtonBox *bbox = new KButtonBox(w);
+ bbox->addStretch(1);
+ QPushButton *b = bbox->addButton("OK");
+ b->setDefault(true);
+ w->connect(b, SIGNAL(clicked()),
+ w, SLOT(accept()));
+ w->connect(bbox->addButton("Cancel"), SIGNAL(clicked()),
+ w, SLOT(accept()));
+ bbox->addStretch(1);
+ bbox->layout();
+ tl->addWidget(bbox,0);
+ tl->activate();
+ w->exec();
+ delete w;
+ }
+
+ // example 4
+ {
+ QDialog *w = new QDialog(0, "Bad example", true);
+ w->setCaption("Example 4");
+ QVBoxLayout *tl = new QVBoxLayout(w, 5);
+ QLabel *l = new QLabel("A very bad example\n\n"\
+ "Sometimes it's a bad idea to take\n"
+ "the maximum width for all buttons\n"
+ "since it will look ugly -- "
+ "anyway, it works", w);
+ l->setAlignment(Qt::AlignVCenter|Qt::AlignLeft|Qt::WordBreak);
+ l->setMinimumSize(l->sizeHint());
+ tl->addWidget(l,1);
+ KButtonBox *bbox = new KButtonBox(w);
+ bbox->addStretch(1);
+ QPushButton *b = bbox->addButton("OK");
+ b->setDefault(true);
+ w->connect(b, SIGNAL(clicked()),
+ w, SLOT(accept()));
+ w->connect(bbox->addButton("Cancel"), SIGNAL(clicked()),
+ w, SLOT(accept()));
+
+ bbox->addButton("Push me and I give you a banana");
+ bbox->addStretch(1);
+ bbox->layout();
+ tl->addWidget(bbox,0);
+ tl->activate();
+ w->exec();
+ delete w;
+ }
+
+ // example 5
+ {
+ QDialog *w = new QDialog(0, "Bad example", true);
+ w->setCaption("Example 5");
+ QVBoxLayout *tl = new QVBoxLayout(w, 5);
+ QLabel *l = new QLabel("A better solution for the bad example\n\n"\
+ "Use \"addButton(\"Push me and I give"
+ "you a banana\", true);\" to\n"
+ "prevent this strange effect as seen\n"
+ "the former example!"
+ ,w);
+ l->setAlignment(Qt::AlignVCenter|Qt::AlignLeft|Qt::WordBreak);
+ l->setMinimumSize(l->sizeHint());
+ tl->addWidget(l,1);
+ KButtonBox *bbox = new KButtonBox(w);
+ bbox->addStretch(1);
+ QPushButton *b = bbox->addButton("OK");
+ b->setDefault(true);
+ w->connect(b, SIGNAL(clicked()),
+ w, SLOT(accept()));
+ w->connect(bbox->addButton("Cancel"), SIGNAL(clicked()),
+ w, SLOT(accept()));
+
+ bbox->addButton("Push me and I give you a banana", true);
+ bbox->addStretch(1);
+ bbox->layout();
+ tl->addWidget(bbox,0);
+ tl->activate();
+ w->exec();
+ delete w;
+ }
+
+ // example 6
+ {
+ QDialog *w = new QDialog(0, "Vertical", true);
+ w->setCaption("Example 6 (last)");
+ QHBoxLayout *tl = new QHBoxLayout(w, 5);
+ QLabel *l = new QLabel("Did I mention that it's possible\n"
+ "to make vertically aligned buttons\n"
+ "too?"
+ ,w);
+ l->setAlignment(Qt::AlignVCenter|Qt::AlignLeft|Qt::WordBreak);
+ l->setMinimumSize(l->sizeHint());
+ tl->addWidget(l,1);
+ KButtonBox *bbox = new KButtonBox(w, KButtonBox::Vertical);
+ QPushButton *b = bbox->addButton("OK");
+ b->setDefault(true);
+ w->connect(b, SIGNAL(clicked()),
+ w, SLOT(accept()));
+ w->connect(bbox->addButton("Cancel"), SIGNAL(clicked()),
+ w, SLOT(accept()));
+
+ bbox->addStretch(1);
+ bbox->layout();
+ tl->addWidget(bbox,0);
+ tl->activate();
+ w->exec();
+ delete w;
+ }
+
+ return 0;
+}
diff --git a/kdeui/tests/kcharselecttest.cpp b/kdeui/tests/kcharselecttest.cpp
new file mode 100644
index 000000000..facd17bca
--- /dev/null
+++ b/kdeui/tests/kcharselecttest.cpp
@@ -0,0 +1,16 @@
+#include <kapplication.h>
+#include <klocale.h>
+#include "kcharselect.h"
+
+int main (int argc,char **argv)
+{
+ KApplication app( argc, argv, "kcharselecttest" );
+
+ KCharSelect selector( 0, "char selector" );
+ selector.resize( selector.sizeHint() );
+ selector.show();
+ selector.setCaption( "KCharSelect Test" );
+
+ app.setMainWidget( &selector );
+ return app.exec();
+}
diff --git a/kdeui/tests/kcolordlgtest.cpp b/kdeui/tests/kcolordlgtest.cpp
new file mode 100644
index 000000000..b5ba68393
--- /dev/null
+++ b/kdeui/tests/kcolordlgtest.cpp
@@ -0,0 +1,41 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 Martin Jones (mjones@kde.org)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <kapplication.h>
+#include "kcolordialog.h"
+#include <kconfig.h>
+#include <klocale.h>
+
+int main( int argc, char *argv[] )
+{
+ QColor color;
+
+ KLocale::setMainCatalogue("kdelibs");
+ QApplication::setColorMode( QApplication::CustomColors );
+ KApplication a( argc, argv, "KColorDialogTest" );
+ KConfig aConfig;
+ aConfig.setGroup( "KColorDialog-test" );
+
+ color = aConfig.readColorEntry( "Chosen" );
+ int nRet = KColorDialog::getColor( color, Qt::red /*testing default color*/ );
+ aConfig.writeEntry( "Chosen", color );
+
+ return nRet;
+}
+
diff --git a/kdeui/tests/kcolortest.cpp b/kdeui/tests/kcolortest.cpp
new file mode 100644
index 000000000..c4dd5892b
--- /dev/null
+++ b/kdeui/tests/kcolortest.cpp
@@ -0,0 +1,169 @@
+
+#include "kcolortest.h"
+#include <kapplication.h>
+#include <kimageeffect.h>
+#include <stdio.h>
+#include <qdatetime.h>
+
+bool fullscreen = false, oldway = false, intvsfade = false;
+int max = 20; // how many steps
+
+KColorWidget::KColorWidget(QWidget *parent, const char *name)
+ : QWidget(parent, name)
+{
+
+ if (fullscreen || intvsfade) {
+ QPixmap shot = QPixmap::grabWindow(QApplication::desktop()->winId());
+ original = shot.convertToImage();
+ }
+ else
+ original = QImage("testimage.png");
+ resize(original.width(), original.height());
+}
+
+void KColorWidget::paintEvent(QPaintEvent *)
+{
+ if(!pixmap.isNull())
+ bitBlt(this, 0, 0, &pixmap, 0, 0, pixmap.width(), pixmap.height(),
+ Qt::CopyROP, true);
+}
+
+void KColorWidget::doIntensityLoop()
+{
+ int count;
+
+ int start, stop;
+ QTime t;
+
+ t.start();
+
+ image = original; image.detach();
+
+ if (fullscreen){
+ start = t.elapsed();
+ for(count=0; count < max; ++count){
+ if (!oldway)
+ KImageEffect::intensity(image, -1./max);
+ else {
+ uint *qptr=(uint *)image.bits();
+ QRgb qrgb;
+ int size=pixmap.width()*pixmap.height();
+ for (int i=0;i<size; i++, qptr++)
+ {
+ qrgb=*(QRgb *)qptr;
+ *qptr=qRgb((int)(qRed(qrgb)*1./max),
+ (int)(qGreen(qrgb)*1./max),
+ (int)(qBlue(qrgb)*1./max));
+ }
+ }
+ pixmap.convertFromImage(image);
+ bitBlt(this, 0, 0, &pixmap, 0, 0, pixmap.width(), pixmap.height(),
+ Qt::CopyROP, true);
+ }
+ stop = t.elapsed();
+ qDebug ("Total fullscreen %s dim time for %d steps : %f s",
+ oldway?"(antonio)":"(intensity)", count, (stop - start)*1e-3);
+
+ if (intvsfade) {
+ image = original; image.detach();
+ start = t.elapsed();
+ for(count=0; count < max; ++count){
+ KImageEffect::fade(image, 1./max, black);
+ pixmap.convertFromImage(image);
+ bitBlt(this, 0, 0, &pixmap, 0, 0, pixmap.width(), pixmap.height(),
+ Qt::CopyROP, true);
+ }
+ }
+ stop = t.elapsed();
+ qDebug ("Total fullscreen (fade) dim time for %d steps : %f s",
+ count, (stop - start)*1e-3);
+
+ }
+
+ else {
+ image = original; image.detach();
+ qDebug("Intensity test");
+ for(count=0; count < max; ++count){
+ KImageEffect::intensity(image, 1./max);
+ pixmap.convertFromImage(image);
+ bitBlt(this, 0, 0, &pixmap, 0, 0, pixmap.width(), pixmap.height(),
+ Qt::CopyROP, true);
+ }
+
+ for(count=0; count < max; ++count){
+ KImageEffect::intensity(image, -1./max);
+ pixmap.convertFromImage(image);
+ bitBlt(this, 0, 0, &pixmap, 0, 0, pixmap.width(), pixmap.height(),
+ Qt::CopyROP, true);
+ }
+
+ image = original; image.detach();
+ qDebug("Red channel intensity test");
+ for(count=0; count < max; ++count){
+ KImageEffect::channelIntensity(image, -1./max, KImageEffect::Red);
+ pixmap.convertFromImage(image);
+ bitBlt(this, 0, 0, &pixmap, 0, 0, pixmap.width(), pixmap.height(),
+ Qt::CopyROP, true);
+ }
+ for(count=0; count < max; ++count){
+ KImageEffect::channelIntensity(image, 1./max, KImageEffect::Red);
+ pixmap.convertFromImage(image);
+ bitBlt(this, 0, 0, &pixmap, 0, 0, pixmap.width(), pixmap.height(),
+ Qt::CopyROP, true);
+ }
+
+ image = original; image.detach();
+ qDebug("Green channel intensity test");
+ for(count=0; count < max; ++count){
+ KImageEffect::channelIntensity(image, -1./max, KImageEffect::Green);
+ pixmap.convertFromImage(image);
+ bitBlt(this, 0, 0, &pixmap, 0, 0, pixmap.width(), pixmap.height(),
+ Qt::CopyROP, true);
+ }
+ for(count=0; count < max; ++count){
+ KImageEffect::channelIntensity(image, 1./max, KImageEffect::Green);
+ pixmap.convertFromImage(image);
+ bitBlt(this, 0, 0, &pixmap, 0, 0, pixmap.width(), pixmap.height(),
+ Qt::CopyROP, true);
+ }
+
+ image = original; image.detach();
+ qDebug("Blue channel intensity test");
+ for(count=0; count < max; ++count){
+ KImageEffect::channelIntensity(image, -1./max, KImageEffect::Blue);
+ pixmap.convertFromImage(image);
+ bitBlt(this, 0, 0, &pixmap, 0, 0, pixmap.width(), pixmap.height(),
+ Qt::CopyROP, true);
+ }
+ for(count=0; count < max; ++count){
+ KImageEffect::channelIntensity(image, 1./max, KImageEffect::Blue);
+ pixmap.convertFromImage(image);
+ bitBlt(this, 0, 0, &pixmap, 0, 0, pixmap.width(), pixmap.height(),
+ Qt::CopyROP, true);
+ }
+ }
+}
+
+int main(int argc, char **argv)
+{
+ if (argc > 1) {
+ if (!strcmp(argv[1], "fullscreen"))
+ {
+ fullscreen = true;
+ if (!strcmp(argv[2], "old_way"))
+ oldway = true;
+ }
+ else if (!strcmp(argv[1], "int_vs_fade")) {
+ intvsfade = fullscreen = true;
+ oldway = false;
+ }
+ else
+ printf("Usage: %s [int_vs_fade | fullscreen [old_way]]\n ", argv[0]);
+ }
+ KApplication *app = new KApplication(argc, argv, "KColorTest");
+ KColorWidget w;
+ app->setMainWidget(&w);
+ w.show();
+ w.doIntensityLoop();
+ return(app->exec());
+}
diff --git a/kdeui/tests/kcolortest.h b/kdeui/tests/kcolortest.h
new file mode 100644
index 000000000..52cce12cc
--- /dev/null
+++ b/kdeui/tests/kcolortest.h
@@ -0,0 +1,21 @@
+#ifndef __KCOLORTEST_H
+#define __KCOLORTEST_H
+
+#include <qwidget.h>
+#include <qimage.h>
+#include <kpixmap.h>
+
+class KColorWidget : public QWidget
+{
+public:
+ KColorWidget(QWidget *parent=0, const char *name=0);
+ void doIntensityLoop();
+protected:
+ void paintEvent(QPaintEvent *ev);
+private:
+ QImage image, original;
+ KPixmap pixmap;
+
+};
+
+#endif
diff --git a/kdeui/tests/kcomboboxtest.cpp b/kdeui/tests/kcomboboxtest.cpp
new file mode 100644
index 000000000..2eb1f73e0
--- /dev/null
+++ b/kdeui/tests/kcomboboxtest.cpp
@@ -0,0 +1,227 @@
+#define protected public // for delegate()
+#include <kcombobox.h>
+#undef protected
+
+#include "kcomboboxtest.h"
+
+#include <assert.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kdialog.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <ksimpleconfig.h>
+
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qpixmap.h>
+#include <qlabel.h>
+#include <qhbox.h>
+#include <qtimer.h>
+
+
+KComboBoxTest::KComboBoxTest(QWidget* widget, const char* name )
+ :QWidget(widget, name)
+{
+ QVBoxLayout *vbox = new QVBoxLayout (this, KDialog::marginHint(), KDialog::spacingHint());
+
+ // Test for KCombo's KLineEdit destruction
+ KComboBox *testCombo = new KComboBox( true, this ); // rw, with KLineEdit
+ testCombo->setEditable( false ); // destroys our KLineEdit
+ assert( testCombo->delegate() == 0L );
+ delete testCombo; // not needed anymore
+
+ // Qt combobox
+ QHBox* hbox = new QHBox(this);
+ hbox->setSpacing (KDialog::spacingHint());
+ QLabel* lbl = new QLabel("&QCombobox:", hbox);
+ lbl->setSizePolicy (QSizePolicy::Maximum, QSizePolicy::Preferred);
+
+ m_qc = new QComboBox(hbox, "QtReadOnlyCombo" );
+ lbl->setBuddy (m_qc);
+ QObject::connect (m_qc, SIGNAL(activated(int)), SLOT(slotActivated(int)));
+ QObject::connect (m_qc, SIGNAL(activated(const QString&)), SLOT (slotActivated(const QString&)));
+ vbox->addWidget (hbox);
+
+ // Read-only combobox
+ hbox = new QHBox(this);
+ hbox->setSpacing (KDialog::spacingHint());
+ lbl = new QLabel("&Read-Only Combo:", hbox);
+ lbl->setSizePolicy (QSizePolicy::Maximum, QSizePolicy::Preferred);
+
+ m_ro = new KComboBox(hbox, "ReadOnlyCombo" );
+ lbl->setBuddy (m_ro);
+ m_ro->setCompletionMode( KGlobalSettings::CompletionAuto );
+ QObject::connect (m_ro, SIGNAL(activated(int)), SLOT(slotActivated(int)));
+ QObject::connect (m_ro, SIGNAL(activated(const QString&)), SLOT (slotActivated(const QString&)));
+ vbox->addWidget (hbox);
+
+ // Read-write combobox
+ hbox = new QHBox(this);
+ hbox->setSpacing (KDialog::spacingHint());
+ lbl = new QLabel("&Editable Combo:", hbox);
+ lbl->setSizePolicy (QSizePolicy::Maximum, QSizePolicy::Preferred);
+
+ m_rw = new KComboBox( true, hbox, "ReadWriteCombo" );
+ lbl->setBuddy (m_rw);
+ m_rw->setDuplicatesEnabled( true );
+ m_rw->setInsertionPolicy( QComboBox::NoInsertion );
+ m_rw->setTrapReturnKey( true );
+ QObject::connect (m_rw, SIGNAL(activated(int)), SLOT(slotActivated(int)));
+ QObject::connect (m_rw, SIGNAL(activated(const QString&)), SLOT(slotActivated(const QString&)));
+ QObject::connect (m_rw, SIGNAL(returnPressed()), SLOT(slotReturnPressed()));
+ QObject::connect (m_rw, SIGNAL(returnPressed(const QString&)), SLOT(slotReturnPressed(const QString&)));
+ vbox->addWidget (hbox);
+
+ // History combobox...
+ hbox = new QHBox(this);
+ hbox->setSpacing (KDialog::spacingHint());
+ lbl = new QLabel("&History Combo:", hbox);
+ lbl->setSizePolicy (QSizePolicy::Maximum, QSizePolicy::Preferred);
+
+ m_hc = new KHistoryCombo( true, hbox, "HistoryCombo" );
+ lbl->setBuddy (m_hc);
+ m_hc->setDuplicatesEnabled( true );
+ m_hc->setInsertionPolicy( QComboBox::NoInsertion );
+ QObject::connect (m_hc, SIGNAL(activated(int)), SLOT(slotActivated(int)));
+ QObject::connect (m_hc, SIGNAL(activated(const QString&)), SLOT(slotActivated(const QString&)));
+ QObject::connect (m_hc, SIGNAL(returnPressed()), SLOT(slotReturnPressed()));
+ vbox->addWidget (hbox);
+ m_hc->setTrapReturnKey(true);
+
+ // Read-write combobox that is a replica of code in konqueror...
+ hbox = new QHBox(this);
+ hbox->setSpacing (KDialog::spacingHint());
+ lbl = new QLabel( "&Konq's Combo:", hbox);
+ lbl->setSizePolicy (QSizePolicy::Maximum, QSizePolicy::Preferred);
+
+ m_konqc = new KComboBox( true, hbox, "KonqyCombo" );
+ lbl->setBuddy (m_konqc);
+ m_konqc->setMaxCount( 10 );
+ QObject::connect (m_konqc, SIGNAL(activated(int)), SLOT(slotActivated(int)));
+ QObject::connect (m_konqc, SIGNAL(activated(const QString&)), SLOT (slotActivated(const QString&)));
+ QObject::connect (m_konqc, SIGNAL(returnPressed()), SLOT(slotReturnPressed()));
+ vbox->addWidget (hbox);
+
+ // Create an exit button
+ hbox = new QHBox (this);
+ m_btnExit = new QPushButton( "E&xit", hbox );
+ QObject::connect( m_btnExit, SIGNAL(clicked()), SLOT(quitApp()) );
+
+ // Create a disable button...
+ m_btnEnable = new QPushButton( "Disa&ble", hbox );
+ QObject::connect (m_btnEnable, SIGNAL(clicked()), SLOT(slotDisable()));
+
+ vbox->addWidget (hbox);
+
+ // Popuplate the select-only list box
+ QStringList list;
+ list << "Stone" << "Tree" << "Peables" << "Ocean" << "Sand" << "Chips"
+ << "Computer" << "Mankind";
+ list.sort();
+
+ // Setup the qcombobox
+ m_qc->insertStringList (list);
+
+ // Setup read-only combo
+ m_ro->insertStringList( list );
+ m_ro->completionObject()->setItems( list );
+
+ // Setup read-write combo
+ m_rw->insertStringList( list );
+ m_rw->completionObject()->setItems( list );
+
+ // Setup read-write combo
+ m_hc->insertStringList( list );
+ m_hc->completionObject()->setItems( list );
+
+ // Setup konq's combobox
+ KSimpleConfig historyConfig( "konq_history" );
+ historyConfig.setGroup( "Location Bar" );
+ KCompletion * s_pCompletion = new KCompletion;
+ s_pCompletion->setOrder( KCompletion::Weighted );
+ s_pCompletion->setItems( historyConfig.readListEntry( "ComboContents" ) );
+ s_pCompletion->setCompletionMode( KGlobalSettings::completionMode() );
+ m_konqc->setCompletionObject( s_pCompletion );
+
+ QPixmap pix = SmallIcon("www");
+ m_konqc->insertItem( pix, "http://www.kde.org" );
+ m_konqc->setCurrentItem( m_konqc->count()-1 );
+
+ m_timer = new QTimer (this);
+ connect (m_timer, SIGNAL (timeout()), SLOT (slotTimeout()));
+}
+
+KComboBoxTest::~KComboBoxTest()
+{
+ if (m_timer)
+ {
+ delete m_timer;
+ m_timer = 0;
+ }
+}
+
+void KComboBoxTest::slotDisable ()
+{
+ if (m_timer->isActive())
+ return;
+
+ m_btnEnable->setEnabled (!m_btnEnable->isEnabled());
+
+ m_timer->start (5000, true);
+}
+
+void KComboBoxTest::slotTimeout ()
+{
+ bool enabled = m_ro->isEnabled();
+
+ if (enabled)
+ m_btnEnable->setText ("Ena&ble");
+ else
+ m_btnEnable->setText ("Disa&ble");
+
+ m_qc->setEnabled (!enabled);
+ m_ro->setEnabled (!enabled);
+ m_rw->setEnabled (!enabled);
+ m_hc->setEnabled (!enabled);
+ m_konqc->setEnabled (!enabled);
+
+ m_btnEnable->setEnabled (!m_btnEnable->isEnabled());
+}
+
+void KComboBoxTest::slotActivated( int index )
+{
+ kdDebug() << "Activated Combo: " << sender()->name() << ", index:" << index << endl;
+}
+
+void KComboBoxTest::slotActivated (const QString& item)
+{
+ kdDebug() << "Activated Combo: " << sender()->name() << ", item: " << item << endl;
+}
+
+void KComboBoxTest::slotReturnPressed ()
+{
+ kdDebug() << "Return Pressed: " << sender()->name() << endl;
+}
+
+void KComboBoxTest::slotReturnPressed(const QString& item)
+{
+ kdDebug() << "Return Pressed, value = " << item << endl;
+}
+
+void KComboBoxTest::quitApp()
+{
+ kapp->closeAllWindows();
+}
+
+int main ( int argc, char **argv)
+{
+ KApplication a(argc, argv, "kcomboboxtest");
+ KComboBoxTest* t= new KComboBoxTest;
+ a.setMainWidget (t);
+ t->show ();
+ return a.exec();
+}
+
+#include "kcomboboxtest.moc"
diff --git a/kdeui/tests/kcomboboxtest.h b/kdeui/tests/kcomboboxtest.h
new file mode 100644
index 000000000..8c2a463b6
--- /dev/null
+++ b/kdeui/tests/kcomboboxtest.h
@@ -0,0 +1,44 @@
+#ifndef _KCOMBOBOXTEST_H
+#define _KCOMBOBOXTEST_H
+
+#include <qwidget.h>
+
+class QTimer;
+class QComboBox;
+class QPushButton;
+
+class KComboBox;
+
+class KComboBoxTest : public QWidget
+{
+ Q_OBJECT
+
+public:
+ KComboBoxTest ( QWidget *parent=0, const char *name=0 );
+ ~KComboBoxTest();
+
+private slots:
+ void quitApp();
+ void slotTimeout();
+ void slotDisable();
+ void slotReturnPressed();
+ void slotReturnPressed(const QString&);
+ void slotActivated( int );
+ void slotActivated( const QString& );
+
+protected:
+ QComboBox* m_qc;
+
+ KComboBox* m_ro;
+ KComboBox* m_rw;
+ KComboBox* m_hc;
+ KComboBox* m_konqc;
+
+
+ QPushButton* m_btnExit;
+ QPushButton* m_btnEnable;
+
+ QTimer* m_timer;
+};
+
+#endif
diff --git a/kdeui/tests/kcompletiontest.cpp b/kdeui/tests/kcompletiontest.cpp
new file mode 100644
index 000000000..e04fdfc22
--- /dev/null
+++ b/kdeui/tests/kcompletiontest.cpp
@@ -0,0 +1,198 @@
+#include <klocale.h>
+/****************************************************************************
+** Form implementation generated from reading ui file './kcompletiontest.ui'
+**
+** Created: Wed Nov 15 20:15:10 2000
+** by: The User Interface Compiler (uic)
+**
+** WARNING! All changes made in this file will be lost!
+****************************************************************************/
+#include "kcompletiontest.h"
+
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qlistbox.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qvariant.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+
+#include <kapplication.h>
+#include <klineedit.h>
+#include <kcombobox.h>
+/*
+ * Constructs a Form1 which is a child of 'parent', with the
+ * name 'name' and widget flags set to 'f'
+ */
+Form1::Form1( QWidget* parent, const char* name )
+ : QWidget( parent, name, WDestructiveClose )
+{
+ if ( !name )
+ setName( "Form1" );
+ resize( 559, 465 );
+ setCaption( "Form1" );
+ Form1Layout = new QVBoxLayout( this );
+ Form1Layout->setSpacing( 6 );
+ Form1Layout->setMargin( 11 );
+
+ GroupBox1 = new QGroupBox( this, "GroupBox1" );
+ GroupBox1->setTitle( "Completion Test" );
+ GroupBox1->setColumnLayout(0, Qt::Vertical );
+ GroupBox1->layout()->setSpacing( 0 );
+ GroupBox1->layout()->setMargin( 0 );
+ GroupBox1Layout = new QVBoxLayout( GroupBox1->layout() );
+ GroupBox1Layout->setAlignment( Qt::AlignTop );
+ GroupBox1Layout->setSpacing( 6 );
+ GroupBox1Layout->setMargin( 11 );
+
+ Layout9 = new QVBoxLayout;
+ Layout9->setSpacing( 6 );
+ Layout9->setMargin( 0 );
+
+ Layout1 = new QHBoxLayout;
+ Layout1->setSpacing( 6 );
+ Layout1->setMargin( 0 );
+
+ TextLabel1 = new QLabel( GroupBox1, "TextLabel1" );
+ TextLabel1->setText( "Completion" );
+ Layout1->addWidget( TextLabel1 );
+
+ edit = new KLineEdit( GroupBox1, "edit" );
+ Layout1->addWidget( edit );
+ Layout9->addLayout( Layout1 );
+ edit->completionObject()->setItems( defaultItems() );
+ edit->completionObject()->setIgnoreCase( true );
+ edit->setFocus();
+ QToolTip::add( edit, "right-click to change completion mode" );
+
+ Layout2 = new QHBoxLayout;
+ Layout2->setSpacing( 6 );
+ Layout2->setMargin( 0 );
+
+ combo = new KHistoryCombo( GroupBox1, "history combo" );
+ combo->setCompletionObject( edit->completionObject() );
+ // combo->setMaxCount( 5 );
+ combo->setHistoryItems( defaultItems(), true );
+ connect( combo, SIGNAL( activated( const QString& )),
+ combo, SLOT( addToHistory( const QString& )));
+ QToolTip::add( combo, "KHistoryCombo" );
+ Layout2->addWidget( combo );
+
+ LineEdit1 = new KLineEdit( GroupBox1, "LineEdit1" );
+ Layout2->addWidget( LineEdit1 );
+
+ PushButton1 = new QPushButton( GroupBox1, "PushButton1" );
+ PushButton1->setText( "Add" );
+ connect( PushButton1, SIGNAL( clicked() ), SLOT( slotAdd() ));
+ Layout2->addWidget( PushButton1 );
+ Layout9->addLayout( Layout2 );
+
+ Layout3 = new QHBoxLayout;
+ Layout3->setSpacing( 6 );
+ Layout3->setMargin( 0 );
+ QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );
+ Layout3->addItem( spacer );
+
+ PushButton1_4 = new QPushButton( GroupBox1, "PushButton1_4" );
+ PushButton1_4->setText( "Remove" );
+ connect( PushButton1_4, SIGNAL( clicked() ), SLOT( slotRemove() ));
+ Layout3->addWidget( PushButton1_4 );
+ Layout9->addLayout( Layout3 );
+
+ Layout8 = new QHBoxLayout;
+ Layout8->setSpacing( 6 );
+ Layout8->setMargin( 0 );
+
+ ListBox1 = new QListBox( GroupBox1, "ListBox1" );
+ Layout8->addWidget( ListBox1 );
+ connect( ListBox1, SIGNAL( highlighted( const QString& )),
+ SLOT( slotHighlighted( const QString& )));
+ QToolTip::add( ListBox1, "Contains the contents of the completion object.\n:x is the weighting, i.e. how often an item has been inserted");
+
+ Layout7 = new QVBoxLayout;
+ Layout7->setSpacing( 6 );
+ Layout7->setMargin( 0 );
+
+ PushButton1_3 = new QPushButton( GroupBox1, "PushButton1_3" );
+ PushButton1_3->setText( "Completion items" );
+ connect( PushButton1_3, SIGNAL( clicked() ), SLOT( slotList() ));
+ Layout7->addWidget( PushButton1_3 );
+
+ PushButton1_2 = new QPushButton( GroupBox1, "PushButton1_2" );
+ PushButton1_2->setText( "Clear" );
+ connect( PushButton1_2, SIGNAL( clicked() ),
+ edit->completionObject(), SLOT( clear() ));
+ Layout7->addWidget( PushButton1_2 );
+ Layout8->addLayout( Layout7 );
+ Layout9->addLayout( Layout8 );
+ GroupBox1Layout->addLayout( Layout9 );
+ Form1Layout->addWidget( GroupBox1 );
+
+ slotList();
+}
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+Form1::~Form1()
+{
+ // no need to delete child widgets, Qt does it all for us
+}
+
+void Form1::slotAdd()
+{
+ qDebug("** adding: %s", LineEdit1->text().latin1() );
+ edit->completionObject()->addItem( LineEdit1->text() );
+
+ QStringList matches = edit->completionObject()->allMatches("S");
+ QStringList::ConstIterator it = matches.begin();
+ for ( ; it != matches.end(); ++it )
+ qDebug("-- %s", (*it).latin1());
+}
+
+void Form1::slotRemove()
+{
+ edit->completionObject()->removeItem( LineEdit1->text() );
+}
+
+void Form1::slotList()
+{
+ ListBox1->clear();
+ QStringList items = edit->completionObject()->items();
+ ListBox1->insertStringList( items );
+}
+
+void Form1::slotHighlighted( const QString& text )
+{
+ // remove any "weighting"
+ int index = text.findRev( ':' );
+ if ( index > 0 )
+ LineEdit1->setText( text.left( index ) );
+ else
+ LineEdit1->setText( text );
+}
+
+
+QStringList Form1::defaultItems() const
+{
+ QStringList items;
+ items << "Super" << "Sushi" << "Samson" << "Sucks" << "Sumo" << "Schumi";
+ items << "Slashdot" << "sUpEr" << "SUshi" << "sUshi" << "sUShi";
+ items << "sushI" << "SushI";
+ return items;
+}
+
+
+int main(int argc, char **argv )
+{
+ KApplication app( argc, argv, "kcompletiontest" );
+
+ Form1 *form = new Form1();
+ form->show();
+
+ return app.exec();
+}
+
+
+#include "kcompletiontest.moc"
diff --git a/kdeui/tests/kcompletiontest.h b/kdeui/tests/kcompletiontest.h
new file mode 100644
index 000000000..e2f5a2bee
--- /dev/null
+++ b/kdeui/tests/kcompletiontest.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+** Form interface generated from reading ui file './kcompletiontest.ui'
+**
+** Created: Wed Nov 15 20:12:56 2000
+** by: The User Interface Compiler (uic)
+**
+** WARNING! All changes made in this file will be lost!
+****************************************************************************/
+#ifndef FORM1_H
+#define FORM1_H
+
+#include <qstringlist.h>
+#include <qvariant.h>
+#include <qwidget.h>
+class QVBoxLayout;
+class QHBoxLayout;
+class QGridLayout;
+class QGroupBox;
+class QLabel;
+class QListBox;
+class QListBoxItem;
+class QPushButton;
+
+class KHistoryCombo;
+class KLineEdit;
+
+
+class Form1 : public QWidget
+{
+ Q_OBJECT
+
+public:
+ Form1( QWidget* parent = 0, const char* name = 0 );
+ ~Form1();
+
+ QGroupBox* GroupBox1;
+ QLabel* TextLabel1;
+ KLineEdit* LineEdit1;
+ QPushButton* PushButton1;
+ QPushButton* PushButton1_4;
+ QListBox* ListBox1;
+ QPushButton* PushButton1_3;
+ QPushButton* PushButton1_2;
+
+ KLineEdit* edit;
+ KHistoryCombo *combo;
+
+protected slots:
+ void slotList();
+ void slotAdd();
+ void slotRemove();
+ void slotHighlighted( const QString& );
+
+protected:
+ QStringList defaultItems() const;
+
+ QVBoxLayout* Form1Layout;
+ QVBoxLayout* GroupBox1Layout;
+ QVBoxLayout* Layout9;
+ QHBoxLayout* Layout1;
+ QHBoxLayout* Layout2;
+ QHBoxLayout* Layout3;
+ QHBoxLayout* Layout8;
+ QVBoxLayout* Layout7;
+};
+
+#endif // FORM1_H
diff --git a/kdeui/tests/kdatepicktest.cpp b/kdeui/tests/kdatepicktest.cpp
new file mode 100644
index 000000000..eeef5945f
--- /dev/null
+++ b/kdeui/tests/kdatepicktest.cpp
@@ -0,0 +1,16 @@
+#include "kdatepicker.h"
+#include <qlineedit.h>
+#include <kapplication.h>
+#include <klocale.h>
+
+int main(int argc, char** argv)
+{
+ KLocale::setMainCatalogue("kdelibs");
+ KApplication app(argc, argv, "KDatePickertest");
+ KDatePicker picker;
+ app.setMainWidget(&picker);
+ picker.show();
+ // picker.setEnabled(false);
+ return app.exec();
+}
+
diff --git a/kdeui/tests/kdatetimewidgettest.cpp b/kdeui/tests/kdatetimewidgettest.cpp
new file mode 100644
index 000000000..fd3680be0
--- /dev/null
+++ b/kdeui/tests/kdatetimewidgettest.cpp
@@ -0,0 +1,14 @@
+#include "kdatetimewidget.h"
+#include <kapplication.h>
+#include <klocale.h>
+
+int main(int argc, char** argv)
+{
+ KLocale::setMainCatalogue("kdelibs");
+ KApplication app(argc, argv, "KDateTimeWidgettest");
+ KDateTimeWidget dateTimeWidget;
+ app.setMainWidget(&dateTimeWidget);
+ dateTimeWidget.show();
+ // dateTimeWidget.setEnabled(false);
+ return app.exec();
+}
diff --git a/kdeui/tests/kdatewidgettest.cpp b/kdeui/tests/kdatewidgettest.cpp
new file mode 100644
index 000000000..d58037960
--- /dev/null
+++ b/kdeui/tests/kdatewidgettest.cpp
@@ -0,0 +1,16 @@
+#include "kdatewidget.h"
+#include <qlineedit.h>
+#include <kapplication.h>
+#include <klocale.h>
+
+int main(int argc, char** argv)
+{
+ KLocale::setMainCatalogue("kdelibs");
+ KApplication app(argc, argv, "KDateWidgettest");
+ KDateWidget dateWidget;
+ app.setMainWidget(&dateWidget);
+ dateWidget.show();
+ // dateWidget.setEnabled(false);
+ return app.exec();
+}
+
diff --git a/kdeui/tests/kdesattest.cpp b/kdeui/tests/kdesattest.cpp
new file mode 100644
index 000000000..803e2e0ee
--- /dev/null
+++ b/kdeui/tests/kdesattest.cpp
@@ -0,0 +1,65 @@
+#include "kdesattest.h"
+#include <kapplication.h>
+#include <kimageeffect.h>
+#include <qpainter.h>
+#include <qdatetime.h>
+#include <qstring.h>
+
+int cols = 3, rows = 3; // how many
+
+KDesatWidget::KDesatWidget(QWidget *parent, const char *name)
+ :QWidget(parent, name)
+{
+
+ image = QImage("testimage.png");
+ slide = new KDoubleNumInput(700, this, "desat");
+ slide->setRange(0, 1, 0.001);
+ slide->setLabel("Desaturate: ", AlignVCenter | AlignLeft);
+ connect(slide,SIGNAL(valueChanged(double)), this, SLOT(change(double)));
+
+ resize(image.width()*2, image.height() + slide->height());
+ slide->setGeometry(0, image.height(), image.width()*2, slide->height());
+}
+
+void KDesatWidget::change(double) {
+ desat_value = slide->value();
+ repaint(false);
+}
+
+void KDesatWidget::paintEvent(QPaintEvent */*ev*/)
+{
+ QTime time;
+ int it, ft;
+ QString say;
+
+ QPainter p(this);
+ p.setPen(Qt::black);
+
+ // original image
+ time.start();
+ it = time.elapsed();
+ image = QImage("testimage.png");
+ p.drawImage(0, 0, image);
+ ft = time.elapsed();
+ say.setNum( ft - it); say += " ms, Vertical";
+ p.drawText(5 , 15, say);
+
+ // desaturated image
+ it = time.elapsed();
+ image = KImageEffect::desaturate(image, desat_value);
+ p.drawImage(image.width(), 0, image);
+ ft = time.elapsed();
+ say.setNum( ft - it); say += " ms, Horizontal";
+ p.drawText(15+image.width() , 15, say);
+}
+
+int main(int argc, char **argv)
+{
+ KApplication *app = new KApplication(argc, argv, "KDesatTest");
+ KDesatWidget w;
+ app->setMainWidget(&w);
+ w.show();
+ return(app->exec());
+}
+
+#include "kdesattest.moc"
diff --git a/kdeui/tests/kdesattest.h b/kdeui/tests/kdesattest.h
new file mode 100644
index 000000000..71a51c0be
--- /dev/null
+++ b/kdeui/tests/kdesattest.h
@@ -0,0 +1,31 @@
+//
+// Simple little hack to show off blending effects.
+//
+// (C) KDE Artistic Cristian Tibirna <tibirna@kde.org>
+//
+
+#ifndef __KBLEND_TEST_H
+#define __KBLEND_TEST_H
+
+#include <qwidget.h>
+#include <qimage.h>
+#include <knuminput.h>
+
+class KDesatWidget : public QWidget
+{
+Q_OBJECT
+public:
+ KDesatWidget(QWidget *parent=0, const char *name=0);
+
+public slots:
+ void change(double);
+
+protected:
+ void paintEvent(QPaintEvent *ev);
+private:
+ float desat_value;
+ QImage image;
+ KDoubleNumInput *slide;
+};
+
+#endif
diff --git a/kdeui/tests/kdialogbasetest.cpp b/kdeui/tests/kdialogbasetest.cpp
new file mode 100644
index 000000000..998e10d02
--- /dev/null
+++ b/kdeui/tests/kdialogbasetest.cpp
@@ -0,0 +1,77 @@
+#include <kapplication.h>
+#include <kdialogbase.h>
+
+#include <qstring.h>
+#include <qtextview.h>
+
+int main(int argc, char** argv)
+{
+ KApplication app(argc, argv, "DialogBaseTest");
+ // -----
+ QString text= // the explanation shown by the example dialog
+ "<center><h1>DialogBase Example</h1></center><hr><br>"
+ "This example shows the usage of the <i>DialogBase</i> class. "
+ "<i>DialogBase</i> is the KDE user interface class used to create "
+ "dialogs with unique layout without having to define an own dialog "
+ "style for your application. <br>"
+ "It provides three standard buttons (<b>OK</b>, <b>Apply</b>, and "
+ "<b>Cancel</b>) that are needed in most dialogs. Each one may be "
+ "hidden, enabled or disabled, and tooltips and quickhelp texts might be"
+ " added. And you do not need to bother about geometry management, this "
+ "is all done automatically.<br>"
+ "To polish your user interface even further, you might want to add "
+ "textures to the inner and the outer frame of the dialog (the frame is "
+ "created by the dialog object). This is done "
+ "using the <tt>setMainFrameTile</tt> and the <tt>setBaseFrameTile</tt> "
+ "methods. These tiles are added application-wide, so each dialog "
+ "of you application uses the same tiles. This is a tribute to a "
+ "comprehensable user interface.<br>"
+ "The class supports the creation of dialogs without being forced "
+ "to derive an own class for it, but you may derive your own class "
+ "for a better code structure.<br>"
+ "If you wrote a help chapter explaining what your dialog does, you "
+ "should add a link to it to the dialog using <tt>setHelp</tt>. You do "
+ "not have to take care about launching the help viewer, just set the "
+ "help file and topic and of course copy it to your documentation "
+ "directory during the program installation.";
+ /* Create the dialog object. DialogBase is derived from QDialog, but
+ you do not need to derive it to create a nice-looking dialog. Mostly,
+ you already have a widget class representing the core of your dialog,
+ and you only need to add a frame around it and the default buttons.
+
+ If you want to derive it, you still can, moving all code shown here
+ inside of your new class. */
+ KDialogBase dialog;
+ /* Set a help chapter. If you do not set one, the link is not shown, and the
+ upper part of the frame shrinks as much as possible. The help window "
+ "will of course only pop up if you correctly installed kdebase. */
+ // I disabled it, as khcclient did not run for me.
+ // dialog.setHelp("kdehelp/intro.html", "", "");
+ /* This QTextView is intended to be the main widget of our dialog. The
+ main widget is placed inside the dialogs frame, with the buttons below
+ it. You do not have to take care about the size handling, but it is a
+ good idea to set the main wigdets minimum size, since the sizes Qt and
+ the DialogBase class guess are sometimes ugly.
+
+ It is important that your main widget is created with the dialog object
+ as its parent! */
+ QTextView view(text, QString::null, &dialog);
+ //view.setMinimumSize(400, view.heightForWidth(400)+20);
+ view.setMinimumSize( 250, 300 );
+ dialog.setMainWidget(&view);
+ /* After finishing the setup of your main widget, the dialog needs to be
+ adjusted. It is not done automatically, since the layout of the main
+ widget may change before the dialog is shown. Additionally, setting a
+ help chapter may cause a need for adjustment since it modifies the height
+ of the upper frame. */
+ dialog.resize(dialog.minimumSize());
+ /* The dialog object is used just as any other QDialog: */
+ if(dialog.exec())
+ {
+ qDebug("Accepted.");
+ } else {
+ qDebug("Rejected.");
+ }
+ return 0;
+}
+
diff --git a/kdeui/tests/kdocktest.cpp b/kdeui/tests/kdocktest.cpp
new file mode 100644
index 000000000..c6df63ddb
--- /dev/null
+++ b/kdeui/tests/kdocktest.cpp
@@ -0,0 +1,65 @@
+#include "kdocktest.h"
+
+#include <kapplication.h>
+#include <kiconloader.h>
+
+#include <qwidget.h>
+#include <qstring.h>
+
+DockTest::DockTest( QWidget* parent )
+ : KDockArea( parent )
+{
+ m_blueDock = createDockWidget( "Blue Widget", SmallIcon("mail") );
+ //m_blueDock->setDetachable( false );
+ m_blueDock->setEnableDocking( KDockWidget::DockFullSite );
+ KDockWidgetHeader *header = new KDockWidgetHeader( m_blueDock, "Blue Header" );
+ header->forceCloseButtonHidden();
+ m_blueDock->setHeader( header );
+ m_blueDock->setCaption( "Blue" );
+ m_blueDock->setGeometry( 50, 50, 100, 100 );
+ QWidget *l = new QWidget( m_blueDock );
+ l->setBackgroundColor( Qt::blue );
+ l->setMinimumSize( 100,100 );
+ m_blueDock->setWidget( l );
+
+ setMainDockWidget( m_blueDock );
+
+ m_redDock = createDockWidget( "Red Widget", SmallIcon("news") );
+ m_redDock->setEnableDocking( KDockWidget::DockFullSite );
+ //m_redDock->setDetachable( false );
+ header = new KDockWidgetHeader( m_redDock, "Red kHeader" );
+ m_redDock->setHeader( header );
+ m_redDock->setCaption( "Red" );
+ m_redDock->setGeometry( 50, 50, 100, 100 );
+ l = new QWidget( m_redDock );
+ l->setBackgroundColor( Qt::red );
+ l->setMinimumSize( 100,100 );
+ m_redDock->setWidget( l );
+ m_redDock->manualDock( m_blueDock, KDockWidget::DockLeft, 3000 );
+
+ m_yellowDock = createDockWidget( "Yellow Widget", SmallIcon("web") );
+ m_yellowDock->setEnableDocking( KDockWidget::DockFullSite );
+ //m_yellowDock->setDetachable( false );
+// header = new KDockWidgetHeader( m_yellowDock, "Yellow Header" );
+ // m_yellowDock->setHeader( header );
+ m_yellowDock->setCaption( "Yellow" );
+ m_yellowDock->setGeometry( 50, 50, 100, 100 );
+ l = new QWidget( m_yellowDock );
+ l->setBackgroundColor( Qt::yellow );
+ l->setMinimumSize( 100,100 );
+ m_yellowDock->setWidget( l );
+ m_yellowDock->manualDock( m_blueDock, KDockWidget::DockTop, 5000 );
+}
+
+int
+main( int argc, char** argv )
+{
+ KApplication a( argc,argv, "docktest" );
+ DockTest* ap = new DockTest();
+ ap->setCaption("DockWidget demo");
+ a.setMainWidget( ap );
+ ap->show();
+ return a.exec();
+}
+
+#include "kdocktest.moc"
diff --git a/kdeui/tests/kdocktest.h b/kdeui/tests/kdocktest.h
new file mode 100644
index 000000000..906e3bd22
--- /dev/null
+++ b/kdeui/tests/kdocktest.h
@@ -0,0 +1,19 @@
+#ifndef KDOCKTEST_H
+#define KDOCKTEST_H
+
+#include <kdockwidget.h>
+
+class QWidget;
+class DockTest : public KDockArea
+{
+ Q_OBJECT
+public:
+ DockTest( QWidget* parent=0 );
+
+private:
+ KDockWidget* m_blueDock;
+ KDockWidget* m_redDock;
+ KDockWidget* m_yellowDock;
+};
+
+#endif
diff --git a/kdeui/tests/kdockwidgetdemo.cpp b/kdeui/tests/kdockwidgetdemo.cpp
new file mode 100644
index 000000000..e0ff60897
--- /dev/null
+++ b/kdeui/tests/kdockwidgetdemo.cpp
@@ -0,0 +1,796 @@
+#include "kdockwidgetdemo.h"
+
+#include <qheader.h>
+#include <qtoolbutton.h>
+#include <qtooltip.h>
+#include <qtextview.h>
+#include <qfileinfo.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qhbox.h>
+#include <qlabel.h>
+#include <qmultilineedit.h>
+#include <qevent.h>
+#include <qpopupmenu.h>
+#include <qpushbutton.h>
+#include <qpoint.h>
+#include <qmessagebox.h>
+#include <qmime.h>
+#include <qstrlist.h>
+#include <qpainter.h>
+
+#include <kconfig.h>
+#include <kapplication.h>
+//#include <kimgio.h>
+#include <stdlib.h>
+
+static const char *dir_tree_xpm[] = {
+"16 16 8 1",
+" c Gray0",
+". c #000080",
+"X c Cyan",
+"o c #808000",
+"O c Yellow",
+"+ c #808080",
+"@ c None",
+"# c #c1c1c1",
+"@@@@@@@@@@@@@@@@",
+"@@@+++++@@@@@@@@",
+"@@+@O@O@+@@@@@@@",
+"@+@O@O@O@++++++@",
+"@+@@@@@@@@@@@@o ",
+"@+@O@++ +O@O@Oo ",
+"@+@@+@X@ +O@O@o ",
+"@+@+@X@X@ +O@Oo ",
+"@+@+X@X@X o@O@o ",
+"@+@+@X@X@ oO@Oo ",
+"@+@@+@X@ +ooO@o ",
+"@+@O@+ +@..oOo ",
+"@+ooooooo.X..oo ",
+"@@ .X.. @",
+"@@@@@@@@@@@.X.. ",
+"@@@@@@@@@@@@.X. "
+};
+
+static const char *preview_xpm[] = {
+"16 16 6 1",
+" c Gray0",
+". c #000080",
+"X c Yellow",
+"o c #808080",
+"O c None",
+"+ c Gray100",
+"OOOOOOOOOOOOOOOO",
+"OOo oOOOOOOO",
+"Oo oooo OOOOOO",
+"O OOOOoo oOOOOO",
+"O OOOO++oo OOOOO",
+"O OOOO++Oo OOOOO",
+"O O+OOOOOo OOOOO",
+"O OO+OOOOo OOOOO",
+"OooOO+OOo OOOOO",
+"OO oOOOo + OOOO",
+"OOOo .X+ OOO",
+"OOOOOOOOO .X+ OO",
+"OOOOOOOOOO .X+ O",
+"OOOOOOOOOOO .X O",
+"OOOOOOOOOOOO OO",
+"OOOOOOOOOOOOOOOO"
+};
+
+SFileDialog::SFileDialog( QString initially, const QStringList& filter, const char* name )
+:QDialog(0L,name,true)
+{
+ KConfig* config = kapp->config();
+ config->setGroup( QString::fromLatin1("SFileDialogData:") + name );
+ if ( initially.isNull() ){
+ initially = config->readPathEntry( "InitiallyDir", QDir::currentDirPath() );
+ }
+
+ QStringList bookmark;
+ bookmark = config->readListEntry( "Bookmarks" );
+
+ dockManager = new KDockManager(this);
+
+ d_dirView = new KDockWidget( dockManager, "Dock_DirView", QPixmap(dir_tree_xpm) );
+ d_dirView->setCaption("Tree");
+
+ dirView = new DirectoryView( d_dirView, 0 );
+ dirView->addColumn( "" );
+ dirView->header()->hide();
+ d_dirView->setWidget( dirView );
+
+ Directory* root = new Directory( dirView, "/" );
+ root->setOpen(true);
+
+ d_preview = new KDockWidget( dockManager, "Dock_Preview", QPixmap(preview_xpm) );
+ d_preview->setCaption("Preview");
+ preview = new Preview( d_preview );
+ d_preview->setWidget( preview );
+
+ d_fd = new KDockWidget( dockManager, "Dock_QFileDialog", QPixmap(), this );
+ fd = new CustomFileDialog( d_fd );
+ fd->setDir( initially );
+ fd->setFilters( filter );
+ fd->setBookmark( bookmark );
+ fd->reparent(d_fd, QPoint(0,0));
+ d_fd->setWidget( fd );
+
+ connect( dirView, SIGNAL( folderSelected( const QString & ) ), fd, SLOT( setDir2( const QString & ) ) );
+ connect( fd, SIGNAL( dirEntered( const QString & ) ), dirView, SLOT( setDir( const QString & ) ) );
+
+ d_fd->setDockSite( KDockWidget::DockTop|KDockWidget::DockLeft|KDockWidget::DockRight|KDockWidget::DockBottom );
+ d_fd->setEnableDocking(KDockWidget::DockNone);
+
+ d_dirView->setEnableDocking(KDockWidget::DockTop|KDockWidget::DockLeft|KDockWidget::DockRight|KDockWidget::DockBottom|KDockWidget::DockCenter);
+ d_preview->setEnableDocking(KDockWidget::DockTop|KDockWidget::DockLeft|KDockWidget::DockRight|KDockWidget::DockBottom|KDockWidget::DockCenter);
+
+ d_dirView->manualDock( d_fd, KDockWidget::DockLeft, 20 );
+ d_preview->manualDock( d_fd, KDockWidget::DockBottom, 70 );
+
+ connect(fd, SIGNAL(fileHighlighted(const QString&)), preview, SLOT(showPreview(const QString&)));
+ connect(fd, SIGNAL(signalDone(int)), this, SLOT(done(int)));
+
+ connect(fd, SIGNAL(dirEntered(const QString&)), this, SLOT(changeDir(const QString&)));
+ connect(dirView, SIGNAL(folderSelected(const QString&)), this, SLOT(changeDir(const QString&)));
+
+ b_tree = new QToolButton( fd );
+ QToolTip::add( b_tree, "Show/Hide Tree" );
+ b_tree->setPixmap( QPixmap( dir_tree_xpm ) );
+ connect( b_tree, SIGNAL(clicked()), d_dirView, SLOT(changeHideShowState()) );
+ b_tree->setToggleButton(true);
+ b_tree->setOn(true);
+ fd->addToolButton( b_tree, true );
+
+ b_preview = new QToolButton( fd );
+ QToolTip::add( b_preview, "Show/Hide Preview" );
+ b_preview->setPixmap( QPixmap( preview_xpm ) );
+ connect( b_preview, SIGNAL(clicked()), d_preview, SLOT(changeHideShowState()) );
+ b_preview->setToggleButton(true);
+ b_preview->setOn(true);
+ fd->addToolButton( b_preview );
+
+ connect( dockManager, SIGNAL(change()), this, SLOT(dockChange()));
+ connect( dockManager, SIGNAL(setDockDefaultPos(KDockWidget*)), this, SLOT(setDockDefaultPos(KDockWidget*)));
+ setCaption("Open File");
+ resize(550,450);
+ qDebug("read config");
+ dockManager->readConfig( 0L , name );
+}
+
+void SFileDialog::dockChange()
+{
+ b_preview->setOn( d_preview->isVisibleToTLW() );
+ b_tree->setOn( d_dirView->isVisibleToTLW() );
+}
+
+SFileDialog::~SFileDialog()
+{
+ KConfig* config = kapp->config();
+ config->setGroup( QString("SFileDialogData:") + name() );
+ config->writeEntry( "Bookmarks", fd->getBookmark() );
+
+ qDebug("write config");
+ dockManager->writeConfig( 0L , name() );
+}
+
+void SFileDialog::setDockDefaultPos( KDockWidget* d )
+{
+ if ( d == d_dirView ){
+ d_dirView->manualDock( d_fd, KDockWidget::DockLeft, 20 );
+ }
+
+ if ( d == d_preview ){
+ d_preview->manualDock( d_fd, KDockWidget::DockBottom, 70 );
+ }
+}
+
+void SFileDialog::changeDir( const QString& f )
+{
+ if ( !f.isEmpty() ){
+ KConfig* config = kapp->config();
+ config->setGroup( QString("SFileDialogData:") + name() );
+ config->writePathEntry( "InitiallyDir", f );
+ }
+}
+
+QString SFileDialog::getOpenFileName( QString initially,
+ const QStringList& filter,
+ const QString caption, const char* name )
+{
+ SFileDialog* fd = new SFileDialog( initially, filter, name );
+ if ( !caption.isNull() ) fd->setCaption( caption );
+ QString result = ( fd->exec() == QDialog::Accepted ) ? fd->fd->selectedFile():QString::null;
+ delete fd;
+
+ return result;
+}
+
+QStringList SFileDialog::getOpenFileNames( QString initially,
+ const QStringList& filter,
+ const QString caption, const char* name )
+{
+ SFileDialog* fd = new SFileDialog( initially, filter, name );
+ if ( !caption.isNull() ) fd->setCaption( caption );
+
+ fd->fd->setMode( QFileDialog::ExistingFiles );
+ fd->d_preview->undock();
+ fd->b_preview->hide();
+
+ fd->exec();
+ QStringList result = fd->fd->selectedFiles();
+ delete fd;
+
+ return result;
+}
+
+void SFileDialog::showEvent( QShowEvent *e )
+{
+ QDialog::showEvent( e );
+ dirView->setDir( fd->dirPath() );
+}
+
+/******************************************************************************************************/
+PixmapView::PixmapView( QWidget *parent )
+:QScrollView( parent )
+{
+// kimgioRegister();
+ viewport()->setBackgroundMode( PaletteBase );
+}
+
+void PixmapView::setPixmap( const QPixmap &pix )
+{
+ pixmap = pix;
+ resizeContents( pixmap.size().width(), pixmap.size().height() );
+ viewport()->repaint( true );
+}
+
+void PixmapView::drawContents( QPainter *p, int, int, int, int )
+{
+ p->drawPixmap( 0, 0, pixmap );
+}
+
+Preview::Preview( QWidget *parent )
+:QWidgetStack( parent )
+{
+ normalText = new QMultiLineEdit( this );
+ normalText->setReadOnly( true );
+ html = new QTextView( this );
+ pixmap = new PixmapView( this );
+ raiseWidget( normalText );
+}
+
+void Preview::showPreview( const QString &str )
+{
+ QUrl u(str);
+ if ( u.isLocalFile() ){
+ QString path = u.path();
+ QFileInfo fi( path );
+ if ( fi.isFile() && (int)fi.size() > 400 * 1024 ) {
+ normalText->setText( tr( "The File\n%1\nis too large, so I don't show it!" ).arg( path ) );
+ raiseWidget( normalText );
+ return;
+ }
+
+ QPixmap pix( path );
+ if ( pix.isNull() ) {
+ if ( fi.isFile() ) {
+ QFile f( path );
+ if ( f.open( IO_ReadOnly ) ) {
+ QTextStream ts( &f );
+ QString text = ts.read();
+ f.close();
+ if ( fi.extension().lower().contains( "htm" ) ) {
+ QString url = html->mimeSourceFactory()->makeAbsolute( path, html->context() );
+ html->setText( text, url );
+ raiseWidget( html );
+ return;
+ } else {
+ normalText->setText( text );
+ raiseWidget( normalText );
+ return;
+ }
+ }
+ }
+ normalText->setText( QString::null );
+ raiseWidget( normalText );
+ } else {
+ pixmap->setPixmap( pix );
+ raiseWidget( pixmap );
+ }
+ } else {
+ normalText->setText( "I only show local files!" );
+ raiseWidget( normalText );
+ }
+}
+
+// ****************************************************************************************************
+static const char* homepage_xpm[] = {
+"24 24 9 1",
+" c #262660",
+". c #383666",
+"X c #62639c",
+"o c #7e86a5",
+"O c #a6a7dd",
+"+ c #bbbaed",
+"@ c #c4c4f2",
+"# c #f8f9f9",
+"$ c None",
+"$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$o.X$$$$$",
+"$$$$$$$$$$oOOOO$O.X$$$$$",
+"$$$$$$$$$$oXXXX+O.X$$$$$",
+"$$$$$$$$$X#XXXXXO.X$$$$$",
+"$$$$$$$$X #XXXXO.X$$$$$",
+"$$$$$$$X XO #XXXO.X$$$$$",
+"$$$$$$X XOOO #XXX.XX$$$$",
+"$$$$$X XOOOOO #XXXXXX$$$",
+"$$$$X XOOOOOOO #XXXXXX$$",
+"$$$X XOOOOOOOOO #XXXXXX$",
+"$$X XOOOOOOOOOOO #.....$",
+"$$$$$OOOOXXXXOOOOX...$$$",
+"$$$$$OOOOXXXXOOOOX...$$$",
+"$$$$$OOOOXXXXOOOOX..o$$$",
+"$$$$$OOOOXXXXOOOOX.oo$$$",
+"$$$$$OOOOXXXXOOOOXXoo$$$",
+"$$$$$OOOOXXXXOOOOXooo$$$",
+"$$$ooOOOOXXXXOOOOXoooo$$",
+"$ooooXXXXXXXXXXXXXooooo$",
+"$ooooooooooooooooooooooo",
+"$$$$$$$$$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$$$$$$$$$"
+};
+
+static const char* folder_trash[] = {
+"16 16 10 1",
+" c Gray0",
+". c #222222",
+"X c #333366",
+"o c #6666cc",
+"O c Magenta",
+"+ c #808080",
+"@ c #9999ff",
+"# c #c0c0c0",
+"$ c Gray100",
+"% c None",
+"%%%%%%oo%%%%%%%%",
+"%%%%%o$$o%%%%%%%",
+"%%%%o$$$$o%%%%%%",
+"%%%o$+$+$$o o%%%",
+"%%oo$$+$+$$o .%%",
+"%%.oo$$+$+$$o.%%",
+"%% Xoo$$+$$o +%%",
+"%%o Xoo$$oo o%%",
+"%%%X.XX +X%%%",
+"%%%o@X+X#X+X+%%%",
+"%%%+.$X#X+X %%%%",
+"%%%%.o$o#X+X%%%%",
+"%%%%.X@$X+ +%%%%",
+"%%%%+Xo.#. %%%%%",
+"%%%%%.Xo. o%%%%%",
+"%%%%%+. %%%%%%"
+};
+
+static const char* globalbookmark_xpm[]={
+"12 16 3 1",
+". c None",
+"a c #000000",
+"# c #008080",
+"............",
+"............",
+"........##..",
+".......#####",
+"......#####a",
+".....#####a.",
+"....#####a..",
+"...#####a...",
+"..#####a....",
+".#####a.....",
+"aaa##a......",
+"...#a.......",
+"...a........",
+"............",
+"............",
+"............"};
+
+CustomFileDialog::CustomFileDialog( QWidget* parent )
+: QFileDialog( parent, 0, false )
+{
+ QToolButton *p = new QToolButton( this );
+
+ p->setPixmap( QPixmap( globalbookmark_xpm ) );
+ QToolTip::add( p, tr( "Bookmarks" ) );
+
+ bookmarkMenu = new QPopupMenu( this );
+ connect( bookmarkMenu, SIGNAL( activated( int ) ), this, SLOT( bookmarkChosen( int ) ) );
+ addId = bookmarkMenu->insertItem( "Add bookmark" );
+ clearId = bookmarkMenu->insertItem( QPixmap(folder_trash), "Clear bookmarks" );
+ bookmarkMenu->insertSeparator();
+
+ p->setPopup( bookmarkMenu );
+ p->setPopupDelay(0);
+ addToolButton( p, true );
+
+ QToolButton *b = new QToolButton( this );
+ QToolTip::add( b, tr( "Go Home!" ) );
+
+ b->setPixmap( QPixmap( homepage_xpm ) );
+ connect( b, SIGNAL( clicked() ), this, SLOT( goHome() ) );
+
+ addToolButton( b );
+}
+
+
+void CustomFileDialog::setBookmark( QStringList &s )
+{
+ QStringList::Iterator it = s.begin();
+ for ( ; it != s.end(); ++it ){
+ bookmarkList << (*it);
+
+ const char* book_pix[]={
+ "12 16 3 1",
+ ". c None",
+ "a c #000000",
+ "# c #008080",
+ "............",
+ "............",
+ "........##..",
+ ".......#####",
+ "......#####a",
+ ".....#####a.",
+ "....#####a..",
+ "...#####a...",
+ "..#####a....",
+ ".#####a.....",
+ "aaa##a......",
+ "...#a.......",
+ "...a........",
+ "............",
+ "............",
+ "............"};
+ bookmarkMenu->insertItem( QIconSet( book_pix ), (*it) );
+ }
+}
+
+CustomFileDialog::~CustomFileDialog()
+{
+}
+
+void CustomFileDialog::setDir2( const QString &s )
+{
+ blockSignals( true );
+ setDir( s );
+ blockSignals( false );
+}
+
+void CustomFileDialog::bookmarkChosen( int i )
+{
+ if ( i == clearId ){
+ bookmarkList.clear();
+ bookmarkMenu->clear();
+ addId = bookmarkMenu->insertItem( "Add bookmark" );
+ clearId = bookmarkMenu->insertItem( "Clear bookmarks" );
+ bookmarkMenu->insertSeparator();
+ return;
+ }
+
+ if ( i == addId ){
+ bookmarkList << dirPath();
+
+ const char* book_pix[]={
+ "12 16 3 1",
+ ". c None",
+ "a c #000000",
+ "# c #008080",
+ "............",
+ "............",
+ "........##..",
+ ".......#####",
+ "......#####a",
+ ".....#####a.",
+ "....#####a..",
+ "...#####a...",
+ "..#####a....",
+ ".#####a.....",
+ "aaa##a......",
+ "...#a.......",
+ "...a........",
+ "............",
+ "............",
+ "............"};
+ bookmarkMenu->insertItem( QIconSet( book_pix ), dirPath() );
+ return;
+ }
+
+ setDir( bookmarkMenu->text( i ) );
+}
+
+void CustomFileDialog::goHome()
+{
+ if ( getenv( "HOME" ) )
+ setDir( getenv( "HOME" ) );
+ else
+ setDir( "/" );
+}
+
+void CustomFileDialog::done( int i )
+{
+ emit signalDone(i);
+}
+/******************************************************************************************************/
+static const char* folder_closed_xpm[] = {
+"16 16 9 1",
+" c Gray0",
+". c #222222",
+"X c #6666cc",
+"o c #9999ff",
+"O c #c0c0c0",
+"+ c #ccccff",
+"@ c #ffffcc",
+"# c Gray100",
+"$ c None",
+"$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$",
+"$$$$$$$$$$$$$$$$",
+"$$XXXXo$$$$$$$$$",
+"$X#++o@XXXXXX$$$",
+"X#+++++++++++o$$",
+"X#o+o+o+o+o+oX$$",
+"X#+o+o+o+o+o+X $",
+"X#o+o+o+o+o+oX $",
+"X#+o+o+o+o+o+X $",
+"X#o+o+o+o+o+oX $",
+"X#+o+o+o+o+o+X $",
+"X+o+o+o+o+o+oX $",
+"XXXXXXXXXXXXXX $",
+"$ .. $"
+};
+
+static const char* folder_open_xpm[] = {
+"16 16 10 1",
+" c Gray0",
+". c #222222",
+"X c #6666cc",
+"o c Magenta",
+"O c #9999ff",
+"+ c #c0c0c0",
+"@ c #ccccff",
+"# c #ffffcc",
+"$ c Gray100",
+"% c None",
+"%%%%%%%%%%%%%%%%",
+"%%%%%%%%%%%%%%%%",
+"%%%%%%%%%%%%%%%%",
+"%%%%%%%%%%%%%%%%",
+"%%XXXX%%%%%%%%%%",
+"%X$$$XXXXXXXXX%%",
+"%X$O+#######.OX%",
+"%X$+#######.O@X%",
+"%O$#######.O@OX ",
+"XXXXXXXXXX.XO@X ",
+"X$$$$$$$$$+ @OX ",
+"%XO+O+O+O+O+ @X ",
+"%X+O+O+O+O+O. X ",
+"%%X+O+O+O+O+O. ",
+"%%XXXXXXXXXXXXX ",
+"%%% "
+};
+
+static const char* folder_locked_xpm[] = {
+"16 16 8 1",
+" c Gray0",
+". c #333366",
+"X c #6666cc",
+"o c Magenta",
+"O c #9999ff",
+"+ c #c0c0c0",
+"@ c Gray100",
+"# c None",
+"###O.O##########",
+"###...##########",
+"###O.O##########",
+"##.#X#.#OX######",
+"#...X...@@X#####",
+"#.......OOOOOOX#",
+"#.......@@@@@@X#",
+"#@@@@@@@O+O+O+X ",
+"#O@O+O+O+O+O+OX ",
+"#O@+O+O+O+O+O+X ",
+"#O@O+O+O+O+O+OX ",
+"#O@+O+O+O+O+O+X ",
+"#O@O+O+O+O+O+OX ",
+"#OXXXXXXXXXXXXX ",
+"## ",
+"################"
+};
+
+Directory::Directory( Directory * parent, const QString& filename )
+:QListViewItem( parent ), f(filename)
+{
+ p = parent;
+ readable = QDir( fullName() ).isReadable();
+
+ if ( !readable )
+ setPixmap( 0, QPixmap( folder_locked_xpm ) );
+ else
+ setPixmap( 0, QPixmap( folder_closed_xpm ) );
+}
+
+
+Directory::Directory( QListView * parent, const QString& filename )
+:QListViewItem( parent ), f(filename)
+{
+ p = 0;
+ readable = QDir( fullName() ).isReadable();
+}
+
+
+void Directory::setOpen( bool o )
+{
+ if ( o )
+ setPixmap( 0, QPixmap( folder_open_xpm ) );
+ else
+ setPixmap( 0, QPixmap( folder_closed_xpm ) );
+
+ if ( o && !childCount() ){
+ QString s( fullName() );
+ QDir thisDir( s );
+ if ( !thisDir.isReadable() ) {
+ readable = false;
+ setExpandable( false );
+ return;
+ }
+
+ listView()->setUpdatesEnabled( false );
+ const QFileInfoList * files = thisDir.entryInfoList();
+ if ( files ){
+ QFileInfoListIterator it( *files );
+ QFileInfo * f;
+ while( (f=it.current()) != 0 ){
+ ++it;
+ if ( f->fileName() != "." && f->fileName() != ".." && f->isDir() )
+ (void)new Directory( this, f->fileName() );
+ }
+ }
+ listView()->setUpdatesEnabled( true );
+ }
+ QListViewItem::setOpen( o );
+}
+
+
+void Directory::setup()
+{
+ setExpandable( true );
+ QListViewItem::setup();
+}
+
+
+QString Directory::fullName()
+{
+ QString s;
+ if ( p ) {
+ s = p->fullName();
+ s.append( f.name() );
+ s.append( "/" );
+ } else {
+ s = f.name();
+ }
+ return s;
+}
+
+
+QString Directory::text( int column ) const
+{
+ if ( column == 0 )
+ return f.name();
+ else
+ if ( readable )
+ return "Directory";
+ else
+ return "Unreadable Directory";
+}
+
+DirectoryView::DirectoryView( QWidget *parent, const char *name )
+:QListView( parent, name )
+{
+ connect( this, SIGNAL( clicked( QListViewItem * ) ),
+ this, SLOT( slotFolderSelected( QListViewItem * ) ) );
+ connect( this, SIGNAL( doubleClicked( QListViewItem * ) ),
+ this, SLOT( slotFolderSelected( QListViewItem * ) ) );
+ connect( this, SIGNAL( returnPressed( QListViewItem * ) ),
+ this, SLOT( slotFolderSelected( QListViewItem * ) ) );
+
+ setAcceptDrops( true );
+ viewport()->setAcceptDrops( true );
+}
+
+void DirectoryView::setOpen( QListViewItem* i, bool b )
+{
+ QListView::setOpen(i,b);
+ setCurrentItem(i);
+ slotFolderSelected(i);
+}
+
+void DirectoryView::slotFolderSelected( QListViewItem *i )
+{
+ if ( !i ) return;
+
+ Directory *dir = (Directory*)i;
+ emit folderSelected( dir->fullName() );
+}
+
+QString DirectoryView::fullPath(QListViewItem* item)
+{
+ QString fullpath = item->text(0);
+ while ( (item=item->parent()) ) {
+ if ( item->parent() )
+ fullpath = item->text(0) + "/" + fullpath;
+ else
+ fullpath = item->text(0) + fullpath;
+ }
+ return fullpath;
+}
+
+void DirectoryView::setDir( const QString &s )
+{
+ QListViewItemIterator it( this );
+ ++it;
+ for ( ; it.current(); ++it ) {
+ it.current()->setOpen( false );
+ }
+
+ QStringList lst( QStringList::split( "/", s ) );
+ QListViewItem *item = firstChild();
+ QStringList::Iterator it2 = lst.begin();
+ for ( ; it2 != lst.end(); ++it2 ) {
+ while ( item ) {
+ if ( item->text( 0 ) == *it2 ) {
+ item->setOpen( true );
+ break;
+ }
+ item = item->itemBelow();
+ }
+ }
+
+ if ( item ){
+ setSelected( item, true );
+ setCurrentItem( item );
+ }
+}
+
+QString DirectoryView::selectedDir()
+{
+ Directory *dir = (Directory*)currentItem();
+ return dir->fullName();
+}
+/**********************************************************************************************/
+
+int main(int argc, char* argv[]) {
+ KApplication app(argc,argv,"kdockwidgetdemo");
+
+#if 0
+ SFileDialog* openfile = new SFileDialog();
+ openfile->exec();
+ qDebug( openfile->fileName() );
+#endif
+
+#if 0
+ qDebug ( SFileDialog::getOpenFileName( QString::null, QString::fromLatin1("All (*)"),
+ QString::fromLatin1("DockWidget Demo"), "dialog1" ) );
+#endif
+
+#if 1
+ QStringList s = SFileDialog::getOpenFileNames( QString::null, QString::fromLatin1("All (*)"),
+ QString::fromLatin1("DockWidget Demo"), "dialog1" );
+ QStringList::Iterator it = s.begin();
+ for ( ; it != s.end(); ++it ){
+ qDebug( "%s", (*it).local8Bit().data() );
+ }
+#endif
+ return 0;
+}
+
+#include "kdockwidgetdemo.moc"
+
diff --git a/kdeui/tests/kdockwidgetdemo.h b/kdeui/tests/kdockwidgetdemo.h
new file mode 100644
index 000000000..e81162eb0
--- /dev/null
+++ b/kdeui/tests/kdockwidgetdemo.h
@@ -0,0 +1,164 @@
+#ifndef KDOCKWIDGETDEMO_H
+#define KDOCKWIDGETDEMO_H
+
+#include <kdockwidget.h>
+
+#include <qdialog.h>
+#include <qlistview.h>
+#include <qstring.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qtimer.h>
+#include <qscrollview.h>
+#include <qfiledialog.h>
+#include <qwidgetstack.h>
+#include <qvbox.h>
+#include <qurl.h>
+#include <qpixmap.h>
+
+class QMultiLineEdit;
+class QTextView;
+class QToolButton;
+class QSpinBox;
+class QShowEvent;
+class QPopupMenu;
+
+class DirectoryView;
+class CustomFileDialog;
+class Preview;
+class DirectoryView;
+
+class SFileDialog : public QDialog
+{Q_OBJECT
+
+public:
+ SFileDialog( QString initially = QString::null,
+ const QStringList& filter = "All Files ( * )", const char* name = 0 );
+ ~SFileDialog();
+
+ static QString getOpenFileName( QString initially = QString::null,
+ const QStringList& filter = "All Files ( * )",
+ const QString caption = QString::null, const char* name = 0 );
+
+ static QStringList getOpenFileNames( QString initially = QString::null,
+ const QStringList& filter = "All Files ( * )",
+ const QString caption = QString::null, const char* name = 0 );
+
+
+protected:
+ void showEvent( QShowEvent *e );
+
+protected slots:
+ void dockChange();
+ void setDockDefaultPos( KDockWidget* );
+ void changeDir( const QString& );
+
+private:
+ DirectoryView* dirView;
+ CustomFileDialog* fd;
+ Preview* preview;
+
+ KDockManager* dockManager;
+ KDockWidget* d_dirView;
+ KDockWidget* d_preview;
+ KDockWidget* d_fd;
+
+ QToolButton *b_tree;
+ QToolButton *b_preview;
+};
+/******************************************************************************************************/
+class Directory : public QListViewItem
+{
+public:
+ Directory( QListView * parent, const QString& filename );
+ Directory( Directory * parent, const QString& filename );
+
+ QString text( int column ) const;
+
+ QString fullName();
+
+ void setOpen( bool );
+ void setup();
+
+private:
+ QFile f;
+ Directory * p;
+ bool readable;
+};
+
+class DirectoryView : public QListView
+{Q_OBJECT
+public:
+ DirectoryView( QWidget *parent = 0, const char *name = 0 );
+ virtual void setOpen ( QListViewItem *, bool );
+
+ QString selectedDir();
+
+public slots:
+ void setDir( const QString & );
+
+signals:
+ void folderSelected( const QString & );
+
+protected slots:
+ void slotFolderSelected( QListViewItem * );
+
+private:
+ QString fullPath(QListViewItem* item);
+};
+/******************************************************************************************************/
+class PixmapView : public QScrollView
+{Q_OBJECT
+public:
+ PixmapView( QWidget *parent );
+ void setPixmap( const QPixmap &pix );
+ void drawContents( QPainter *p, int, int, int, int );
+
+private:
+ QPixmap pixmap;
+};
+
+class Preview : public QWidgetStack
+{Q_OBJECT
+public:
+ Preview( QWidget *parent );
+
+public slots:
+ void showPreview( const QString& );
+
+private:
+ QMultiLineEdit *normalText;
+ QTextView *html;
+ PixmapView *pixmap;
+};
+
+class CustomFileDialog : public QFileDialog
+{Q_OBJECT
+public:
+ CustomFileDialog( QWidget* parent );
+ ~CustomFileDialog();
+
+ void addToolButton( QButton * b, bool separator = false ){ QFileDialog::addToolButton(b,separator); }
+ void setBookmark( QStringList& );
+ QStringList getBookmark(){ return bookmarkList; }
+
+public slots:
+ void setDir2( const QString & );
+
+signals:
+ void signalDone( int );
+
+protected slots:
+ void bookmarkChosen( int i );
+ void goHome();
+ virtual void done( int );
+
+private:
+ QPopupMenu *bookmarkMenu;
+ QStringList bookmarkList;
+ int addId, clearId;
+};
+
+#endif
+
+
diff --git a/kdeui/tests/kdockwidgettest.cpp b/kdeui/tests/kdockwidgettest.cpp
new file mode 100644
index 000000000..bf1fb272d
--- /dev/null
+++ b/kdeui/tests/kdockwidgettest.cpp
@@ -0,0 +1,255 @@
+/***************************************************************************
+ copyright : (C) 1999 by Judin Max
+ email : novaprint@mtu-net.ru
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include "kdockwidgettest.h"
+
+#include <qpushbutton.h>
+#include <kapplication.h>
+#include <kiconloader.h>
+#include <kstatusbar.h>
+#include <kmenubar.h>
+#include <ktoolbar.h>
+#include <qvbox.h>
+
+static const char*folder[]={
+"16 16 9 1",
+"g c #808080",
+"b c #ffa858",
+"e c #c0c0c0",
+"# c #000000",
+"c c #ffdca8",
+". c None",
+"a c #585858",
+"f c #a0a0a4",
+"d c #ffffff",
+"..#a#...........",
+".#abc##.........",
+".#daabc#####....",
+".#ddeaabcccb#...",
+".#dedeeabccca...",
+".#edeeeeaaaab#..",
+".#deeeeeeefe#ba.",
+".#eeeeeeefef#ba.",
+".#eeeeeefeff#ba.",
+".#eeeeefefff#ba.",
+".##geefeffff#ba.",
+"...##gefffff#ba.",
+".....##fffff#ba.",
+".......##fff#b##",
+".........##f#b##",
+"...........####."};
+
+
+DockApplication::DockApplication( const char* name )
+: KDockMainWindow( 0L, name )
+{
+ QPixmap p(folder);
+
+ initMenuBar();
+ initToolBars();
+ initStatusBar();
+
+ /*****************************************************/
+ dock = createDockWidget( "Green Widget", p );
+ dock->setCaption("Green");
+ dock->setGeometry(50, 50, 100, 100);
+ l = new QWidget(dock);
+ l->setBackgroundColor(green);
+ l->setMinimumSize(100,100);
+ dock->setWidget(l);
+ /*****************************************************/
+ dock1 = createDockWidget( "Blue Widget", p );
+ dock1->setCaption("Blue");
+ dock1->setGeometry( 150, 150, 100, 100);
+ setView( dock1 );
+ setMainDockWidget( dock1 );
+
+ mainW = new QWidget( dock1, "createdOnBlueDock" );
+ mainW->setBackgroundColor(blue);
+ mainW->setMinimumSize(300,150);
+ dock1->setWidget( mainW );
+ /*****************************************************/
+
+ KDockWidget* dock2 = createDockWidget( "Yellow Widget", p );
+ dock2->setGeometry(300, 300, 100, 100);
+ dock2->setCaption("Yellow");
+
+ /* test set new header widget...*/
+// dock2->setHeader( new KDockWidgetHeader(dock2) );
+
+ QWidget* l2 = new QWidget(dock2);
+ l2->setBackgroundColor(yellow);
+ dock2->setWidget( l2 );
+ /*****************************************************/
+
+ /*****************************************************/
+ dock5 = createDockWidget( "Container Widget", p );
+ dock5->setCaption("Container");
+ dock5->setGeometry(50, 50, 100, 100);
+ l = new CTW(dock5);
+ l->setBackgroundColor(white);
+ l->setMinimumSize(100,100);
+ dock5->setWidget(l);
+ if (l->qt_cast("KDockContainer")) qDebug("KDockContainer created for dock 5");
+ /*****************************************************/
+
+ /*****************************************************/
+ dock6 = createDockWidget( "Container Widget2", p );
+ dock6->setCaption("Container2");
+ dock6->setGeometry(50, 50, 100, 100);
+ l = new CTW(dock6);
+ l->setBackgroundColor(white);
+ l->setMinimumSize(100,100);
+ dock6->setWidget(l);
+ if (l->qt_cast("KDockContainer")) qDebug("KDockContainer created for dock 6");
+ /*****************************************************/
+
+
+
+ QPushButton* b1 = new QPushButton(mainW);
+ b1->setGeometry(10, 10, 250, 25);
+ b1->setText("write dock config");
+ connect(b1, SIGNAL(clicked()), SLOT(wConfig()));
+
+ QPushButton* b2 = new QPushButton(mainW);
+ b2->setGeometry(10, 35, 250, 25);
+ b2->setText("read dock config");
+ connect(b2, SIGNAL(clicked()), SLOT(rConfig()));
+
+ m_bname = new QPushButton(mainW);
+ m_bname->setGeometry(10, 60, 250, 25);
+ m_bname->setEnabled( false );
+
+ QPushButton *b3 = new QPushButton(mainW);
+ b3->setGeometry(10,95,250,25);
+ b3->setText("change the icon of the green widget");
+ connect(b3,SIGNAL(clicked()), SLOT(gSetPix1()));
+
+ QPushButton *b4 = new QPushButton(mainW);
+ b4->setGeometry(10,130,250,25);
+ b4->setText("remove icon ");
+ connect(b4,SIGNAL(clicked()), SLOT(gSetPix2()));
+
+ setGeometry(200, 100, 500, 300);
+
+ qDebug("load config");
+ readDockConfig();
+
+ updateButton();
+}
+
+DockApplication::~DockApplication()
+{
+ qDebug("Close & store config");
+ writeDockConfig();
+}
+
+void DockApplication::rConfig()
+{
+ readDockConfig();
+}
+
+void DockApplication::wConfig()
+{
+ writeDockConfig();
+}
+
+void DockApplication::initMenuBar()
+{
+ QPixmap p(folder);
+ QPopupMenu *file_menu = new QPopupMenu();
+
+ file_menu->insertItem(p, "Change Green Widget Caption", this, SLOT(cap()) );
+ file_menu->insertSeparator();
+ file_menu->insertItem(p, "Set Green Widget as MainDockWidget", this, SLOT(greenMain()) );
+ file_menu->insertItem(p, "Set Blue Widget as MainDockWidget", this, SLOT(blueMain()) );
+ file_menu->insertItem(p, "Set NULL as MainDockWidget", this, SLOT(nullMain()) );
+
+ KMenuBar* menu_bar = menuBar();
+ menu_bar->insertItem( "&Test", file_menu );
+ menu_bar->insertItem( "&Docking Windows", dockHideShowMenu() );
+}
+
+void DockApplication::initToolBars()
+{
+ QPixmap p(folder);
+ KToolBar* tool_bar_0 = toolBar(0);
+ tool_bar_0->setFullSize(false);
+ tool_bar_0->insertButton( p, 1 );
+ tool_bar_0->insertButton(p, 2 );
+ tool_bar_0->setFullSize( true );
+}
+
+void DockApplication::initStatusBar()
+{
+ KStatusBar* status_bar = statusBar();
+ status_bar->insertItem("Welcome to KDockWidget test...", 1);
+}
+
+void DockApplication::cap()
+{
+ if ( dock->caption() != "Test Caption1" )
+ dock->setCaption("Test Caption1");
+ else
+ dock->setCaption("Another Caption");
+}
+
+void DockApplication::greenMain()
+{
+ setMainDockWidget( dock );
+ updateButton();
+}
+
+void DockApplication::blueMain()
+{
+ setMainDockWidget( dock1 );
+ updateButton();
+}
+
+void DockApplication::nullMain()
+{
+ setMainDockWidget( 0L );
+ updateButton();
+}
+
+void DockApplication::updateButton()
+{
+ if ( getMainDockWidget() )
+ m_bname->setText(QString("MainDockWidget is %1").arg(getMainDockWidget()->name()));
+ else
+ m_bname->setText("MainDockWidget is NULL");
+}
+
+void DockApplication::gSetPix1() {
+ dock->setPixmap(SmallIcon("agent"));
+
+}
+
+void DockApplication::gSetPix2() {
+ dock->setPixmap();
+
+}
+
+int main(int argc, char* argv[]) {
+ KApplication a(argc,argv, "kdockdemoapp1");
+ DockApplication* ap = new DockApplication("DockWidget demo");
+ ap->setCaption("DockWidget demo");
+ a.setMainWidget(ap);
+ ap->show();
+ return a.exec();
+}
+
+
+#include "kdockwidgettest.moc"
+
diff --git a/kdeui/tests/kdockwidgettest.h b/kdeui/tests/kdockwidgettest.h
new file mode 100644
index 000000000..70d75877c
--- /dev/null
+++ b/kdeui/tests/kdockwidgettest.h
@@ -0,0 +1,72 @@
+/***************************************************************************
+ copyright : (C) 1999 by Judin Max
+ email : novaprint@mtu-net.ru
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef KDOCKWIDGETTEST_H
+#define KDOCKWIDGETTEST_H
+
+#include <kdockwidget.h>
+#include <kdockwidget_p.h>
+#include <qtabwidget.h>
+#include <qlabel.h>
+class QPushButton;
+
+class DockApplication : public KDockMainWindow
+{Q_OBJECT
+public:
+ DockApplication( const char* name );
+ ~DockApplication();
+
+public slots:
+ void rConfig();
+ void wConfig();
+ void cap();
+ void greenMain();
+ void blueMain();
+ void nullMain();
+ void gSetPix1();
+ void gSetPix2();
+
+protected:
+ void initMenuBar();
+ void initToolBars();
+ void initStatusBar();
+
+private:
+ void updateButton();
+ KDockWidget* dock;
+ KDockWidget* dock1;
+ KDockWidget* dock4;
+ KDockWidget* dock5;
+ KDockWidget* dock6;
+
+ QWidget* mainW;
+ QWidget* l;
+ QPushButton* m_bname;
+};
+
+class CTW:public QTabWidget,public KDockContainer
+{
+ Q_OBJECT
+public:
+ CTW(QWidget *parent):QTabWidget(parent,"MyDockContainer"),KDockContainer(){insertTab(new QLabel("BLAH",this),"BLUP");}
+ virtual ~CTW(){;}
+ KDockWidget *parentDockWidget(){return ((KDockWidget*)parent());}
+ void insertWidget (KDockWidget *w, QPixmap, const QString &, int &){qDebug("widget inserted"); insertTab(w,"NO");}
+ void setToolTip (KDockWidget *, QString &){qDebug("Tooltip set");}
+};
+
+
+#endif
+
+
diff --git a/kdeui/tests/kdualcolortest.cpp b/kdeui/tests/kdualcolortest.cpp
new file mode 100644
index 000000000..9022634f1
--- /dev/null
+++ b/kdeui/tests/kdualcolortest.cpp
@@ -0,0 +1,63 @@
+#include "kdualcolortest.h"
+#include <kdualcolorbutton.h>
+#include <kapplication.h>
+#include <klocale.h>
+#include <qlayout.h>
+#include <qpalette.h>
+
+KDualColorWidget::KDualColorWidget(QWidget *parent, const char *name)
+ : QWidget(parent, name)
+{
+ lbl = new QLabel("Testing, testing, 1, 2, 3...", this);
+ KDualColorButton *colorBtn =
+ new KDualColorButton(lbl->colorGroup().text(),
+ lbl->colorGroup().background(), this);
+ connect(colorBtn, SIGNAL(fgChanged(const QColor &)),
+ SLOT(slotFgChanged(const QColor &)));
+ connect(colorBtn, SIGNAL(bgChanged(const QColor &)),
+ SLOT(slotBgChanged(const QColor &)));
+ connect(colorBtn, SIGNAL(currentChanged(KDualColorButton::DualColor)),
+ SLOT(slotCurrentChanged(KDualColorButton::DualColor)));
+
+ QHBoxLayout *layout = new QHBoxLayout(this, 5);
+ layout->addWidget(colorBtn, 0);
+ layout->addWidget(lbl, 1);
+ layout->activate();
+ resize(sizeHint());
+}
+
+void KDualColorWidget::slotFgChanged(const QColor &c)
+{
+ QPalette p = lbl->palette();
+ p.setColor(QColorGroup::Text, c);
+ lbl->setPalette(p);
+}
+
+void KDualColorWidget::slotBgChanged(const QColor &c)
+{
+ QPalette p = lbl->palette();
+ QBrush b(c, SolidPattern);
+ p.setBrush(QColorGroup::Background, b);
+ setPalette(p);
+}
+
+void KDualColorWidget::slotCurrentChanged(KDualColorButton::DualColor current)
+{
+ if(current == KDualColorButton::Foreground)
+ qDebug("Foreground Button Selected.");
+ else
+ qDebug("Background Button Selected.");
+}
+
+int main(int argc, char **argv)
+{
+ KApplication *app = new KApplication(argc, argv, "KDualColorTest");
+ KDualColorWidget w;
+ app->setMainWidget(&w);
+ w.show();
+ return(app->exec());
+}
+
+#include "kdualcolortest.moc"
+
+
diff --git a/kdeui/tests/kdualcolortest.h b/kdeui/tests/kdualcolortest.h
new file mode 100644
index 000000000..6a0c49452
--- /dev/null
+++ b/kdeui/tests/kdualcolortest.h
@@ -0,0 +1,20 @@
+#ifndef __KDUALCOLORTEST_H
+#define __KDUALCOLORTEST_H
+
+#include <qlabel.h>
+#include <kdualcolorbutton.h>
+
+class KDualColorWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ KDualColorWidget(QWidget *parent=0, const char *name=0);
+protected slots:
+ void slotFgChanged(const QColor &c);
+ void slotBgChanged(const QColor &c);
+ void slotCurrentChanged(KDualColorButton::DualColor current);
+protected:
+ QLabel *lbl;
+};
+
+#endif
diff --git a/kdeui/tests/keditlistboxtest.cpp b/kdeui/tests/keditlistboxtest.cpp
new file mode 100644
index 000000000..0cbbece8a
--- /dev/null
+++ b/kdeui/tests/keditlistboxtest.cpp
@@ -0,0 +1,21 @@
+#include <kapplication.h>
+#include <keditlistbox.h>
+#include <kcombobox.h>
+
+int main( int argc, char **argv )
+{
+ KApplication app( argc, argv, "keditlistboxtest" );
+
+ KEditListBox::CustomEditor editor( new KComboBox( true, 0L, "test" ) );
+ KEditListBox *box = new KEditListBox( QString::fromLatin1("KEditListBox"),
+ editor );
+
+ box->insertItem( QString::fromLatin1("Test") );
+ box->insertItem( QString::fromLatin1("for") );
+ box->insertItem( QString::fromLatin1("this") );
+ box->insertItem( QString::fromLatin1("KEditListBox") );
+ box->insertItem( QString::fromLatin1("Widget") );
+ box->show();
+
+ return app.exec();
+}
diff --git a/kdeui/tests/kedittest.cpp b/kdeui/tests/kedittest.cpp
new file mode 100644
index 000000000..271923e18
--- /dev/null
+++ b/kdeui/tests/kedittest.cpp
@@ -0,0 +1,14 @@
+#include <kapplication.h>
+#include <keditcl.h>
+#include <qpopupmenu.h>
+
+int main( int argc, char **argv )
+{
+ KApplication app( argc, argv, "kedittest" );
+ KEdit *edit = new KEdit( 0L );
+ QPopupMenu *pop = new QPopupMenu( 0L );
+ pop->insertItem( "Popupmenu item" );
+ edit->installRBPopup( pop );
+ edit->show();
+ return app.exec();
+}
diff --git a/kdeui/tests/kfontdialogtest.cpp b/kdeui/tests/kfontdialogtest.cpp
new file mode 100644
index 000000000..f1aa74804
--- /dev/null
+++ b/kdeui/tests/kfontdialogtest.cpp
@@ -0,0 +1,51 @@
+/*
+ $Id$
+
+ Requires the Qt widget libraries, available at no cost at
+ http://www.troll.no
+
+ Copyright (C) 1996 Bernd Johannes Wuebben
+ wuebben@math.cornell.edu
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+
+#include <kapplication.h>
+#include "kfontdialog.h"
+#include <kconfig.h>
+
+
+ int main( int argc, char **argv )
+{
+ KApplication app( argc, argv, "KFontDialogTest" );
+
+ KConfig aConfig;
+ aConfig.setGroup( "KFontDialog-test" );
+
+ app.setFont(QFont("Helvetica",12));
+
+ // QFont font = QFont("Times",18,QFont::Bold);
+
+ QFont font = aConfig.readFontEntry( "Chosen" );
+ int nRet = KFontDialog::getFont(font);
+ int flags;
+ nRet = KFontDialog::getFontDiff(font, flags);
+ aConfig.writeEntry( "Chosen", font, true );
+
+ aConfig.sync();
+ return nRet;
+}
diff --git a/kdeui/tests/kgradienttest.cpp b/kdeui/tests/kgradienttest.cpp
new file mode 100644
index 000000000..9fad0bb46
--- /dev/null
+++ b/kdeui/tests/kgradienttest.cpp
@@ -0,0 +1,108 @@
+#include "kgradienttest.h"
+#include <kapplication.h>
+#include <kpixmapeffect.h>
+#include <qpainter.h>
+#include <qdatetime.h>
+#include <qstring.h>
+
+int cols = 3, rows = 3; // how many
+
+void KGradientWidget::paintEvent(QPaintEvent */*ev*/)
+{
+ QTime time;
+ int it, ft;
+ QString say;
+
+ QColor ca = Qt::black, cb = Qt::blue;
+
+ int x = 0, y = 0;
+
+ pix.resize(width()/cols, height()/rows);
+ QPainter p(this);
+ p.setPen(Qt::white);
+
+ // draw once, so that the benchmarking be fair :-)
+ KPixmapEffect::gradient(pix,ca, cb, KPixmapEffect::VerticalGradient);
+
+ // vertical
+ time.start();
+ it = time.elapsed();
+ KPixmapEffect::gradient(pix,ca, cb, KPixmapEffect::VerticalGradient);
+ ft = time.elapsed();
+ say.setNum( ft - it); say += " ms, Vertical";
+ p.drawPixmap(x*width()/cols, y*height()/rows, pix);
+ p.drawText(5 + (x++)*width()/cols, 15+y*height()/rows, say); // augment x
+
+ // horizontal
+ it = time.elapsed();
+ KPixmapEffect::gradient(pix,ca, cb, KPixmapEffect::HorizontalGradient);
+ ft = time.elapsed() ;
+ say.setNum( ft - it); say += " ms, Horizontal";
+ p.drawPixmap(x*width()/cols, y*height()/rows, pix);
+ p.drawText(5+(x++)*width()/cols, 15+y*height()/rows, say);
+
+ // elliptic
+ it = time.elapsed();
+ KPixmapEffect::gradient(pix, ca, cb, KPixmapEffect::EllipticGradient);
+ ft = time.elapsed() ;
+ say.setNum( ft - it); say += " ms, Elliptic";
+ p.drawPixmap(x*width()/cols, y*height()/rows, pix);
+ p.drawText(5+(x++)*width()/cols, 15+y*height()/rows, say);
+
+ y++; // next row
+ x = 0; // reset the columns
+
+ // diagonal
+ it = time.elapsed();
+ KPixmapEffect::gradient(pix,ca, cb, KPixmapEffect::DiagonalGradient);
+ ft = time.elapsed();
+ say.setNum( ft - it); say += " ms, Diagonal";
+ p.drawPixmap(x*width()/cols, y*height()/rows, pix);
+ p.drawText(5+(x++)*width()/cols, 15+y*height()/rows, say);
+
+ // crossdiagonal
+ it = time.elapsed();
+ KPixmapEffect::gradient(pix,ca, cb, KPixmapEffect::CrossDiagonalGradient);
+ ft = time.elapsed();
+ say.setNum( ft - it); say += " ms, CrossDiagonal";
+ p.drawPixmap(width()/cols, y*height()/rows, pix);
+ p.drawText(5+(x++)*width()/cols, 15+y*height()/rows, say);
+
+ y++; // next row
+ x = 0; // reset the columns
+
+ // pyramidal
+ it = time.elapsed();
+ KPixmapEffect::gradient(pix, ca, cb, KPixmapEffect::PyramidGradient);
+ ft = time.elapsed();
+ say.setNum( ft - it); say += " ms, Pyramid";
+ p.drawPixmap(x*width()/cols, y*height()/rows, pix);
+ p.drawText(5+(x++)*width()/cols, 15+y*height()/rows, say);
+
+ // pattern
+ it = time.elapsed();
+ KPixmapEffect::gradient(pix, ca, cb, KPixmapEffect::RectangleGradient);
+ ft = time.elapsed();
+ say.setNum( ft - it); say += " ms, Rectangle";
+ p.drawPixmap(x*width()/cols, y*height()/rows, pix);
+ p.drawText(5+(x++)*width()/rows, 15+y*height()/rows, say);
+
+ // crosspipe
+ it = time.elapsed();
+ KPixmapEffect::gradient(pix, ca, cb, KPixmapEffect::PipeCrossGradient);
+ ft = time.elapsed();
+ say.setNum( ft - it); say += " ms, PipeCross";
+ p.drawPixmap(x*width()/cols, y*height()/rows, pix);
+ p.drawText(5+(x++)*width()/rows, 15+y*height()/rows, say);
+}
+
+int main(int argc, char **argv)
+{
+ KApplication *app = new KApplication(argc, argv, "KGradientTest");
+ KGradientWidget w;
+ w.resize(250 * cols, 250 * rows);
+ app->setMainWidget(&w);
+ w.show();
+ return(app->exec());
+}
+
diff --git a/kdeui/tests/kgradienttest.h b/kdeui/tests/kgradienttest.h
new file mode 100644
index 000000000..09b17ffc7
--- /dev/null
+++ b/kdeui/tests/kgradienttest.h
@@ -0,0 +1,24 @@
+//
+// Simple little hack to show off new diagonal gradients.
+//
+// (C) KDE Artistic Daniel M. Duley <mosfet@kde.org>
+//
+
+#ifndef __KGRADIENT_TEST_H
+#define __KGRADIENT_TEST_H
+
+#include <qwidget.h>
+#include <kpixmap.h>
+
+class KGradientWidget : public QWidget
+{
+public:
+ KGradientWidget(QWidget *parent=0, const char *name=0)
+ : QWidget(parent, name){;}
+protected:
+ void paintEvent(QPaintEvent *ev);
+private:
+ KPixmap pix;
+};
+
+#endif
diff --git a/kdeui/tests/khashtest.cpp b/kdeui/tests/khashtest.cpp
new file mode 100644
index 000000000..1065bef1a
--- /dev/null
+++ b/kdeui/tests/khashtest.cpp
@@ -0,0 +1,137 @@
+#include "khashtest.h"
+#include <kapplication.h>
+#include <kpixmapeffect.h>
+#include <kimageeffect.h>
+#include <qpainter.h>
+#include <qdatetime.h>
+#include <qstring.h>
+#include <qimage.h>
+
+int cols = 3, rows = 3; // how many
+
+void KHashWidget::paintEvent(QPaintEvent * /*ev*/)
+{
+ QTime time;
+ int it, ft;
+ QString say;
+
+ QColor cb = QColor(0,70,70), ca = QColor(80,200,200);
+
+ int x = 0, y = 0;
+
+ pix.resize(width()/cols, height()/rows);
+ QPainter p(this);
+ p.setPen(Qt::white);
+
+ // draw once, so that the benchmarking be fair :-)
+ KPixmapEffect::gradient(pix,ca, cb, KPixmapEffect::VerticalGradient);
+
+ // vertical
+ time.start();
+ it = time.elapsed();
+ KPixmapEffect::gradient(pix,ca, cb, KPixmapEffect::VerticalGradient);
+ KPixmapEffect::hash(pix,KPixmapEffect::NorthLite);
+ ft = time.elapsed();
+ say.setNum( ft - it); say += " ms, Vertical";
+ p.drawPixmap(x*width()/cols, y*height()/rows, pix);
+ p.drawText(5 + (x++)*width()/cols, 15+y*height()/rows, say); // augment x
+
+ // horizontal
+ it = time.elapsed();
+ KPixmapEffect::gradient(pix,ca, cb, KPixmapEffect::HorizontalGradient);
+ KPixmapEffect::hash(pix,KPixmapEffect::SouthLite);
+ ft = time.elapsed() ;
+ say.setNum( ft - it); say += " ms, Horizontal";
+ p.drawPixmap(x*width()/cols, y*height()/rows, pix);
+ p.drawText(5+(x++)*width()/cols, 15+y*height()/rows, say);
+
+ // elliptic
+ it = time.elapsed();
+ KPixmapEffect::gradient(pix, ca, cb, KPixmapEffect::EllipticGradient);
+ KPixmapEffect::hash(pix,KPixmapEffect::NorthLite, 1);
+ ft = time.elapsed() ;
+ say.setNum( ft - it); say += " ms, Elliptic";
+ p.drawPixmap(x*width()/cols, y*height()/rows, pix);
+ p.drawText(5+(x++)*width()/cols, 15+y*height()/rows, say);
+
+ y++; // next row
+ x = 0; // reset the columns
+
+ // diagonal
+ it = time.elapsed();
+ KPixmapEffect::gradient(pix,ca, cb, KPixmapEffect::DiagonalGradient);
+ KPixmapEffect::hash(pix,KPixmapEffect::EastLite);
+ ft = time.elapsed();
+ say.setNum( ft - it); say += " ms, Diagonal";
+ p.drawPixmap(x*width()/cols, y*height()/rows, pix);
+ p.drawText(5+(x++)*width()/cols, 15+y*height()/rows, say);
+
+ // crossdiagonal
+ it = time.elapsed();
+ KPixmapEffect::gradient(pix,ca, cb, KPixmapEffect::CrossDiagonalGradient);
+ KPixmapEffect::hash(pix,KPixmapEffect::EastLite, 2);
+ ft = time.elapsed();
+ say.setNum( ft - it); say += " ms, CrossDiagonal";
+ p.drawPixmap(x*width()/cols, y*height()/rows, pix);
+
+ p.drawText(5+(x++)*width()/cols, 15+y*height()/rows, say);
+
+
+ QImage image = QImage("testimage.png");
+ it = time.elapsed();
+ KImageEffect::hash(image, KImageEffect::WestLite, 2);
+ ft = time.elapsed();
+ pix.resize(image.width(), image.height());
+ pix.convertFromImage(image);
+ pix.resize(width()/cols, height()/rows);
+ say.setNum( ft - it); say += " ms, CrossDiagonal";
+ p.drawPixmap(x*width()/cols, y*height()/rows, pix);
+ p.setPen(Qt::blue);
+ p.drawText(5+(x++)*width()/cols, 15+y*height()/rows, say);
+ p.setPen(Qt::white);
+
+
+ y++; // next row
+ x = 0; // reset the columns
+
+ // pyramidal
+ it = time.elapsed();
+ KPixmapEffect::gradient(pix, ca, cb, KPixmapEffect::PyramidGradient);
+ KPixmapEffect::hash(pix,KPixmapEffect::WestLite);
+ ft = time.elapsed();
+ say.setNum( ft - it); say += " ms, Pyramid";
+ p.drawPixmap(x*width()/cols, y*height()/rows, pix);
+ p.drawText(5+(x++)*width()/cols, 15+y*height()/rows, say);
+
+ // rectangular
+ it = time.elapsed();
+ KPixmapEffect::gradient(pix, ca, cb, KPixmapEffect::RectangleGradient);
+ KPixmapEffect::hash(pix,KPixmapEffect::NWLite);
+ ft = time.elapsed();
+ say.setNum( ft - it); say += " ms, Rectangle";
+ p.drawPixmap(x*width()/cols, y*height()/rows, pix);
+ p.drawText(5+(x++)*width()/rows, 15+y*height()/rows, say);
+
+ // crosspipe
+ it = time.elapsed();
+ KPixmapEffect::gradient(pix, ca, cb, KPixmapEffect::PipeCrossGradient);
+ KPixmapEffect::hash(pix,KPixmapEffect::WestLite, 3);
+ ft = time.elapsed();
+ say.setNum( ft - it); say += " ms, PipeCross";
+ p.drawPixmap(x*width()/cols, y*height()/rows, pix);
+ p.drawText(5+(x++)*width()/rows, 15+y*height()/rows, say);
+
+}
+
+int main(int argc, char **argv)
+{
+
+ KApplication *app = new KApplication(argc, argv, "KHashTest");
+ KHashWidget w;
+ w.resize(250 * cols, 250 * rows);
+ app->setMainWidget(&w);
+ w.show();
+ return(app->exec());
+}
+
+#include <khashtest.moc>
diff --git a/kdeui/tests/khashtest.h b/kdeui/tests/khashtest.h
new file mode 100644
index 000000000..24a01c4f1
--- /dev/null
+++ b/kdeui/tests/khashtest.h
@@ -0,0 +1,26 @@
+//
+// Simple little hack to show off new diagonal gradients.
+//
+// (C) KDE Artistic Daniel M. Duley <mosfet@kde.org>
+//
+
+#ifndef __KHASH_TEST_H
+#define __KHASH_TEST_H
+
+#include <qwidget.h>
+#include <kpixmap.h>
+
+class KHashWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ KHashWidget(QWidget *parent=0, const char *name=0)
+ : QWidget(parent, name){;}
+protected:
+ void paintEvent(QPaintEvent *ev);
+private:
+ KPixmap pix;
+};
+
+#endif
diff --git a/kdeui/tests/kinputdialogtest.cpp b/kdeui/tests/kinputdialogtest.cpp
new file mode 100644
index 000000000..3f9509a40
--- /dev/null
+++ b/kdeui/tests/kinputdialogtest.cpp
@@ -0,0 +1,67 @@
+/*
+ * Author: Nadeem Hasan <nhasan@kde.org>
+ * License: GPL V2
+ */
+
+#include <kapplication.h>
+#include <kinputdialog.h>
+#include <kdebug.h>
+
+#include <qstring.h>
+#include <qvalidator.h>
+
+int main( int argc, char *argv[] )
+{
+ KApplication app( argc, argv, "kinputdialogtest" );
+
+ bool ok;
+ QString svalue;
+ int ivalue;
+ double dvalue;
+
+ svalue = KInputDialog::getText( "_caption", "_label:", "_value", &ok );
+ kdDebug() << "value1: " << svalue << ", ok: " << ok << endl;
+
+ svalue = KInputDialog::getText( "_caption", "_label:", "_value", &ok, 0L, 0L,
+ &QRegExpValidator( QRegExp( "[0-9]{3}\\-[0-9]{3}\\-[0-9]{4}" ), 0L ) );
+ kdDebug() << "value2: " << svalue << ", ok: " << ok << endl;
+
+ svalue = KInputDialog::getText( "_caption", "_label:", "_value", &ok, 0L, 0L,
+ 0L, "900.900.900.900" );
+ kdDebug() << "value1: " << svalue << ", ok: " << ok << endl;
+
+ ivalue = KInputDialog::getInteger( "_caption", "_label:", 64, 0, 255,
+ 16, 16, &ok );
+ kdDebug() << "value3: " << ivalue << ", ok: " << ok << endl;
+
+ ivalue = KInputDialog::getInteger( "_caption", "_label:", 100, 0, 255,
+ 10, 10, &ok );
+ kdDebug() << "value4: " << ivalue << ", ok: " << ok << endl;
+
+ dvalue = KInputDialog::getDouble( "_caption", "_label:", 10, 0, 100, 0.1,
+ 2, &ok );
+ kdDebug() << "value5: " << dvalue << ", ok: " << ok << endl;
+
+ dvalue = KInputDialog::getDouble( "_caption", "_label:", 10, 0, 100, 2, &ok );
+ kdDebug() << "value6: " << dvalue << ", ok: " << ok << endl;
+
+ QStringList list, slvalue;
+ list << "Item 1" << "Item 2" << "Item 3" << "Item 4" << "Item 5";
+ svalue = KInputDialog::getItem( "_caption", "_label:", list, 1, false, &ok );
+ kdDebug() << "value7: " << svalue << ", ok: " << ok << endl;
+
+ svalue = KInputDialog::getItem( "_caption", "_label:", list, 1, true, &ok );
+ kdDebug() << "value8: " << svalue << ", ok: " << ok << endl;
+
+ QStringList select;
+ select << "Item 3";
+ list << "Item 6" << "Item 7" << "Item 8" << "Item 9" << "Item 10";
+ slvalue = KInputDialog::getItemList( "_caption", "_label:", list, select,
+ false, &ok );
+ kdDebug() << "value9: " << slvalue << ", ok: " << ok << endl;
+
+ select << "Item 5";
+ slvalue = KInputDialog::getItemList( "_caption", "_label:", list, select,
+ true, &ok );
+ kdDebug() << "value10: " << slvalue << ", ok: " << ok << endl;
+}
diff --git a/kdeui/tests/kjanuswidgettest.cpp b/kdeui/tests/kjanuswidgettest.cpp
new file mode 100644
index 000000000..5788f3638
--- /dev/null
+++ b/kdeui/tests/kjanuswidgettest.cpp
@@ -0,0 +1,25 @@
+#include <kapplication.h>
+#include <kjanuswidget.h>
+
+#include <qstring.h>
+#include <qcheckbox.h>
+#include <qvbox.h>
+
+int main(int argc, char** argv)
+{
+ KApplication app(argc, argv, "JanusWidgetTest");
+ // -----
+ KJanusWidget* janus = new KJanusWidget( 0, 0, KJanusWidget::IconList );
+
+ QVBox* page1 = janus->addVBoxPage( QString( "Page1" ) ); // use i18n in real apps
+ QCheckBox* cb1 = new QCheckBox( "a", page1 );
+
+ QVBox* page2 = janus->addVBoxPage( QString( "Page2" ) );
+ QCheckBox* cb2 = new QCheckBox( "a", page2 );
+
+ janus->show();
+ QObject::connect( &app, SIGNAL( lastWindowClosed() ), &app, SLOT( quit() ) );
+
+ return app.exec();
+}
+
diff --git a/kdeui/tests/kledtest.cpp b/kdeui/tests/kledtest.cpp
new file mode 100644
index 000000000..8fc082420
--- /dev/null
+++ b/kdeui/tests/kledtest.cpp
@@ -0,0 +1,160 @@
+#include <kapplication.h>
+#include <qwidget.h>
+#include <qtimer.h>
+#include <stdlib.h>
+#include "kled.h"
+#include "kledtest.h"
+
+
+
+KLedTest::KLedTest(QWidget* parent)
+ : QWidget(parent, 0),
+ LedWidth(16),
+ LedHeight(10),
+ Grid(3),
+ ledcolor(0),
+ red(QColor("red")),
+ blue(QColor("blue")),
+ green(QColor("green")),
+ yellow(QColor("yellow")),
+ kled_round(true) // Switch HERE between rectangle and circular leds
+{
+ if (kled_round) {
+ //KLed l(KLed::red, &qw); // create lamp
+ //KLed l(KLed::blue, &qw); // create lamp
+ l = new KLed(Qt::green, this); // create lamp
+ //KLed l(KLed::yellow, &qw); // create lamp
+ //KLed l(KLed::orange, &qw); // create lamp
+
+
+ l->resize(16,30);
+ //l.setLook(KLed::flat);
+ l->setShape(KLed::Circular);
+ //l->setShape(KLed::Rectangular);
+
+ //l->setLook(KLed::Flat);
+ //l->setLook(KLed::Flat);
+ //l->setLook(KLed::Flat);
+
+ l->move(5,5);
+ // ktmp tmpobj(l);
+
+ t_toggle.start(1000, false);
+ t_color.start(3500, false);
+ t_look.start(3500, false);
+ QObject::connect(&t_toggle, SIGNAL(timeout()), l, SLOT(toggle()));
+ QObject::connect(&t_color, SIGNAL(timeout()), this, SLOT(nextColor()));
+ QObject::connect(&t_look, SIGNAL(timeout()), this, SLOT(nextLook()));
+ l->show();
+ resize(240,140);
+ }
+ else {
+ y=Grid; index=0;
+ for( int shape=0; (int)shape<2; shape=(KLed::Shape)(shape+1)) {
+ x=Grid;
+ for( int look=0; (int)look<3; look=(KLed::Look)(look+1)) {
+ for(state=KLed::Off; (int)state<2; state=(KLed::State)(state+1))
+ {
+ leds[index]=new KLed(Qt::yellow, state,
+ (KLed::Look)(look+1),
+ (KLed::Shape)(shape+1), this);
+ leds[index]->setGeometry(x, y, LedWidth, LedHeight);
+ ++index;
+ x+=Grid+LedWidth;
+ }
+ }
+ y+=Grid+LedHeight;
+ }
+ setFixedSize(x+Grid, y+Grid);
+ connect(&timer, SIGNAL(timeout()), SLOT(timeout()));
+ timer.start(500);
+ }
+}
+
+
+KLedTest::~KLedTest()
+{
+ if (kled_round) {
+ delete l;
+ }
+}
+
+
+void
+KLedTest::nextColor() {
+
+ ledcolor++;
+ ledcolor%=4;
+
+ switch(ledcolor) {
+ default:
+ case 0: l->setColor(green); break;
+ case 1: l->setColor(blue); break;
+ case 2: l->setColor(red); break;
+ case 3: l->setColor(yellow); break;
+ }
+}
+
+
+void
+KLedTest::nextLook() {
+ register int tmp;
+ if (kled_round) {
+ tmp = (static_cast<int>(ledlook) +1 ) % 3 ;
+ }
+ else {
+ tmp = (static_cast<int>(ledlook) + 1) % 3;
+ }
+ ledlook = static_cast<KLed::Look>(tmp);
+ l->setLook(ledlook);
+ //qDebug("painting look %i", ledlook);
+ //l->repaint();
+}
+
+
+void
+KLedTest::timeout()
+{
+ const int NoOfLeds=sizeof(leds)/sizeof(leds[0]);
+ int count;
+ // -----
+ for(count=0; count<NoOfLeds; ++count)
+ {
+ if(leds[count]->state()==KLed::Off)
+ {
+ leds[count]->setState(KLed::On);
+ } else {
+ leds[count]->setState(KLed::Off);
+ }
+ }
+}
+
+
+/*#include <stdio.h>*/
+
+int main( int argc, char **argv )
+{
+ KApplication a( argc, argv, "KLedTest" );
+ KLedTest widget;
+ // -----
+ /*
+ if (argc>1) { // look out for round or circular led command
+ if (strncmp(argv[1],"-c",2)) {
+ // paint circular
+ printf("painting circular led\n");
+ widget.kled_round = true;
+ }
+ else if (strncmp(argv[1],"-r",2)) {
+ // paint rectangle
+ printf("painting rectangular led\n");
+ widget.kled_round = false;
+ }
+ }
+ */
+ a.setMainWidget(&widget);
+ widget.show();
+ return a.exec(); // go
+}
+
+#include "kledtest.moc"
+
diff --git a/kdeui/tests/kledtest.h b/kdeui/tests/kledtest.h
new file mode 100644
index 000000000..ad9ad3ffb
--- /dev/null
+++ b/kdeui/tests/kledtest.h
@@ -0,0 +1,56 @@
+#ifndef kledtest_h
+#define kledtest_h
+
+#include <qwidget.h>
+#include <qtimer.h>
+#include <stdlib.h>
+#include <kled.h>
+
+class KLedTest : public QWidget
+{
+ Q_OBJECT
+protected:
+ QTimer timer;
+ KLed *leds[/*KLed::NoOfShapes*/2* /*KLed::NoOfLooks*/3* /*KLed::NoOfStates*/2];
+ const int LedWidth;
+ const int LedHeight;
+ const int Grid;
+ KLed::Shape shape;
+ KLed::Look look;
+ KLed::State state;
+ int x, y, index;
+
+
+ QTimer t_toggle, t_color, t_look;
+ //KLed *l; // create lamp
+ //KLed *l; // create lamp
+ KLed *l; // create lamp
+ //KLed *l; // create lamp
+ //KLed *l; // create lamp
+ int ledcolor;
+ KLed::Look ledlook;
+
+ const QColor red;
+ const QColor blue;
+ const QColor green;
+ const QColor yellow;
+
+public:
+
+ KLedTest(QWidget* parent=0);
+ ~KLedTest();
+
+ bool kled_round;
+
+
+public slots:
+ void timeout();
+
+ void nextColor();
+ void nextLook();
+
+
+};
+
+#endif
+
diff --git a/kdeui/tests/klineeditdlgtest.cpp b/kdeui/tests/klineeditdlgtest.cpp
new file mode 100644
index 000000000..2c9dc5248
--- /dev/null
+++ b/kdeui/tests/klineeditdlgtest.cpp
@@ -0,0 +1,19 @@
+#include <kapplication.h>
+#include <klineeditdlg.h>
+
+#include <qstring.h>
+#include <qtextview.h>
+
+int main(int argc, char** argv)
+{
+ KApplication app(argc, argv, "klineedittest");
+ KLineEditDlg dialog( "_text", "_value", 0L );
+ if(dialog.exec())
+ {
+ qDebug("Accepted.");
+ } else {
+ qDebug("Rejected.");
+ }
+ return 0;
+}
+
diff --git a/kdeui/tests/klineedittest.cpp b/kdeui/tests/klineedittest.cpp
new file mode 100644
index 000000000..2b40163a1
--- /dev/null
+++ b/kdeui/tests/klineedittest.cpp
@@ -0,0 +1,137 @@
+#include <qstring.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qhbox.h>
+#include <qtimer.h>
+
+#include <kaboutdata.h>
+#include <kcmdlineargs.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kdialog.h>
+#include <klocale.h>
+#include <klineedit.h>
+#include <kglobalsettings.h>
+#include <kcompletionbox.h>
+
+#include "klineedittest.h"
+
+KLineEditTest::KLineEditTest (QWidget* widget, const char* name )
+ :QWidget( widget, name )
+{
+ QVBoxLayout* layout = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
+
+ QStringList list;
+ list << "Tree" << "Suuupa" << "Stroustrup" << "Stone" << "Slick"
+ << "Slashdot" << "Send" << "Peables" << "Mankind" << "Ocean"
+ << "Chips" << "Computer" << "Sandworm" << "Sandstorm" << "Chops";
+ list.sort();
+
+ m_lineedit = new KLineEdit( this, "klineedittest" );
+ m_lineedit->completionObject()->setItems( list );
+ m_lineedit->setFixedSize(500,30);
+ m_lineedit->setEnableSqueezedText( true );
+ connect( m_lineedit, SIGNAL( returnPressed() ), SLOT( slotReturnPressed() ) );
+ connect( m_lineedit, SIGNAL( returnPressed(const QString&) ),
+ SLOT( slotReturnPressed(const QString&) ) );
+
+ QHBox *hbox = new QHBox (this);
+ m_btnExit = new QPushButton( "E&xit", hbox );
+ m_btnExit->setFixedSize(100,30);
+ connect( m_btnExit, SIGNAL( clicked() ), SLOT( quitApp() ) );
+
+ m_btnReadOnly = new QPushButton( "&Read Only", hbox );
+ m_btnReadOnly->setToggleButton (true);
+ m_btnReadOnly->setFixedSize(100,30);
+ connect( m_btnReadOnly, SIGNAL( toggled(bool) ), SLOT( slotReadOnly(bool) ) );
+
+ m_btnEnable = new QPushButton( "Dis&able", hbox );
+ m_btnEnable->setToggleButton (true);
+ m_btnEnable->setFixedSize(100,30);
+ connect( m_btnEnable, SIGNAL( toggled(bool) ), SLOT( slotEnable(bool) ) );
+
+ m_btnHide = new QPushButton( "Hi&de", hbox );
+ m_btnHide->setFixedSize(100,30);
+ connect( m_btnHide, SIGNAL( clicked() ), SLOT( slotHide() ) );
+
+ layout->addWidget( m_lineedit );
+ layout->addWidget( hbox );
+ setCaption( "KLineEdit Unit Test" );
+}
+
+KLineEditTest::~KLineEditTest()
+{
+}
+
+void KLineEditTest::quitApp()
+{
+ kapp->closeAllWindows();
+}
+
+void KLineEditTest::show()
+{
+ if (m_lineedit->isHidden())
+ m_lineedit->show();
+
+ m_btnHide->setEnabled( true );
+
+ QWidget::show();
+}
+
+void KLineEditTest::slotReturnPressed()
+{
+ kdDebug() << "Return pressed" << endl;
+}
+
+void KLineEditTest::slotReturnPressed( const QString& text )
+{
+ kdDebug() << "Return pressed: " << text << endl;
+}
+
+void KLineEditTest::resultOutput( const QString& text )
+{
+ kdDebug() << "KlineEditTest Debug: " << text << endl;
+}
+
+void KLineEditTest::slotReadOnly( bool ro )
+{
+ m_lineedit->setReadOnly (ro);
+ QString text = (ro) ? "&Read Write" : "&Read Only";
+ m_btnReadOnly->setText (text);
+}
+
+void KLineEditTest::slotEnable (bool enable)
+{
+ m_lineedit->setEnabled (!enable);
+ QString text = (enable) ? "En&able":"Dis&able";
+ m_btnEnable->setText (text);
+}
+
+void KLineEditTest::slotHide()
+{
+ m_lineedit->hide();
+ m_btnHide->setEnabled( false );
+ m_lineedit->setText( "My dog ate the homework, whaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaa! I want my mommy!" );
+ QTimer::singleShot( 1000, this, SLOT(show()) );
+}
+
+int main ( int argc, char **argv)
+{
+ KAboutData aboutData( "klineedittest", "klineedittest", "1.0" );
+ KCmdLineArgs::init(argc, argv, &aboutData);
+ KApplication::addCmdLineOptions();
+
+ KApplication a;
+ KLineEditTest *t = new KLineEditTest();
+ //t->lineEdit()->setTrapReturnKey( true );
+ //t->lineEdit()->completionBox()->setTabHandling( false );
+ t->lineEdit()->setEnableSqueezedText( true );
+ t->lineEdit()->setText ("This is a really really really really really really "
+ "really really long line because I am a talkative fool!");
+ a.setMainWidget(t);
+ t->show();
+ return a.exec();
+}
+
+#include "klineedittest.moc"
diff --git a/kdeui/tests/klineedittest.h b/kdeui/tests/klineedittest.h
new file mode 100644
index 000000000..e3b87c30e
--- /dev/null
+++ b/kdeui/tests/klineedittest.h
@@ -0,0 +1,41 @@
+#ifndef _KLINEEDITTEST_H
+#define _KLINEEDITTEST_H
+
+#include <qwidget.h>
+#include <qguardedptr.h>
+
+class QString;
+class QPushButton;
+
+class KLineEdit;
+
+class KLineEditTest : public QWidget
+{
+ Q_OBJECT
+
+public:
+ KLineEditTest( QWidget *parent=0, const char *name=0 );
+ ~KLineEditTest();
+ KLineEdit* lineEdit() const { return m_lineedit; }
+
+public slots:
+ virtual void show ();
+
+private slots:
+ void quitApp();
+ void slotHide();
+ void slotEnable( bool );
+ void slotReadOnly( bool );
+ void slotReturnPressed();
+ void resultOutput( const QString& );
+ void slotReturnPressed( const QString& );
+
+protected:
+ QGuardedPtr<KLineEdit> m_lineedit;
+ QPushButton* m_btnExit;
+ QPushButton* m_btnReadOnly;
+ QPushButton* m_btnEnable;
+ QPushButton* m_btnHide;
+};
+
+#endif
diff --git a/kdeui/tests/klistviewtest.cpp b/kdeui/tests/klistviewtest.cpp
new file mode 100644
index 000000000..75c01e439
--- /dev/null
+++ b/kdeui/tests/klistviewtest.cpp
@@ -0,0 +1,39 @@
+#include <klistview.h>
+#include <kapplication.h>
+#include <kdialogbase.h>
+#include <qvbox.h>
+
+
+int main( int argc, char **argv )
+{
+ KApplication app( argc, argv, "klistviewtest" );
+ KDialogBase dialog;
+ KListView *view = new KListView( dialog.makeVBoxMainWidget() );
+ view->setSelectionModeExt( KListView::FileManager );
+ view->setDragEnabled( true );
+ view->setItemsMovable( false );
+ view->setAcceptDrops( true );
+ view->addColumn("Column 1");
+ view->addColumn("Column 2");
+ view->addColumn("Column 3");
+
+ new KListViewItem( view, "Item 1");
+ new KListViewItem( view, "Item 1");
+ new KListViewItem( view, "Item 1");
+ new KListViewItem( view, "Item 1");
+ new KListViewItem( view, "Item 1");
+ new KListViewItem( view, "Item 1");
+ new KListViewItem( view, "Item 1");
+ new KListViewItem( view, "Item 1");
+ new KListViewItem( view, "Item 1");
+ new KListViewItem( view, "Item 2", "Some more", "Hi Mom :)" );
+
+ view->restoreLayout( KGlobal::config(), "ListView" );
+
+ new KListViewItem( view, "Item 3" );
+
+ dialog.exec();
+ view->saveLayout( KGlobal::config(), "ListView" );
+
+ return 0;
+}
diff --git a/kdeui/tests/kmainwindowrestoretest.cpp b/kdeui/tests/kmainwindowrestoretest.cpp
new file mode 100644
index 000000000..35198a6c2
--- /dev/null
+++ b/kdeui/tests/kmainwindowrestoretest.cpp
@@ -0,0 +1,41 @@
+
+#include "kmainwindowrestoretest.h"
+
+#include <kapplication.h>
+
+#include <qlabel.h>
+
+#define MAKE_WINDOW( kind, title ) do { \
+ MainWin##kind * m = new MainWin##kind; \
+ m->setCaption( title ); \
+ m->setCentralWidget( new QLabel( title, m ) ); \
+ m->show(); \
+} while ( false )
+
+int main( int argc, char * argv[] ) {
+
+ KApplication app( argc, argv, "kmainwindowrestoretest" );
+
+ if ( kapp->isRestored() ) {
+ kRestoreMainWindows< MainWin1, MainWin2, MainWin3 >();
+ kRestoreMainWindows< MainWin4, MainWin5 >();
+ RESTORE(MainWin6);
+ //kRestoreMainWindows< MainWin6 >(); // should be equivalent to RESTORE()
+ } else {
+ MAKE_WINDOW( 1, "First 1" );
+ MAKE_WINDOW( 1, "Second 1" );
+ MAKE_WINDOW( 2, "Only 2" );
+ MAKE_WINDOW( 3, "First 3" );
+ MAKE_WINDOW( 4, "First 4" );
+ MAKE_WINDOW( 4, "Second 4" );
+ MAKE_WINDOW( 3, "Second 3" );
+ MAKE_WINDOW( 4, "Third 4" );
+ MAKE_WINDOW( 5, "First 5" );
+ MAKE_WINDOW( 5, "Second 5" );
+ MAKE_WINDOW( 1, "Only 6" );
+ }
+
+ return app.exec();
+}
+
+#include "kmainwindowrestoretest.moc"
diff --git a/kdeui/tests/kmainwindowrestoretest.h b/kdeui/tests/kmainwindowrestoretest.h
new file mode 100644
index 000000000..7bd535f74
--- /dev/null
+++ b/kdeui/tests/kmainwindowrestoretest.h
@@ -0,0 +1,48 @@
+#ifndef _KDEUI_TESTS_KMAINWINDOWRESTORETEST_H_
+#define _KDEUI_TESTS_KMAINWINDOWRESTORETEST_H_
+
+#include <kmainwindow.h>
+
+class MainWin1 : public KMainWindow {
+ Q_OBJECT
+public:
+ MainWin1() : KMainWindow() {}
+ virtual ~MainWin1() {}
+};
+
+class MainWin2 : public KMainWindow {
+ Q_OBJECT
+public:
+ MainWin2() : KMainWindow() {}
+ virtual ~MainWin2() {}
+};
+
+class MainWin3 : public KMainWindow {
+ Q_OBJECT
+public:
+ MainWin3() : KMainWindow() {}
+ virtual ~MainWin3() {}
+};
+
+class MainWin4 : public KMainWindow {
+ Q_OBJECT
+public:
+ MainWin4() : KMainWindow() {}
+ virtual ~MainWin4() {}
+};
+
+class MainWin5 : public KMainWindow {
+ Q_OBJECT
+public:
+ MainWin5() : KMainWindow() {}
+ virtual ~MainWin5() {}
+};
+
+class MainWin6 : public KMainWindow {
+ Q_OBJECT
+public:
+ MainWin6() : KMainWindow() {}
+ virtual ~MainWin6() {}
+};
+
+#endif // _KDEUI_TESTS_KMAINWINDOWRESTORETEST_H_
diff --git a/kdeui/tests/kmainwindowtest.cpp b/kdeui/tests/kmainwindowtest.cpp
new file mode 100644
index 000000000..6ab8d33a0
--- /dev/null
+++ b/kdeui/tests/kmainwindowtest.cpp
@@ -0,0 +1,38 @@
+#include <qtimer.h>
+#include <qlabel.h>
+
+#include <kapplication.h>
+#include <kstatusbar.h>
+#include <kmenubar.h>
+
+#include "kmainwindowtest.h"
+
+MainWindow::MainWindow()
+{
+ QTimer::singleShot( 2*1000, this, SLOT( showMessage() ) );
+
+ setCentralWidget( new QLabel( "foo", this ) );
+
+ menuBar()->insertItem( "hi" );
+}
+
+void MainWindow::showMessage()
+{
+ statusBar()->show();
+ statusBar()->message( "test" );
+}
+
+int main( int argc, char **argv )
+{
+ KApplication app( argc, argv, "kmainwindowtest" );
+
+ MainWindow* mw = new MainWindow; // deletes itself when closed
+ mw->show();
+
+ return app.exec();
+}
+
+#include "kmainwindowtest.moc"
+
+/* vim: et sw=4 ts=4
+ */
diff --git a/kdeui/tests/kmainwindowtest.h b/kdeui/tests/kmainwindowtest.h
new file mode 100644
index 000000000..4fb426ac5
--- /dev/null
+++ b/kdeui/tests/kmainwindowtest.h
@@ -0,0 +1,18 @@
+#ifndef KMAINWINDOWTEST_H
+#define KMAINWINDOWTEST_H
+
+#include <kmainwindow.h>
+
+class MainWindow : public KMainWindow
+{
+ Q_OBJECT
+public:
+ MainWindow();
+
+private slots:
+ void showMessage();
+};
+
+#endif // KMAINWINDOWTEST_H
+/* vim: et sw=4 ts=4
+ */
diff --git a/kdeui/tests/kmessageboxtest.cpp b/kdeui/tests/kmessageboxtest.cpp
new file mode 100644
index 000000000..372bef16a
--- /dev/null
+++ b/kdeui/tests/kmessageboxtest.cpp
@@ -0,0 +1,242 @@
+#include "kmessagebox.h"
+
+#include <qdialog.h>
+#include <qlayout.h>
+
+#include <stdlib.h>
+
+#include <stdio.h>
+
+#include <kstatusbar.h>
+#include <kapplication.h>
+
+#include <kglobal.h>
+
+class ExampleWidget : public QLabel
+{
+public:
+ ExampleWidget( QWidget *parent = 0, const char *name = 0 );
+};
+
+ExampleWidget::ExampleWidget( QWidget *parent, const char *name )
+ : QLabel(parent, name )
+{
+ // Make the top-level layout; a vertical box to contain all widgets
+ // and sub-layouts.
+ QSize sh;
+ setText("<p>Hello.</p>");
+ sh = sizeHint();
+ qWarning("SizeHint = %d x %d", sh.width(), sh.height());
+ setText("Hello.");
+ sh = sizeHint();
+ qWarning("SizeHint = %d x %d", sh.width(), sh.height());
+ setText("<p>Hello<br>World</p>");
+ sh = sizeHint();
+ qWarning("SizeHint = %d x %d", sh.width(), sh.height());
+// setText("Hello\nWorld");
+ sh = sizeHint();
+ qWarning("SizeHint = %d x %d", sh.width(), sh.height());
+ setMinimumSize(sizeHint());
+}
+
+
+class Foo: public QDialog
+{
+ public:
+ Foo() : QDialog(0, "foo", true) { resize(200,200); new QLabel("Hello World", this); show(); }
+};
+
+void showResult(int test, int i)
+{
+ printf("%d. returned %d ", test, i);
+ switch( i) {
+ case KMessageBox::Ok : printf("(%s)\n", "Ok"); break;
+ case KMessageBox::Cancel : printf("(%s)\n", "Cancel"); break;
+ case KMessageBox::Yes : printf("(%s)\n", "Yes"); break;
+ case KMessageBox::No : printf("(%s)\n", "No"); break;
+ case KMessageBox::Continue : printf("(%s)\n", "Continue"); break;
+ default: printf("(%s)\n", "ERROR!"); exit(1);
+ }
+}
+
+
+int main( int argc, char *argv[] )
+{
+ int i, test;
+ new KApplication( argc, argv, "MyApplication" );
+
+ ExampleWidget *w = new ExampleWidget();
+ w->show();
+ w->deleteLater();
+
+ QStringList list; list.append("Hello"); list.append("World");
+
+ for( test = 1; true; test++)
+ {
+ switch(test)
+ {
+case 1:
+ i = KMessageBox::warningContinueCancel(w,
+ "You are about to <Print>.\n"
+ "Are you sure?",
+ "Print", QString::fromLatin1("&Print"), "dontask", false);
+ i = KMessageBox::warningContinueCancel(0,
+ "You are about to <Print>.\n"
+ "Are you sure?",
+ "Print", QString::fromLatin1("&Print"), "dontask", KMessageBox::AllowLink);
+ i = KMessageBox::questionYesNo(0, "<p>Do you have a printer? thisisaverylongdkldhklghklghklashgkllasghkdlsghkldfghklsabla bla bbla bla. It also has <a href=http://www.kde.org>this URL</a>.</p>",
+ QString("Bla"), QString("Yes"), QString("No"), "bla", KMessageBox::AllowLink);
+ break;
+
+case 2:
+ i = KMessageBox::questionYesNo(0, "Do you have a printer?",
+ QString("Printer setup"), QString::null);
+ break;
+
+case 3:
+ i = KMessageBox::questionYesNo(0,
+ "Does your printer support color or only black and white?",
+ "Printer setup", QString::fromLatin1("&Color"), QString::fromLatin1("&Black & White"));
+ break;
+
+case 4:
+ i = KMessageBox::warningYesNo(0,
+ "KDVI could not locate the program 'dvipdfm' on your computer. That program is "
+ "absolutely needed by the export function. You can, however, convert "
+ "the DVI-file to PDF using the print function of KDVI, but that will often "
+ "produce files which print ok, but are of inferior quality if viewed in the "
+ "Acrobat Reader. It may be wise to upgrade to a more recent version of your "
+ "TeX distribution which includes the 'dvipdfm' program.\n"
+ "Hint to the perplexed system administrator: KDVI uses the shell's PATH variable "
+ "when looking for programs."
+ );
+ break;
+
+
+case 5:
+ i = KMessageBox::warningYesNo(0, "Your printer has been added.\n"
+ "Do you want to update your configuration?",
+ "Printer Setup");
+ break;
+
+case 6:
+ i = KMessageBox::warningContinueCancel(0,
+ "You are about to print.\n"
+ "Are you sure?",
+ "Print", QString::fromLatin1("&Print"));
+ break;
+case 7:
+ i = KMessageBox::warningContinueCancel(0,
+ "You are about to <Print>.\n"
+ "Are you sure?",
+ "Print", QString::fromLatin1("&Print"), "dontask", false);
+ break;
+
+case 8:
+ i = KMessageBox::warningYesNoCancel(0,
+ "Your document contains unsaved changes.\n"
+ "Do you want to save your changes?\n");
+ break;
+
+case 9:
+ i = KMessageBox::warningYesNoCancel(0,
+ "Your document contains unsaved changes.\n"
+ "Do you want to save your changes?\n",
+ QString::fromLatin1("Close"));
+ break;
+
+case 10:
+ i = KMessageBox::warningYesNoCancel(0,
+ "Your document contains unsaved changes.\n"
+ "Do you want to save or discard your changes?\n",
+ "Close", QString::fromLatin1("&Save"), QString::fromLatin1("&Discard") );
+ break;
+
+case 11:
+ i = KMessageBox::Ok;
+ KMessageBox::error(0, "Oops, Your harddisk is unreadable.");
+ break;
+
+case 12:
+ i = KMessageBox::Ok;
+ KMessageBox::error(0, "Oops, Your harddisk is unreadable." , "Uh ooh");
+ break;
+
+case 13:
+ i = KMessageBox::Ok;
+ KMessageBox::sorry(0, "Sorry, Your harddisk appears to be empty.");
+ break;
+
+case 14:
+ i = KMessageBox::Ok;
+ KMessageBox::sorry(0, "Sorry, Your harddisk appears to be empty.", "Oops");
+ break;
+
+case 15:
+ i = KMessageBox::Ok;
+ KMessageBox::information(0, "You can enable the menubar again "
+ "with the right mouse button menu.");
+ break;
+
+case 16:
+ i = KMessageBox::Ok;
+ KMessageBox::information(0, "You can enable the menubar again "
+ "with the right mouse button menu.", "Menubar Info");
+ break;
+
+case 17:
+ i = KMessageBox::Ok;
+ KMessageBox::information(0, "You can enable the menubar again\nwith the right mouse button menu.", QString::null, "Enable_Menubar");
+ break;
+
+case 18:
+ i = KMessageBox::Ok;
+ KMessageBox::enableAllMessages();
+ break;
+
+case 19:
+ i = KMessageBox::Ok;
+ KMessageBox::information(0, "Return of the annoying popup message.", QString::null, "Enable_Menubar");
+ break;
+case 20:
+ {
+ QStringList strlist;
+ strlist << "/dev/hda" << "/etc/inittab" << "/usr/somefile" << "/some/really/"
+ "long/file/name/which/is/in/a/really/deep/directory/in/a/really/large/"
+ "hard/disk/of/your/system" << "/and/another/one" ;
+ i = KMessageBox::questionYesNoList(0, "Do you want to delete the following files ?",strlist);
+ }
+ break;
+case 21:
+ {
+ QStringList strlist;
+ printf("Filling StringList...\n");
+ for (int j=1;j<=6000;j++) strlist.append(QString("/tmp/tmp.%1").arg(j));
+ printf("Completed...\n");
+ i = KMessageBox::questionYesNoList(0, "Do you want to delete the following files ?",strlist);
+ }
+ break;
+
+case 22:
+ i = KMessageBox::Ok;
+ KMessageBox::informationList(0, "The following words have been found:",list);
+ break;
+
+case 23:
+ i = KMessageBox::Ok;
+ KMessageBox::informationList(0, "The following words have been found:", list, "Search Words");
+ break;
+
+case 24:
+ i = KMessageBox::Ok;
+ KMessageBox::informationList(0, "The follwoing words have been found:", list, QString::null, "Search_Words");
+ break;
+
+default:
+ return 0;
+ } // Switch
+
+ showResult(test, i);
+ } // Test
+}
+
diff --git a/kdeui/tests/knuminputtest.cpp b/kdeui/tests/knuminputtest.cpp
new file mode 100644
index 000000000..b3d8e9067
--- /dev/null
+++ b/kdeui/tests/knuminputtest.cpp
@@ -0,0 +1,145 @@
+/*
+* Tests the KNumInput Widget class
+*
+* Copyright (c) 1999 by Dirk A. Mueller <dmuell@gmx.net>
+*
+* License: GPL, version 2
+* Version: $Id:
+*
+*/
+
+#include <qlayout.h>
+#include <qvgroupbox.h>
+
+#include <kapplication.h>
+#include <knuminput.h>
+
+#include "knuminputtest.h"
+
+KApplication *a;
+
+#include <kdebug.h>
+void TopLevel::slotPrint( int n ) {
+ kdDebug() << "slotPrint( " << n << " )" << endl;
+}
+void TopLevel::slotPrint( double n ) {
+ kdDebug() << "slotPrint( " << n << " )" << endl;
+}
+
+#define conn(x,y) connect( x, SIGNAL(valueChanged(y)), SLOT(slotPrint(y)))
+TopLevel::TopLevel(QWidget *parent, const char *name)
+ : QWidget(parent, name)
+{
+ setCaption("KNumInput test application");
+
+ QBoxLayout* l = new QHBoxLayout(this, 10);
+
+ QGroupBox* b1 = new QVGroupBox("KIntNumInput", this);
+
+ i1 = new KIntNumInput(42, b1, 10, "perc_no_slider");
+ i1->setLabel("percent of usage (no slider)");
+ i1->setRange(0, 100, 5, false);
+ conn(i1,int);
+
+ i2 = new KIntNumInput(i1, 42, b1);
+ i2->setLabel("percentage of usage (with slider)");
+ i2->setRange(0, 100, 5);
+ i2->setSuffix(" %");
+ conn(i2,int);
+
+ i3 = new KIntNumInput(i2, 0xAF, b1, 16);
+ i3->setLabel("Hex byte (no slider)");
+ i3->setRange(0, 255, 1, false);
+ i3->setSuffix(" (hex)");
+ conn(i3,int);
+
+ i4 = new KIntNumInput(i3, 0xfe, b1, 16);
+ i4->setLabel("Hex byte (with slider)");
+ i4->setRange(0, 255, 1);
+ conn(i4,int);
+
+ i5 = new KIntNumInput(i4, 10, b1, 10);
+ i5->setLabel("Width (keeps aspect ratio):");
+ i5->setRange(0, 200, 1, false);
+ i5->setReferencePoint( 5 );
+
+ i6 = new KIntNumInput(i5, 20, b1, 10);
+ i6->setLabel("Height (should be 2xWidth):");
+ i6->setRange(0, 200, 1, false);
+ i6->setReferencePoint( 10 );
+ connect( i5, SIGNAL(relativeValueChanged(double)),
+ i6, SLOT(setRelativeValue(double)) );
+ connect( i6, SIGNAL(relativeValueChanged(double)),
+ i5, SLOT(setRelativeValue(double)) );
+
+ i7 = new KIntNumInput(i6, 0, b1, 10);
+ i7->setLabel("math test:", AlignVCenter|AlignLeft );
+ i7->setRange( INT_MIN, INT_MAX, 1 );
+ conn(i7,int);
+
+ l->addWidget(b1);
+
+ QGroupBox* b2 = new QVGroupBox("KDoubleNumInput", this);
+
+ d1 = new KDoubleNumInput(4.0, b2, "perc_double_no_slider");
+ d1->setLabel("percent of usage (no slider)", AlignTop | AlignRight);
+ d1->setRange(0.0, 4000.0, 0.01, false);
+ //d1->setValue(1.00000000000000000001);
+ conn(d1,double);
+
+ d2 = new KDoubleNumInput(d1, 0.422, b2, "perc_double_with_slider");
+ d2->setLabel("percentage of usage (with slider)", AlignBottom | AlignLeft);
+ d2->setRange(0, 1.0, 0.005);
+ d2->setSuffix("%");
+ conn(d2,double);
+
+ d3 = new KDoubleNumInput(d2, 16.20, b2);
+ d3->setLabel("cash: ", AlignVCenter | AlignHCenter);
+ d3->setRange(0.10, 100, 0.1);
+ d3->setPrefix("p");
+ d3->setSuffix("$");
+ conn(d3,double);
+
+ d4 = new KDoubleNumInput(d3, INT_MAX/10000.0, b2);
+ d4->setPrecision(3);
+ d4->setRange(double(INT_MIN+1)/1000.0, double(INT_MAX)/1000.0, 1);
+ d4->setLabel("math test: ", AlignVCenter | AlignLeft);
+// d4->setFormat("%g");
+ conn(d4,double);
+
+ d5 = new KDoubleNumInput(d4, double(INT_MIN+1)/1e9, double(INT_MAX-1)/1e9,
+ 0.1, 0.001, 9, b2, "d5");
+ d5->setLabel("math test 2: ", AlignVCenter|AlignLeft);
+ conn(d5,double);
+
+ d6 = new KDoubleNumInput(d5, -10, 10, 0, 0.001, 3, b2, "d6");
+ d6->setLabel("aspect ratio test with a negative ratio:");
+ d6->setReferencePoint( 1 );
+
+ d7 = new KDoubleNumInput(d6, -30, 30, 0, 0.001, 3, b2, "d7");
+ d7->setReferencePoint( -3 );
+
+ connect( d6, SIGNAL(relativeValueChanged(double)),
+ d7, SLOT(setRelativeValue(double)) );
+ connect( d7, SIGNAL(relativeValueChanged(double)),
+ d6, SLOT(setRelativeValue(double)) );
+
+ l->addWidget(b2);
+}
+
+
+
+
+int main( int argc, char ** argv )
+{
+ a = new KApplication ( argc, argv, "KNuminputTest" );
+
+ TopLevel *toplevel = new TopLevel(0, "knuminputtest");
+
+ toplevel->show();
+ a->setMainWidget(toplevel);
+ a->exec();
+}
+
+#include "knuminputtest.moc"
+
diff --git a/kdeui/tests/knuminputtest.h b/kdeui/tests/knuminputtest.h
new file mode 100644
index 000000000..e4a979e48
--- /dev/null
+++ b/kdeui/tests/knuminputtest.h
@@ -0,0 +1,23 @@
+#ifndef _KNUMINPUTTEST_H
+#define _KNUMINPUTTEST_H
+
+#include <qwidget.h>
+
+class KIntNumInput;
+class KDoubleNumInput;
+
+class TopLevel : public QWidget
+{
+ Q_OBJECT
+public:
+
+ TopLevel( QWidget *parent=0, const char *name=0 );
+protected:
+ KIntNumInput* i1, *i2, *i3, *i4, *i5, *i6, *i7;
+ KDoubleNumInput* d1, *d2, *d3, *d4, *d5, *d6, *d7;
+protected slots:
+ void slotPrint( int );
+ void slotPrint( double );
+};
+
+#endif
diff --git a/kdeui/tests/kpalettetest.cpp b/kdeui/tests/kpalettetest.cpp
new file mode 100644
index 000000000..d75563ec5
--- /dev/null
+++ b/kdeui/tests/kpalettetest.cpp
@@ -0,0 +1,38 @@
+
+#include <kapplication.h>
+#include <qwidget.h>
+#include <qtimer.h>
+#include <stdlib.h>
+#include "kpalette.h"
+#include "kledtest.h"
+#include <stdio.h>
+
+#include <qstringlist.h>
+
+
+int main( int argc, char **argv )
+{
+ KApplication a( argc, argv, "KPalettetest" );
+
+ QStringList palettes = KPalette::getPaletteList();
+ for(QStringList::ConstIterator it = palettes.begin();
+ it != palettes.end(); it++)
+ {
+ printf("Palette = %s\n", (*it).ascii());
+
+ KPalette myPalette = KPalette(*it);
+
+ printf("Palette Name = \"%s\"\n", myPalette.name().ascii());
+ printf("Description:\n\"%s\"\n", myPalette.description().ascii());
+ printf("Nr of Colors = %d\n", myPalette.nrColors());
+ for(int i = 0; i < myPalette.nrColors(); i++)
+ {
+ int r,g,b;
+ myPalette.color(i).rgb(&r, &g, &b);
+ printf("#%d Name = \"%s\" #%02x%02x%02x\n",
+ i, myPalette.colorName(i).ascii(), r,g,b);
+ }
+ }
+}
+
+
diff --git a/kdeui/tests/kpanelmenutest.cpp b/kdeui/tests/kpanelmenutest.cpp
new file mode 100644
index 000000000..4ff13b89c
--- /dev/null
+++ b/kdeui/tests/kpanelmenutest.cpp
@@ -0,0 +1,72 @@
+#include "kpanelmenutest.h"
+#include <kapplication.h>
+#include <kstandarddirs.h>
+#include <dcopclient.h>
+
+TestWidget::TestWidget(QWidget *parent, const char *name)
+ : QLabel(parent, name)
+{
+ testMenu = new KPanelAppMenu(locate("mini", "x.png"), "Client Test", this,
+ "menu1");
+
+ subMenu = testMenu->insertMenu(locate("mini", "x.png"), "Submenu Test");
+ subMenu->insertItem(locate("mini", "bx2.png"), "First Entry", 100);
+ subMenu->insertItem(locate("mini", "bx2.png"), "Second Entry", 101);
+
+ KPanelAppMenu *ssub = subMenu->insertMenu(locate("mini", "x.png"), "One more");
+
+ connect(testMenu, SIGNAL(activated(int)), SLOT(slotMenuCalled(int)));
+ connect(subMenu, SIGNAL(activated(int)), SLOT(slotSubMenuCalled(int)));
+ init();
+
+ setText("We added \"Client Test\" to kicker. Click the K Menu to check.");
+ resize(sizeHint());
+}
+
+void TestWidget::init()
+{
+ testMenu->insertItem(locate("mini", "bx2.png"),
+ "Add another entry!", 1);
+ testMenu->insertItem("Attention, this will clear the menu", 2);
+}
+
+void TestWidget::slotMenuCalled(int id)
+{
+ switch ( id ) {
+ case 1:
+ setText("Selected \"Add another entry!\" ");
+ testMenu->insertItem("Another entry");
+ break;
+ case 2:
+ setText("Selected \"Attention, this will clear the menu\"");
+ testMenu->clear();
+ init();
+ break;
+ default:
+ setText("Selected \"Another entry...\"");
+ }
+}
+
+
+void TestWidget::slotSubMenuCalled(int id)
+{
+ QString msg("Called with id=%1");
+ setText(msg.arg(id));
+}
+
+
+int main(int argc, char **argv)
+{
+ KApplication *app = new KApplication(argc, argv, "menutest");
+
+ TestWidget w;
+ app->setMainWidget(&w);
+ w.show();
+
+ app->exec();
+}
+
+#include "kpanelmenutest.moc"
+
+
+
diff --git a/kdeui/tests/kpanelmenutest.h b/kdeui/tests/kpanelmenutest.h
new file mode 100644
index 000000000..0e0e4a728
--- /dev/null
+++ b/kdeui/tests/kpanelmenutest.h
@@ -0,0 +1,21 @@
+#ifndef __KPANELMENUTEST_H
+#define __KPANELMENUTEST_H
+
+#include <kpanelappmenu.h>
+#include <qlabel.h>
+
+class TestWidget : public QLabel
+{
+ Q_OBJECT
+public:
+ TestWidget(QWidget *parent=0, const char *name=0);
+ ~TestWidget(){delete testMenu;}
+public slots:
+ void slotMenuCalled(int id);
+ void slotSubMenuCalled(int id);
+private:
+ void init();
+ KPanelAppMenu *testMenu, *subMenu;
+};
+
+#endif
diff --git a/kdeui/tests/kpixmapregionselectordialogtest.cpp b/kdeui/tests/kpixmapregionselectordialogtest.cpp
new file mode 100644
index 000000000..7d57c4234
--- /dev/null
+++ b/kdeui/tests/kpixmapregionselectordialogtest.cpp
@@ -0,0 +1,33 @@
+#include "kpixmapregionselectordialog.h"
+#include <qpixmap.h>
+#include <qimage.h>
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <iostream>
+
+static const KCmdLineOptions options[] =
+{
+ { "+file", "The image file to open", 0 },
+ KCmdLineLastOption
+};
+
+int main(int argc, char**argv)
+{
+ KCmdLineArgs::init(argc, argv, "test", "test" ,"test" ,"1.0");
+ KCmdLineArgs::addCmdLineOptions( options );
+ KApplication app("test");
+
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+ if (args->count()!=1)
+ {
+ std::cout << "Usage: kpixmapregionselectordialogtest <imageFile>" << std::endl;
+ return 1;
+ }
+
+ QImage image=
+ KPixmapRegionSelectorDialog::getSelectedImage(QPixmap(args->arg(0)),100,100);
+
+ image.save("output.png", "PNG");
+
+ return 0;
+}
diff --git a/kdeui/tests/kpopuptest.cpp b/kdeui/tests/kpopuptest.cpp
new file mode 100644
index 000000000..43e3c0958
--- /dev/null
+++ b/kdeui/tests/kpopuptest.cpp
@@ -0,0 +1,40 @@
+#include <kapplication.h>
+#include <qwidget.h>
+#include <qcursor.h>
+#include "kpopupmenu.h"
+
+class DemoWidget : public QWidget {
+private:
+ KPopupMenu *menu;
+
+void mousePressEvent(QMouseEvent *)
+{
+ menu->popup(QCursor::pos());
+}
+
+void paintEvent(QPaintEvent *)
+{
+ drawText(32, 32, "Press a Mouse Button!");
+}
+
+public:
+ DemoWidget() : QWidget()
+ {
+ menu = new KPopupMenu("Popup Menu:");
+ menu->insertItem("Item1");
+ menu->insertItem("Item2");
+ menu->insertSeparator();
+ menu->insertItem("Quit", qApp, SLOT(quit()));
+ }
+};
+
+int main(int argc, char **argv)
+{
+ KApplication app(argc, argv, "kpopupmenutest");
+ DemoWidget w;
+ app.setMainWidget(&w);
+ w.setFont(QFont("helvetica", 12, QFont::Bold), true);
+ w.show();
+ return app.exec();
+}
+
diff --git a/kdeui/tests/kprogresstest.cpp b/kdeui/tests/kprogresstest.cpp
new file mode 100644
index 000000000..d748fcb0f
--- /dev/null
+++ b/kdeui/tests/kprogresstest.cpp
@@ -0,0 +1,58 @@
+#include <kapplication.h>
+#include <qwidget.h>
+#include "kprogress.h"
+
+
+class MyWidget : public QWidget {
+public:
+ MyWidget() : QWidget()
+ {
+ setFixedSize(440, 80);
+ Progress = new KProgress(this);
+ Progress->resize(400, 40);
+ Progress->move(20, 20);
+ startTimer(50);
+ }
+
+private:
+ KProgress *Progress;
+
+ void timerEvent(QTimerEvent *);
+};
+
+void MyWidget::timerEvent(QTimerEvent *)
+{
+ static enum { fwd, back } direction = fwd;
+ //static KProgress::BarStyle style = KProgress::Solid;
+ if (direction == fwd)
+ {
+ if (Progress->value() == Progress->maxValue())
+ direction = back;
+ else
+ Progress->advance(1);
+ }
+ else
+ {
+ if (Progress->value() == 0 /*Progress->minValue()*/)
+ {
+ direction = fwd;
+ //style = (style == KProgress::Solid)? KProgress::Blocked : KProgress::Solid;
+ //Progress->setBarStyle(style);
+ }
+ else
+ Progress->advance(-1);
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ KApplication app(argc, argv, "KProgressTest");
+ MyWidget w;
+
+ app.setMainWidget(&w);
+
+ w.show();
+
+ int ret = app.exec();
+ return ret;
+}
diff --git a/kdeui/tests/krulertest.cpp b/kdeui/tests/krulertest.cpp
new file mode 100644
index 000000000..1efe57643
--- /dev/null
+++ b/kdeui/tests/krulertest.cpp
@@ -0,0 +1,375 @@
+
+
+#include "krulertest.h"
+
+#include "kruler.h"
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qgroupbox.h>
+
+/*
+void
+MyCheckBox::mouseReleaseEvent(QMouseEvent *e )
+{
+ QButton::mouseReleaseEvent(e);
+ if ();
+}
+*/
+
+MouseWidget::MouseWidget( QWidget *parent, const char *name, WFlags f )
+ : QFrame(parent, name, f)
+{
+}
+
+void
+MouseWidget::mousePressEvent( QMouseEvent *e )
+{
+ mouseButtonDown = true;
+ emit newXPos(e->x());
+ emit newYPos(e->y());
+}
+
+void
+MouseWidget::mouseReleaseEvent( QMouseEvent * )
+{ mouseButtonDown = false; }
+
+void
+MouseWidget::mouseMoveEvent( QMouseEvent *e )
+{
+ if (mouseButtonDown) {
+ emit newXPos(e->x());
+ emit newYPos(e->y());
+ }
+}
+
+void
+MouseWidget::resizeEvent( QResizeEvent *r )
+{
+ emit newWidth(r->size().width());
+ emit newHeight(r->size().height());
+}
+
+
+KRulerTest::KRulerTest( const char *name )
+ : KMainWindow(0, name)
+{
+ mainframe = new QFrame(this);
+
+ layout = new QGridLayout(mainframe, 2, 2);
+
+ miniwidget = new QFrame(mainframe);
+ miniwidget->setFrameStyle(QFrame::WinPanel | QFrame::Raised);
+ bigwidget = new MouseWidget(mainframe);
+ bigwidget->setFrameStyle(QFrame::WinPanel | QFrame::Sunken);
+
+ // QRect bwrect = bigwidget->frameRect();
+ // qDebug("big rect: top%i left%i bottom%i right%i",
+ // bwrect.top(), bwrect.left(), bwrect.bottom(), bwrect.right());
+ hruler = new KRuler(Horizontal, mainframe);
+ // hruler->setRange( bwrect.left(), bwrect.right() );
+ hruler->setRange( 0, 1000 );
+ // hruler->setOffset( bwrect.left() - bigwidget->frameRect().left() );
+ hruler->setOffset( 0 );
+
+ vruler = new KRuler(Vertical, mainframe);
+ vruler->setFrameStyle(QFrame::WinPanel | QFrame::Sunken);
+ vruler->setOffset( 0 );
+ vruler->setRange( 0, 1000 );
+
+ connect( bigwidget, SIGNAL(newXPos(int)),
+ hruler, SLOT(slotNewValue(int)) );
+ connect( bigwidget, SIGNAL(newYPos(int)),
+ vruler, SLOT(slotNewValue(int)) );
+ connect( bigwidget, SIGNAL(newWidth(int)),
+ SLOT(slotNewWidth(int)) );
+ connect( bigwidget, SIGNAL(newHeight(int)),
+ SLOT(slotNewHeight(int)) );
+
+ layout->addWidget(miniwidget, 0, 0);
+ layout->addWidget(hruler, 0, 1);
+ layout->addWidget(vruler, 1, 0);
+ layout->addWidget(bigwidget, 1, 1);
+
+ mouse_message = new QLabel("Press and hold mouse button\nfor pointer movement", bigwidget);
+ mouse_message->adjustSize();
+ mouse_message->move(4,4);
+
+ showMarks = new QGroupBox("Show which marks ?", bigwidget);
+ showMarks->setFixedSize(140, 160);
+ showMarks->move(330,4);
+ showTM = new QCheckBox("show tiny marks", showMarks);
+ showTM->adjustSize();
+ showTM->move(5,15);
+ showTM->setChecked(true);
+ connect(showTM, SIGNAL(toggled(bool)), SLOT(slotSetTinyMarks(bool)) );
+ showLM = new QCheckBox("show little marks", showMarks);
+ showLM->adjustSize();
+ showLM->move(5,35);
+ showLM->setChecked(true);
+ connect(showLM, SIGNAL(toggled(bool)), SLOT(slotSetLittleMarks(bool)) );
+ showMM = new QCheckBox("show medium marks", showMarks);
+ showMM->adjustSize();
+ showMM->move(5,55);
+ showMM->setChecked(true);
+ connect(showMM, SIGNAL(toggled(bool)), SLOT(slotSetMediumMarks(bool)) );
+ showBM = new QCheckBox("show big marks", showMarks);
+ showBM->adjustSize();
+ showBM->move(5,75);
+ showBM->setChecked(true);
+ connect(showBM, SIGNAL(toggled(bool)), SLOT(slotSetBigMarks(bool)) );
+ showEM = new QCheckBox("show end marks", showMarks);
+ showEM->adjustSize();
+ showEM->move(5,95);
+ showEM->setChecked(true);
+ connect(showEM, SIGNAL(toggled(bool)), SLOT(slotSetEndMarks(bool)) );
+ showPT = new QCheckBox("show ruler pointer", showMarks);
+ showPT->adjustSize();
+ showPT->move(5,115);
+ showPT->setChecked(true);
+ connect(showPT, SIGNAL(toggled(bool)), SLOT(slotSetRulerPointer(bool)) );
+ fixLen = new QCheckBox("fix ruler length", showMarks);
+ fixLen->adjustSize();
+ fixLen->move(5,135);
+ fixLen->setChecked(true);
+ connect(fixLen, SIGNAL(toggled(bool)), SLOT(slotFixRulerLength(bool)) );
+ connect(fixLen, SIGNAL(toggled(bool)), SLOT(slotCheckLength(bool)) );
+
+ lineEdit = new QGroupBox("Value of begin/end", bigwidget);
+ lineEdit->setFixedSize(140, 80);
+ lineEdit->move(330,4+160);
+ beginMark = new KIntNumInput(0, lineEdit);
+ beginMark->setRange(-1000, 1000, 1, false);
+ beginMark->move(5, 15);
+ beginMark->setFixedSize(beginMark->sizeHint());
+ connect(beginMark, SIGNAL(valueChanged(int)),
+ hruler, SLOT(slotNewOffset(int)) );
+ connect(beginMark, SIGNAL(valueChanged(int)),
+ vruler, SLOT(slotNewOffset(int)) );
+ endMark = new KIntNumInput(0, lineEdit);
+ endMark->setRange(-1000, 1000, 1, false);
+ endMark->move(5, 35);
+ endMark->setFixedSize(endMark->sizeHint());
+ connect(endMark, SIGNAL(valueChanged(int)),
+ hruler, SLOT(slotEndOffset(int)) );
+ connect(endMark, SIGNAL(valueChanged(int)),
+ vruler, SLOT(slotEndOffset(int)) );
+ lengthInput = new KIntNumInput(0, lineEdit);
+ lengthInput->setRange(-1000, 1000, 1, false);
+ lengthInput->move(5, 55);
+ lengthInput->setFixedSize(lengthInput->sizeHint());
+ connect(lengthInput, SIGNAL(valueChanged(int)),
+ hruler, SLOT(slotEndOffset(int)) );
+ connect(lengthInput, SIGNAL(valueChanged(int)),
+ vruler, SLOT(slotEndOffset(int)) );
+
+
+ vertrot = new QGroupBox("Value of rotate translate for Vert.", bigwidget);
+ vertrot->setFixedSize(140, 80);
+ vertrot->move(330,4+160+80+4);
+ transX = new KDoubleNumInput(0.0, vertrot);
+ transX->setRange(-1000, 1000, 1, false);
+ transX->move(5, 15);
+ transX->setFixedSize(transX->sizeHint());
+ //transX->setLabel("transx", AlignLeft);
+ connect(transX, SIGNAL(valueChanged(double)),
+ SLOT(slotSetXTrans(double)) );
+ transY = new KDoubleNumInput(-12.0, vertrot);
+ transY->setRange(-1000, 1000, 1, false);
+ transY->move(5, 35);
+ transY->setFixedSize(transY->sizeHint());
+ //transY->setLabel("transy", AlignLeft);
+ connect(transY, SIGNAL(valueChanged(double)),
+ SLOT(slotSetYTrans(double)) );
+ rotV = new KDoubleNumInput(90.0, vertrot);
+ rotV->setRange(-1000, 1000, 1, false);
+ rotV->move(5, 55);
+ rotV->setFixedSize(rotV->sizeHint());
+ //rotV->setLabel("rot", AlignLeft);
+ connect(rotV, SIGNAL(valueChanged(double)),
+ SLOT(slotSetRotate(double)) );
+
+
+ metricstyle = new QButtonGroup("metric styles", bigwidget);
+ metricstyle->setFixedSize(100, 120);
+ metricstyle->move(330-110,4);
+ pixelmetric = new QRadioButton("pixel", metricstyle);
+ pixelmetric->adjustSize();
+ pixelmetric->move(5,15);
+ metricstyle->insert(pixelmetric, (int)KRuler::Pixel);
+ inchmetric = new QRadioButton("inch", metricstyle);
+ inchmetric->adjustSize();
+ inchmetric->move(5,35);
+ metricstyle->insert(inchmetric, (int)KRuler::Inch);
+ mmmetric = new QRadioButton("millimeter", metricstyle);
+ mmmetric->adjustSize();
+ mmmetric->move(5,55);
+ metricstyle->insert(mmmetric, (int)KRuler::Millimetres);
+ cmmetric = new QRadioButton("centimeter", metricstyle);
+ cmmetric->adjustSize();
+ cmmetric->move(5,75);
+ metricstyle->insert(cmmetric, (int)KRuler::Centimetres);
+ mmetric = new QRadioButton("meter", metricstyle);
+ mmetric->adjustSize();
+ mmetric->move(5,95);
+ metricstyle->insert(mmetric, (int)KRuler::Metres);
+ connect ( metricstyle, SIGNAL(clicked(int)), SLOT(slotSetMStyle(int)) );
+
+ setCentralWidget(mainframe);
+
+ slotUpdateShowMarks();
+}
+
+KRulerTest::~KRulerTest()
+{
+ delete layout;
+ delete hruler;
+ delete vruler;
+ delete miniwidget;
+ delete bigwidget;
+ delete mainframe;
+}
+
+void
+KRulerTest::slotNewWidth(int width)
+{
+ hruler->setMaxValue(width);
+}
+
+void
+KRulerTest::slotNewHeight(int height)
+{
+ vruler->setMaxValue(height);
+}
+
+void
+KRulerTest::slotSetTinyMarks(bool set)
+{
+ hruler->setShowTinyMarks(set);
+ vruler->setShowTinyMarks(set);
+}
+
+void
+KRulerTest::slotSetLittleMarks(bool set)
+{
+ hruler->setShowLittleMarks(set);
+ vruler->setShowLittleMarks(set);
+}
+
+void
+KRulerTest::slotSetMediumMarks(bool set)
+{
+ hruler->setShowMediumMarks(set);
+ vruler->setShowMediumMarks(set);
+}
+
+void
+KRulerTest::slotSetBigMarks(bool set)
+{
+ hruler->setShowBigMarks(set);
+ vruler->setShowBigMarks(set);
+}
+
+void
+KRulerTest::slotSetEndMarks(bool set)
+{
+ hruler->setShowEndMarks(set);
+ vruler->setShowEndMarks(set);
+}
+
+void
+KRulerTest::slotSetRulerPointer(bool set)
+{
+ hruler->setShowPointer(set);
+ vruler->setShowPointer(set);
+}
+
+void
+KRulerTest::slotSetRulerLength(int len)
+{
+ hruler->setLength(len);
+ vruler->setLength(len);
+}
+
+void
+KRulerTest::slotFixRulerLength(bool fix)
+{
+ hruler->setLengthFixed(fix);
+ vruler->setLengthFixed(fix);
+}
+
+void
+KRulerTest::slotSetMStyle(int style)
+{
+ hruler->setRulerMetricStyle((KRuler::MetricStyle)style);
+ vruler->setRulerMetricStyle((KRuler::MetricStyle)style);
+ slotUpdateShowMarks();
+}
+
+
+void
+KRulerTest::slotUpdateShowMarks()
+{
+ showTM->setChecked(hruler->showTinyMarks());
+ showLM->setChecked(hruler->showLittleMarks());
+ showMM->setChecked(hruler->showMediumMarks());
+ showBM->setChecked(hruler->showBigMarks());
+ showEM->setChecked(hruler->showEndMarks());
+}
+
+void
+KRulerTest::slotCheckLength(bool fixlen)
+{
+ beginMark->setValue(hruler->offset());
+ endMark->setValue(hruler->endOffset());
+ lengthInput->setValue(hruler->length());
+}
+
+void
+KRulerTest::slotSetRotate(double d)
+{
+#ifdef KRULER_ROTATE_TEST
+ vruler->rotate = d;
+ vruler->update();
+ //debug("rotate %.1f", d);
+#endif
+}
+
+void
+KRulerTest::slotSetXTrans(double d)
+{
+#ifdef KRULER_ROTATE_TEST
+ vruler->xtrans = d;
+ vruler->update();
+ //debug("trans x %.1f", d);
+#endif
+}
+
+void
+KRulerTest::slotSetYTrans(double d)
+{
+#ifdef KRULER_ROTATE_TEST
+ vruler->ytrans = d;
+ vruler->update();
+ //debug("trans y %.1f", d);
+#endif
+}
+
+
+/* --- MAIN -----------------------*/
+int main(int argc, char **argv)
+{
+ KApplication *testapp;
+ KRulerTest *window;
+
+ testapp = new KApplication(argc, argv,"krulertest");
+ testapp->setFont(QFont("Helvetica",12),true);
+
+ window = new KRulerTest("main");
+ testapp->setMainWidget(window);
+ window->setCaption("KRulerTest");
+ window->show();
+ return testapp->exec();
+}
+
+#include "krulertest.moc"
+
diff --git a/kdeui/tests/krulertest.h b/kdeui/tests/krulertest.h
new file mode 100644
index 000000000..ba9938deb
--- /dev/null
+++ b/kdeui/tests/krulertest.h
@@ -0,0 +1,91 @@
+/* -*- c++ -*- */
+
+#ifndef krulertest_h
+#define krulertest_h
+
+#include <kapplication.h>
+#include <kmainwindow.h>
+#include <qwidget.h>
+#include <qcheckbox.h>
+#include <qradiobutton.h>
+#include <qbuttongroup.h>
+#include <knuminput.h>
+
+class KRuler;
+class QWidget;
+class QFrame;
+class QGridLayout;
+class QCheckBox;
+class QGroupBox;
+
+
+class MouseWidget : public QFrame
+{
+Q_OBJECT
+public:
+MouseWidget( QWidget *parent=0, const char *name=0, WFlags f=0 );
+
+signals:
+ void newXPos(int);
+ void newYPos(int);
+ void newWidth(int);
+ void newHeight(int);
+
+protected:
+ virtual void mousePressEvent ( QMouseEvent * );
+ virtual void mouseReleaseEvent ( QMouseEvent * );
+ virtual void mouseMoveEvent ( QMouseEvent * );
+ virtual void resizeEvent ( QResizeEvent * );
+private:
+ bool mouseButtonDown;
+
+};
+
+
+class KRulerTest : public KMainWindow
+{
+Q_OBJECT
+public:
+KRulerTest( const char *name = 0L );
+~KRulerTest();
+
+private slots:
+ void slotNewWidth(int);
+ void slotNewHeight(int);
+
+ void slotSetTinyMarks(bool);
+ void slotSetLittleMarks(bool);
+ void slotSetMediumMarks(bool);
+ void slotSetBigMarks(bool);
+ void slotSetEndMarks(bool);
+ void slotSetRulerPointer(bool);
+
+ void slotSetRulerLength(int);
+ void slotFixRulerLength(bool);
+ void slotSetMStyle(int);
+ void slotUpdateShowMarks();
+ void slotCheckLength(bool);
+
+ void slotSetRotate(double);
+ void slotSetXTrans(double);
+ void slotSetYTrans(double);
+
+
+private:
+
+ KRuler *hruler, *vruler;
+ QGridLayout *layout;
+ QFrame *miniwidget, *bigwidget;
+ QFrame *mainframe;
+
+ QLabel *mouse_message;
+ QGroupBox *showMarks, *lineEdit, *vertrot;
+ QCheckBox *showTM, *showLM, *showMM, *showBM, *showEM, *showPT, *fixLen;
+ KIntNumInput *beginMark, *endMark, *lengthInput;
+ KDoubleNumInput *transX, *transY, *rotV;
+ QButtonGroup *metricstyle;
+ QRadioButton *pixelmetric, *inchmetric, *mmmetric, *cmmetric, *mmetric;
+
+};
+#endif
+
diff --git a/kdeui/tests/kseparatortest.cpp b/kdeui/tests/kseparatortest.cpp
new file mode 100644
index 000000000..2abd84448
--- /dev/null
+++ b/kdeui/tests/kseparatortest.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 1997 Michael Roth <mroth@wirlweb.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.
+ *
+ */
+
+
+#include <kapplication.h>
+#include <qlayout.h>
+#include <qwidget.h>
+
+#include "kseparator.h"
+
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+
+ QWidget *toplevel = new QWidget();
+
+ QBoxLayout *mainbox = new QBoxLayout(toplevel, QBoxLayout::TopToBottom, 10);
+
+ KSeparator *sep1 = new KSeparator( KSeparator::VLine, toplevel );
+ mainbox->addWidget(sep1);
+
+ KSeparator *sep2 = new KSeparator( KSeparator::HLine, toplevel );
+ mainbox->addWidget(sep2);
+
+ mainbox->activate();
+
+ app.setMainWidget(toplevel);
+ toplevel->show();
+ return app.exec();
+}
+
+
+
+
diff --git a/kdeui/tests/kspelltest.cpp b/kdeui/tests/kspelltest.cpp
new file mode 100644
index 000000000..4511edd6c
--- /dev/null
+++ b/kdeui/tests/kspelltest.cpp
@@ -0,0 +1,57 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1997 David Sweet <dsweet@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kspell.h"
+#include <kapplication.h>
+#include <kdebug.h>
+
+#include <qstring.h>
+#include <qlabel.h>
+#include <qtextcodec.h>
+
+int main(int argc, char **argv)
+{
+ KApplication *app = new KApplication(argc, argv, "KSpellTest");
+
+ // test ASCII
+ //QString text( "I have noo idee of how to wride englisch or englisch" );
+
+ // test Latin-3 (need dictionary "esperanto" and "Latin3" in config)
+ //QCString ctext( "sed jen: e¶oþanø' æiu¼aýde; e¶uþunøo øiun fendredon - kaj dimanøon...");
+ //QTextCodec *codec = QTextCodec::codecForName("ISO 8859-3");
+
+ // test UTF-8 (need dictionary "esperanto" and "UTF-8" in config)
+ QCString ctext( "sed jen: e\304\245oÅanÄo ĉiuĵaÅ­de e\304\245uÅunÄo Äiun fendredon kaj dimanÄon");
+ QTextCodec *codec = QTextCodec::codecForName("UTF-8");
+
+ QString text = codec->toUnicode(ctext.data());
+
+ KSpell::modalCheck( text );
+
+ kdDebug() << "Returned " << text << endl;
+
+ return 0;
+
+}
+
+
+
+
+
+
+
diff --git a/kdeui/tests/ksqueezedtextlabeltest.cpp b/kdeui/tests/ksqueezedtextlabeltest.cpp
new file mode 100644
index 000000000..62f3c1a76
--- /dev/null
+++ b/kdeui/tests/ksqueezedtextlabeltest.cpp
@@ -0,0 +1,13 @@
+#include "ksqueezedtextlabel.h"
+#include <kapplication.h>
+
+int main( int argc, char **argv )
+{
+ KApplication app( argc, argv, "KSqueezedTextLabelTest" );
+
+ KSqueezedTextLabel l( "This is a rather long string", 0);
+ app.setMainWidget( &l );
+ l.show();
+
+ return app.exec();
+}
diff --git a/kdeui/tests/kstatusbartest.cpp b/kdeui/tests/kstatusbartest.cpp
new file mode 100644
index 000000000..80b92c446
--- /dev/null
+++ b/kdeui/tests/kstatusbartest.cpp
@@ -0,0 +1,121 @@
+#include <qpopupmenu.h>
+#include <qwidget.h>
+#include <qstring.h>
+#include <qmessagebox.h>
+#include <qmultilineedit.h>
+#include <qkeycode.h>
+#include <qpixmap.h>
+#include <qcursor.h>
+
+#include <stdlib.h>
+
+#include "kstatusbar.h"
+#include <kapplication.h>
+#include <kmainwindow.h>
+#include <kmenubar.h>
+#include "kstatusbartest.h"
+
+testWindow::testWindow (QWidget *, const char *name)
+ : KMainWindow (0, name)
+ {
+ // Setup Menus
+ menuBar = new KMenuBar (this);
+ fileMenu = new QPopupMenu;
+ menuBar->insertItem ("&File", fileMenu);
+ fileMenu->insertItem ("&Exit", KApplication::kApplication(),
+ SLOT( quit() ), ALT + Key_Q );
+ statusbar = new KStatusBar (this);
+ statusbar->insertItem("Zoom: XXXX", 0);
+ statusbar->insertItem("XXX", 1);
+ statusbar->insertItem("Line: XXXXX", 2);
+
+ statusbar->changeItem("Zoom: 100%", 0);
+ statusbar->changeItem("INS", 1);
+ insert = true;
+ statusbar->changeItem("Line: 13567", 2);
+
+ connect (statusbar, SIGNAL(pressed(int)), this, SLOT(slotPress(int)));
+ connect (statusbar, SIGNAL(released(int)), this, SLOT(slotClick(int)));
+
+ widget = new QMultiLineEdit (this);
+
+ setCentralWidget(widget);
+
+ setCaption( KApplication::kApplication()->caption() );
+
+ smenu = new QPopupMenu;
+
+ smenu->insertItem("50%");
+ smenu->insertItem("75%");
+ smenu->insertItem("100%");
+ smenu->insertItem("150%");
+ smenu->insertItem("200%");
+ smenu->insertItem("400%");
+ smenu->insertItem("oo%");
+
+ connect (smenu, SIGNAL(activated(int)), this, SLOT(slotMenu(int)));
+}
+
+void testWindow::slotClick(int id)
+{
+ switch (id)
+ {
+ case 0:
+ break;
+
+ case 1:
+ if (insert == true)
+ {
+ insert = false;
+ statusbar->changeItem("OVR", 1);
+ }
+ else
+ {
+ insert = true;
+ statusbar->changeItem("INS", 1);
+ }
+ break;
+
+ case 2:
+ QMessageBox::information(0, "Go to line", "Enter line number:", "where?");
+ statusbar->changeItem("16543", 2);
+ break;
+ }
+}
+
+void testWindow::slotPress(int id)
+{
+ if (id == 0)
+ smenu->popup(QCursor::pos()); // This popup should understand keys up and down
+}
+
+void testWindow::slotMenu(int id)
+{
+ QString s = "Zoom: ";
+ s.append (smenu->text(id));
+ statusbar->changeItem(s,0);
+}
+
+testWindow::~testWindow ()
+{
+ // I would delete toolbars here, but there are none
+ delete statusbar;
+}
+
+int main( int argc, char *argv[] )
+{
+ KApplication *myApp = new KApplication( argc, argv, "KStatusBarTest" );
+ testWindow *test = new testWindow;
+
+ myApp->setMainWidget(test);
+ test->show();
+ test->resize(test->width(), test->height()); // I really really really dunno why it doesn't show
+ int ret = myApp->exec();
+
+ delete test;
+
+ return ret;
+}
+
+#include "kstatusbartest.moc"
+
diff --git a/kdeui/tests/kstatusbartest.h b/kdeui/tests/kstatusbartest.h
new file mode 100644
index 000000000..ea59073b6
--- /dev/null
+++ b/kdeui/tests/kstatusbartest.h
@@ -0,0 +1,33 @@
+#ifndef test_kstatusbar_h
+#define test_kstatusbar_h
+
+#include <kmenubar.h>
+#include <qpopupmenu.h>
+#include <kstatusbar.h>
+#include <kmainwindow.h>
+
+class QMultiLineEdit;
+
+class testWindow : public KMainWindow
+{
+ Q_OBJECT
+
+public:
+ testWindow (QWidget *parent=0, const char *name=0);
+ ~testWindow ();
+
+public slots:
+ void slotPress(int i);
+ void slotClick(int i);
+ void slotMenu(int i);
+
+protected:
+ QPopupMenu *fileMenu;
+ QPopupMenu *smenu;
+ KMenuBar *menuBar;
+ KStatusBar *statusbar;
+ bool insert;
+ QMultiLineEdit *widget;
+};
+#endif
+
diff --git a/kdeui/tests/ksystemtraytest.cpp b/kdeui/tests/ksystemtraytest.cpp
new file mode 100644
index 000000000..746246132
--- /dev/null
+++ b/kdeui/tests/ksystemtraytest.cpp
@@ -0,0 +1,14 @@
+#include <ksystemtray.h>
+#include <kapplication.h>
+
+int main(int argc, char **argv)
+{
+ KApplication app( argc, argv, "ksystemtraytest" );
+ QLabel *l = new QLabel("System Tray Main Window", 0L);
+ KSystemTray *tray = new KSystemTray( l );
+ tray->setText("Test");
+ l->show();
+ tray->show();
+
+ return app.exec();
+}
diff --git a/kdeui/tests/ktabctltest.cpp b/kdeui/tests/ktabctltest.cpp
new file mode 100644
index 000000000..20b7246c1
--- /dev/null
+++ b/kdeui/tests/ktabctltest.cpp
@@ -0,0 +1,105 @@
+/*
+ *
+ */
+
+#include <kapplication.h>
+#include <qpushbutton.h>
+#include <qlabel.h>
+#include <qobject.h>
+#include <qlistbox.h>
+#include <qgroupbox.h>
+#include <qevent.h>
+#include <qcombobox.h>
+#include <qlineedit.h>
+#include <qradiobutton.h>
+#include <qcheckbox.h>
+#include <qtabdialog.h>
+#include <qtooltip.h>
+#include <qmessagebox.h>
+#include <qtabbar.h>
+#include <qpalette.h>
+#include <qmultilineedit.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ktabctl.h"
+#include "ktabctltest.h"
+
+QFont default_font("Helvetica", 12);
+
+KApplication *a;
+
+TopLevel::TopLevel(QWidget *parent, const char *name)
+ : QWidget(parent, name)
+{
+ setCaption("KTabCtl test application");
+ setMinimumSize(300, 200);
+
+ /*
+ * add a tabctrl widget
+ */
+
+ test = new KTabCtl(this, "test");
+ connect(test, SIGNAL(tabSelected(int)), this, SLOT(tabChanged(int)));
+ QWidget *w = new QWidget(test, "_page1");
+ QPushButton *bt = new QPushButton("Click me to quit", w, "_bt1");
+ connect(bt, SIGNAL(clicked()), this, SLOT(okPressed()));
+ bt->adjustSize();
+ bt->move(20, 20);
+ test->addTab(w, "Seite 1");
+ pages[0] = w;
+ w = new QWidget(test, "_page2");
+ e = new QMultiLineEdit(w, "_editor");
+ e->setText("Write some usesless stuff here :-)");
+ w->resize(width(), height());
+ test->addTab(w, "Seite 2");
+ pages[1] = w;
+ w = new QWidget(test, "_page3");
+ bt = new QPushButton("This button does absolutely nothing", w, "_bt3");
+ bt->adjustSize();
+ bt->move(20, 20);
+ test->addTab(w, "Seite 3");
+ pages[2] = w;
+ test->resize(200, 200);
+ test->move(0, 0);
+ move(20, 20);
+ resize(400, 300);
+ adjustSize();
+}
+
+void TopLevel::resizeEvent( QResizeEvent * )
+{
+ test->resize(width(), height());
+ e->setGeometry(10, 10, pages[1]->width() - 20, pages[1]->height() - 20);
+}
+
+void TopLevel::tabChanged(int newpage)
+{
+ printf("tab number %d selected\n", newpage);
+ if(newpage == 1)
+ e->setFocus();
+}
+
+void TopLevel::okPressed()
+{
+ a->quit();
+}
+
+int main( int argc, char ** argv )
+{
+ a = new KApplication ( argc, argv, "KTabCtlTest" );
+
+ a->setFont(default_font);
+
+ TopLevel *toplevel = new TopLevel(0, "_ktabctl_test");
+
+ toplevel->show();
+ a->setMainWidget(toplevel);
+ a->exec();
+}
+
+#include "ktabctltest.moc"
+
diff --git a/kdeui/tests/ktabctltest.h b/kdeui/tests/ktabctltest.h
new file mode 100644
index 000000000..c010c993f
--- /dev/null
+++ b/kdeui/tests/ktabctltest.h
@@ -0,0 +1,30 @@
+/*
+ * $Id$
+ */
+
+#ifndef _KTABCTLTEST_H
+#define _KTABCTLTEST_H
+
+#include <qwidget.h>
+class KTabCtl;
+class QPushButton;
+class QMultiLineEdit;
+
+class TopLevel : public QWidget
+{
+ Q_OBJECT
+public:
+
+ TopLevel( QWidget *parent=0, const char *name=0 );
+protected:
+ void resizeEvent(QResizeEvent *);
+ KTabCtl *test;
+ QPushButton *ok, *cancel;
+ QMultiLineEdit *e;
+ QWidget *pages[3];
+public slots:
+ void okPressed();
+ void tabChanged(int);
+};
+
+#endif
diff --git a/kdeui/tests/ktabwidgettest.cpp b/kdeui/tests/ktabwidgettest.cpp
new file mode 100644
index 000000000..82db9109c
--- /dev/null
+++ b/kdeui/tests/ktabwidgettest.cpp
@@ -0,0 +1,366 @@
+#include <qcheckbox.h>
+#include <qlayout.h>
+#include <qdragobject.h>
+
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <kinputdialog.h>
+#include <kdebug.h>
+
+#include "ktabwidgettest.h"
+
+Test::Test( QWidget* parent, const char *name )
+ :QVBox( parent, name ), mChange(0), mLeftWidget(0), mRightWidget(0),
+ mLeftPopup( false ), mRightPopup( false ), mTabbarContextPopup( false ), mContextPopup( false )
+
+{
+ resize( 600,300 );
+
+ mWidget = new KTabWidget( this );
+ mWidget->addTab( new QLabel( "Testlabel 1", mWidget ), "One" );
+ mWidget->addTab( new QLabel( "Testlabel 2", mWidget ), "Two" );
+ mWidget->addTab( new QWidget( mWidget), SmallIcon( "konsole" ), "Three" );
+ mWidget->addTab( new QWidget( mWidget), "Four" );
+ mWidget->setTabColor( mWidget->page(0), Qt::red );
+ mWidget->setTabColor( mWidget->page(1), Qt::blue );
+
+ connect( mWidget, SIGNAL( currentChanged( QWidget * ) ), SLOT( currentChanged( QWidget * ) ) );
+ connect( mWidget, SIGNAL( contextMenu( QWidget *, const QPoint & )), SLOT(contextMenu( QWidget *, const QPoint & )));
+ connect( mWidget, SIGNAL( contextMenu( const QPoint & )), SLOT(tabbarContextMenu( const QPoint & )));
+ connect( mWidget, SIGNAL( mouseDoubleClick( QWidget * )), SLOT(mouseDoubleClick( QWidget * )));
+ connect( mWidget, SIGNAL( mouseMiddleClick() ), SLOT(addTab() ));
+ connect( mWidget, SIGNAL( mouseMiddleClick( QWidget * )), SLOT(mouseMiddleClick( QWidget * )));
+ connect( mWidget, SIGNAL( closeRequest( QWidget * )), SLOT(mouseMiddleClick( QWidget * )));
+ connect( mWidget, SIGNAL( testCanDecode(const QDragMoveEvent *, bool & )), SLOT(testCanDecode(const QDragMoveEvent *, bool & )));
+ connect( mWidget, SIGNAL( receivedDropEvent( QDropEvent * )), SLOT(receivedDropEvent( QDropEvent * )));
+ connect( mWidget, SIGNAL( receivedDropEvent( QWidget *, QDropEvent * )), SLOT(receivedDropEvent( QWidget *, QDropEvent * )));
+ connect( mWidget, SIGNAL( initiateDrag( QWidget * )), SLOT(initiateDrag( QWidget * )));
+ connect( mWidget, SIGNAL( movedTab( int, int )), SLOT(movedTab( int, int )));
+ mWidget->setTabReorderingEnabled( true );
+
+ QWidget * grid = new QWidget(this);
+ QGridLayout * gridlayout = new QGridLayout( grid, 5, 2 );
+
+ QPushButton * addTab = new QPushButton( "Add Tab", grid );
+ gridlayout->addWidget( addTab, 0, 0 );
+ connect( addTab, SIGNAL( clicked() ), SLOT( addTab() ) );
+
+ QPushButton * removeTab = new QPushButton( "Remove Current Tab", grid );
+ gridlayout->addWidget( removeTab, 0, 1 );
+ connect( removeTab, SIGNAL( clicked() ), SLOT( removeCurrentTab() ) );
+
+ mLeftButton = new QCheckBox( "Show left button", grid );
+ gridlayout->addWidget( mLeftButton, 1, 0 );
+ connect( mLeftButton, SIGNAL( toggled(bool) ), SLOT( toggleLeftButton(bool) ) );
+ mLeftButton->setChecked(true);
+
+ QCheckBox * leftPopup = new QCheckBox( "Enable left popup", grid );
+ gridlayout->addWidget( leftPopup, 2, 0 );
+ connect( leftPopup, SIGNAL( toggled(bool) ), SLOT( toggleLeftPopup(bool) ) );
+ leftPopup->setChecked(true);
+
+ mRightButton = new QCheckBox( "Show right button", grid );
+ gridlayout->addWidget( mRightButton, 1, 1 );
+ connect( mRightButton, SIGNAL( toggled(bool) ), SLOT( toggleRightButton(bool) ) );
+ mRightButton->setChecked(true);
+
+ QCheckBox * rightPopup = new QCheckBox( "Enable right popup", grid );
+ gridlayout->addWidget( rightPopup, 2, 1 );
+ connect( rightPopup, SIGNAL( toggled(bool) ), SLOT( toggleRightPopup(bool) ) );
+ rightPopup->setChecked(true);
+
+ mTabsBottom = new QCheckBox( "Show tabs at bottom", grid );
+ gridlayout->addWidget( mTabsBottom, 3, 0 );
+ connect( mTabsBottom, SIGNAL( toggled(bool) ), SLOT( toggleTabPosition(bool) ) );
+
+ QCheckBox * tabshape = new QCheckBox( "Triangular tab shape", grid );
+ gridlayout->addWidget( tabshape, 3, 1 );
+ connect( tabshape, SIGNAL( toggled(bool) ), SLOT( toggleTabShape(bool) ) );
+
+ QCheckBox *tabClose = new QCheckBox( "Close button on icon hover", grid );
+ gridlayout->addWidget( tabClose, 4, 0 );
+ connect( tabClose, SIGNAL( toggled(bool) ), SLOT( toggleCloseButtons(bool) ) );
+ tabClose->setChecked(true);
+
+ QCheckBox * showlabels = new QCheckBox( "Show labels", grid );
+ gridlayout->addWidget( showlabels, 4, 1 );
+ connect( showlabels, SIGNAL( toggled(bool) ), this, SLOT( toggleLabels(bool) ) );
+}
+
+void Test::currentChanged(QWidget* w)
+{
+ mWidget->setTabColor( w, Qt::black );
+}
+
+void Test::addTab()
+{
+ mWidget->addTab( new QWidget( mWidget ), SmallIcon( "konsole" ), QString("Tab %1").arg( mWidget->count()+1 ) );
+}
+
+void Test::testCanDecode(const QDragMoveEvent *e, bool &accept /* result */)
+{
+ if ( QTextDrag::canDecode(e) ) // don't accept=false if it cannot be decoded!
+ accept = true;
+}
+
+void Test::receivedDropEvent( QDropEvent *e )
+{
+ QString dropText;
+ if (QTextDrag::decode(e, dropText)) {
+ mWidget->addTab( new QWidget( mWidget), dropText );
+ }
+}
+
+void Test::receivedDropEvent( QWidget *w, QDropEvent *e )
+{
+ QString dropText;
+ if (QTextDrag::decode(e, dropText)) {
+ mWidget->changeTab( w, dropText );
+ }
+}
+
+void Test::initiateDrag( QWidget *w )
+{
+ QDragObject *d = new QTextDrag( mWidget->label( mWidget->indexOf( w ) ), this );
+ d->dragCopy(); // do NOT delete d.
+}
+
+void Test::removeCurrentTab()
+{
+ if ( mWidget->count()==1 ) return;
+
+ mWidget->removePage( mWidget->currentPage() );
+}
+
+void Test::toggleLeftButton(bool state)
+{
+ if (state) {
+ if (!mLeftWidget) {
+ mLeftWidget = new QToolButton( mWidget );
+ connect( mLeftWidget, SIGNAL( clicked() ), SLOT( addTab() ) );
+ mLeftWidget->setIconSet( SmallIcon( "tab_new" ) );
+ mLeftWidget->setTextLabel("New");
+ mLeftWidget->setTextPosition(QToolButton::Right);
+ mLeftWidget->adjustSize();
+ //mLeftWidget->setGeometry( 0, 0, h, h );
+ mLeftWidget->setPopup(mLeftPopup);
+ mWidget->setCornerWidget( mLeftWidget, TopLeft );
+ }
+ mLeftWidget->show();
+ }
+ else
+ mLeftWidget->hide();
+}
+
+void Test::toggleLeftPopup(bool state)
+{
+ if (state) {
+ if (!mLeftPopup) {
+ mLeftPopup = new QPopupMenu(this);
+ mLeftPopup->insertItem(SmallIcon( "tab_new" ), "Empty Tab", 0);
+ mLeftPopup->insertItem(SmallIcon( "tab_new" ), "Empty Tab After First", 3);
+ mLeftPopup->insertSeparator();
+ mLeftPopup->insertItem(SmallIcon( "tab_new" ), "Button Tab", 1);
+ mLeftPopup->insertItem(SmallIcon( "tab_new" ), "Label Tab", 2);
+ connect(mLeftPopup, SIGNAL(activated(int)), SLOT(leftPopupActivated(int)));
+ }
+ mLeftWidget->setPopup(mLeftPopup);
+ }
+ else
+ mLeftWidget->setPopup(0);
+}
+
+void Test::leftPopupActivated(int item)
+{
+ switch (item) {
+ case 0: mWidget->addTab( new QWidget( mWidget), QString("Tab %1").arg( mWidget->count()+1 ) );
+ break;
+ case 1: mWidget->addTab( new QPushButton( "Testbutton", mWidget ), QString("Tab %1").arg( mWidget->count()+1 ) );
+ break;
+ case 2: mWidget->addTab( new QLabel( "Testlabel", mWidget ), QString("Tab %1").arg( mWidget->count()+1 ) );
+ break;
+ case 3: mWidget->insertTab( new QWidget( mWidget), QString("Tab %1").arg( mWidget->count()+1 ), 1 );
+ }
+}
+
+void Test::toggleRightButton(bool state)
+{
+if (state) {
+ if ( !mRightWidget) {
+ mRightWidget = new QToolButton( mWidget );
+ QObject::connect( mRightWidget, SIGNAL( clicked() ), SLOT( removeCurrentTab() ) );
+ mRightWidget->setIconSet( SmallIcon( "tab_remove" ) );
+ mRightWidget->setTextLabel("Close");
+ mRightWidget->setTextPosition(QToolButton::Right);
+ mRightWidget->adjustSize();
+ //mRightButton->setGeometry( 0, 0, h, h );
+ mRightWidget->setPopup(mRightPopup);
+ mWidget->setCornerWidget( mRightWidget, TopRight );
+ }
+ mRightWidget->show();
+ }
+ else
+ mRightWidget->hide();
+}
+
+void Test::toggleRightPopup(bool state)
+{
+ if (state) {
+ if (!mRightPopup) {
+ mRightPopup = new QPopupMenu(this);
+ mRightPopup->insertItem(SmallIcon( "tab_remove" ), "Current Tab", 1);
+ mRightPopup->insertSeparator();
+ mRightPopup->insertItem(SmallIcon( "tab_remove" ), "Most Left Tab", 0);
+ mRightPopup->insertItem(SmallIcon( "tab_remove" ), "Most Right Tab", 2);
+ connect(mRightPopup, SIGNAL(activated(int)), SLOT(rightPopupActivated(int)));
+ }
+ mRightWidget->setPopup(mRightPopup);
+ }
+ else
+ mRightWidget->setPopup(0);
+}
+
+void Test::rightPopupActivated(int item)
+{
+ switch (item) {
+ case 0: if ( mWidget->count() >1) {
+ mWidget->removePage( mWidget->page(0) );
+ }
+ break;
+ case 1: removeCurrentTab();
+ break;
+ case 2: int count = mWidget->count();
+ if (count>1) {
+ mWidget->removePage( mWidget->page(count-1) );
+ }
+ }
+}
+
+void Test::toggleTabPosition(bool state)
+{
+ mWidget->setTabPosition(state ? QTabWidget::Bottom : QTabWidget::Top);
+}
+
+void Test::toggleTabShape(bool state)
+{
+ mWidget->setTabShape(state ? QTabWidget::Triangular : QTabWidget::Rounded);
+}
+
+void Test::toggleCloseButtons(bool state)
+{
+ mWidget->setHoverCloseButton( state );
+}
+
+void Test::contextMenu(QWidget *w, const QPoint &p)
+{
+ if (mContextPopup)
+ delete mContextPopup;
+
+ mContextPopup = new QPopupMenu(this);
+ mContextPopup->insertItem( "Activate Tab", 4);
+ mContextPopup->insertSeparator();
+ mContextPopup->insertItem(SmallIcon( "konsole" ), "Set This Icon", 0);
+ mContextPopup->insertItem(SmallIcon( "konqueror" ), "Set This Icon", 1);
+ mContextPopup->insertSeparator();
+ mContextPopup->insertItem( mWidget->isTabEnabled(w) ? "Disable Tab" : "Enable Tab", 2);
+ mContextPopup->insertItem( mWidget->tabToolTip(w).isEmpty() ? "Set Tooltip" : "Remove Tooltip", 3);
+ connect(mContextPopup, SIGNAL(activated(int)), SLOT(contextMenuActivated(int)));
+
+ mContextWidget = w;
+ mContextPopup->popup(p);
+}
+
+void Test::contextMenuActivated(int item)
+{
+ switch (item) {
+ case 0: mWidget->changeTab( mContextWidget, SmallIcon( "konsole" ), mWidget->label( mWidget->indexOf( mContextWidget ) ) );
+ break;
+ case 1: mWidget->changeTab( mContextWidget, SmallIcon( "konqueror" ), mWidget->label( mWidget->indexOf( mContextWidget ) ) );
+ break;
+ case 2: mWidget->setTabEnabled( mContextWidget, !(mWidget->isTabEnabled(mContextWidget)) );
+ break;
+ case 3: if ( mWidget->tabToolTip(mContextWidget).isEmpty() )
+ mWidget->setTabToolTip( mContextWidget, "This is a tool tip.");
+ else
+ mWidget->removeTabToolTip( mContextWidget );
+ break;
+ case 4: mWidget->showPage( mContextWidget );
+ }
+ delete mContextPopup;
+ mContextPopup = 0;
+}
+
+void Test::tabbarContextMenu(const QPoint &p)
+{
+ if (mTabbarContextPopup)
+ delete mTabbarContextPopup;
+
+ mTabbarContextPopup = new QPopupMenu(this);
+ mTabbarContextPopup->insertItem(SmallIcon( "tab_new" ), mLeftWidget->isVisible() ? "Hide \"Add\" Button" : "Show \"Add\" Button", 0);
+ mTabbarContextPopup->insertItem(SmallIcon( "tab_remove" ), mRightWidget->isVisible() ? "Hide \"Remove\" Button" : "Show \"Remove\" Button", 1);
+ mTabbarContextPopup->insertSeparator();
+ mTabbarContextPopup->insertItem(mWidget->tabPosition()==QTabWidget::Top ? "Put Tabbar to Bottom" : "Put Tabbar to Top", 2);
+ connect(mTabbarContextPopup, SIGNAL(activated(int)), SLOT(tabbarContextMenuActivated(int)));
+
+ mTabbarContextPopup->popup(p);
+}
+
+void Test::tabbarContextMenuActivated(int item)
+{
+ switch (item) {
+ case 0: mLeftButton->toggle();
+ break;
+ case 1: mRightButton->toggle();
+ break;
+ case 2: mTabsBottom->toggle();
+ }
+ delete mTabbarContextPopup;
+ mTabbarContextPopup = 0;
+}
+
+void Test::mouseDoubleClick(QWidget *w)
+{
+ bool ok;
+ QString text = KInputDialog::getText(
+ "Rename Tab", "Enter new name:",
+ mWidget->label( mWidget->indexOf( w ) ), &ok, this );
+ if ( ok && !text.isEmpty() ) {
+ mWidget->changeTab( w, text );
+ mWidget->setTabColor( w, Qt::green );
+ }
+}
+
+void Test::mouseMiddleClick(QWidget *w)
+{
+ if ( mWidget->count()==1 ) return;
+
+ mWidget->removePage( w );
+}
+
+void Test::movedTab(int from, int to)
+{
+ kdDebug() << "Moved tab from index " << from << " to " << to << endl;
+}
+
+void Test::toggleLabels(bool state)
+{
+ mLeftWidget->setUsesTextLabel(state);
+ mLeftWidget->adjustSize();
+ mRightWidget->setUsesTextLabel(state);
+ mRightWidget->adjustSize();
+ mWidget->hide(); // trigger update
+ mWidget->show();
+}
+
+int main(int argc, char** argv )
+{
+ KCmdLineArgs::init(argc, argv, "ktabwidgettest", "ktabwidget test app", "1.0");
+ KApplication app(argc, argv);
+ Test *t = new Test();
+
+ app.setMainWidget( t );
+ t->show();
+ app.exec();
+}
+
+#include "ktabwidgettest.moc"
diff --git a/kdeui/tests/ktabwidgettest.h b/kdeui/tests/ktabwidgettest.h
new file mode 100644
index 000000000..cc96a24c6
--- /dev/null
+++ b/kdeui/tests/ktabwidgettest.h
@@ -0,0 +1,69 @@
+#ifndef KTABWIDGETTEST_H
+#define KTABWIDGETTEST_H
+
+#include <kiconloader.h>
+#include <qwidget.h>
+#include <ktabwidget.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qpopupmenu.h>
+#include <stdlib.h>
+#include <qvbox.h>
+#include <time.h>
+#include <qcheckbox.h>
+#include <qtoolbutton.h>
+
+class Test : public QVBox
+{
+ Q_OBJECT
+public:
+ Test( QWidget* parent=0, const char *name =0 );
+
+private slots:
+ void addTab();
+ void removeCurrentTab();
+ void toggleLeftButton(bool);
+ void toggleRightButton(bool);
+ void toggleLeftPopup(bool);
+ void toggleRightPopup(bool);
+ void toggleTabPosition(bool);
+ void toggleTabShape(bool);
+ void toggleCloseButtons(bool);
+ void toggleLabels(bool);
+
+ void currentChanged(QWidget*);
+ void contextMenu(QWidget*, const QPoint&);
+ void tabbarContextMenu(const QPoint&);
+ void testCanDecode(const QDragMoveEvent *, bool & /* result */);
+ void receivedDropEvent( QDropEvent* );
+ void initiateDrag( QWidget * );
+ void receivedDropEvent( QWidget *, QDropEvent * );
+ void mouseDoubleClick(QWidget*);
+ void mouseMiddleClick(QWidget*);
+ void movedTab( int, int );
+
+ void leftPopupActivated(int);
+ void rightPopupActivated(int);
+ void contextMenuActivated(int);
+ void tabbarContextMenuActivated(int);
+
+private:
+ KTabWidget* mWidget;
+ int mChange;
+
+ QCheckBox * mLeftButton;
+ QCheckBox * mRightButton;
+ QCheckBox * mTabsBottom;
+
+ QToolButton* mLeftWidget;
+ QToolButton* mRightWidget;
+
+ QPopupMenu* mLeftPopup;
+ QPopupMenu* mRightPopup;
+ QPopupMenu* mTabbarContextPopup;
+ QPopupMenu* mContextPopup;
+ QWidget* mContextWidget;
+};
+
+
+#endif
diff --git a/kdeui/tests/ktextedittest.cpp b/kdeui/tests/ktextedittest.cpp
new file mode 100644
index 000000000..d37afab30
--- /dev/null
+++ b/kdeui/tests/ktextedittest.cpp
@@ -0,0 +1,43 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <kapplication.h>
+#include <ktextedit.h>
+
+#include <qfile.h>
+
+int main( int argc, char **argv )
+{
+ KApplication app( argc, argv, "ktextedittest" );
+ KTextEdit *edit = new KTextEdit();
+ edit->setReadOnly( true );
+ edit->setCheckSpellingEnabled( true );
+
+ QFile file( "ktextedittest.cpp" );
+ if ( file.open( IO_ReadOnly ) )
+ {
+ edit->setText( file.readAll() );
+ file.close();
+ }
+
+ edit->resize( 600, 600 );
+ edit->show();
+ edit->setReadOnly( false ); // also enables spell checking
+ return app.exec();
+}
diff --git a/kdeui/tests/ktimewidgettest.cpp b/kdeui/tests/ktimewidgettest.cpp
new file mode 100644
index 000000000..f2767b416
--- /dev/null
+++ b/kdeui/tests/ktimewidgettest.cpp
@@ -0,0 +1,14 @@
+#include "ktimewidget.h"
+#include <kapplication.h>
+#include <klocale.h>
+
+int main(int argc, char** argv)
+{
+ KLocale::setMainCatalogue("kdelibs");
+ KApplication app(argc, argv, "KTimeWidgettest");
+ KTimeWidget timeWidget;
+ app.setMainWidget(&timeWidget);
+ timeWidget.show();
+ // timeWidget.setEnabled(false);
+ return app.exec();
+}
diff --git a/kdeui/tests/ktoolbarlabelactiontest.cpp b/kdeui/tests/ktoolbarlabelactiontest.cpp
new file mode 100644
index 000000000..8ff2ccb74
--- /dev/null
+++ b/kdeui/tests/ktoolbarlabelactiontest.cpp
@@ -0,0 +1,97 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2004 Felix Berger <felixberger@beldesign.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qguardedptr.h>
+
+#include <kapplication.h>
+#include <kmainwindow.h>
+#include <klineedit.h>
+#include <klistview.h>
+#include <kstandarddirs.h>
+#include <ktoolbarlabelaction.h>
+#include <ksqueezedtextlabel.h>
+#include <kdebug.h>
+#include <qvbox.h>
+
+#include <assert.h>
+
+class MainWindow : public KMainWindow
+{
+public:
+ MainWindow()
+ {
+ QVBox* main = new QVBox(this);
+ setCentralWidget(main);
+
+ KSqueezedTextLabel* accel = new KSqueezedTextLabel
+ ("&Really long, long, long and boring text goes here", main,
+ "kde toolbar widget");
+ new KSqueezedTextLabel
+ ("Really long, long, long and boring text goes here", main,
+ "kde toolbar widget");
+
+
+ // first constructor
+ KToolBarLabelAction* label1 = new KToolBarLabelAction("&Label 1", 0,
+ 0, 0,
+ actionCollection(),
+ "label1");
+ // second constructor
+ KLineEdit* lineEdit = new KLineEdit(this);
+ new KWidgetAction(lineEdit, "Line Edit", 0, this, 0,
+ actionCollection(), "lineEdit");
+ KToolBarLabelAction* label2 =
+ new KToolBarLabelAction(lineEdit, "L&abel 2", 0, 0, 0,
+ actionCollection(),
+ "label2");
+
+ // set buddy for label1
+ label1->setBuddy(lineEdit);
+ accel->setBuddy(lineEdit);
+
+ // third constructor
+ QLabel* customLabel = new KSqueezedTextLabel
+ ("&Really long, long, long and boring text goes here", this,
+ "kde toolbar widget");
+
+ KToolBarLabelAction* label3 = new KToolBarLabelAction(customLabel, 0, 0, 0,
+ actionCollection(),
+ "label3");
+
+ // set buddy for label3
+ label3->setBuddy(lineEdit);
+
+ // customLabel->setText("&test me again some time soon");
+
+ createGUI("ktoolbarlabelactiontestui.rc");
+ }
+};
+
+int main( int argc, char **argv )
+{
+ KApplication app( argc, argv, "ktoolbarlabelactiontest" );
+
+ KGlobal::instance()->dirs()->addResourceDir("data", ".");
+
+ MainWindow* mw = new MainWindow;
+ app.setMainWidget(mw);
+ mw->show();
+
+ return app.exec();
+}
+
diff --git a/kdeui/tests/ktoolbarlabelactiontestui.rc b/kdeui/tests/ktoolbarlabelactiontestui.rc
new file mode 100644
index 000000000..75d02e54e
--- /dev/null
+++ b/kdeui/tests/ktoolbarlabelactiontestui.rc
@@ -0,0 +1,9 @@
+<!DOCTYPE kpartgui>
+<kpartgui name="ktoolbarlabelactiontest" version="0.1">
+<ToolBar>
+<Action name="label1"/>
+<Action name="label2"/>
+<Action name="lineEdit"/>
+<Action name="label3"/>
+</ToolBar>
+</kpartgui>
diff --git a/kdeui/tests/kunbalancedgrdtest.cpp b/kdeui/tests/kunbalancedgrdtest.cpp
new file mode 100644
index 000000000..ec3ce967b
--- /dev/null
+++ b/kdeui/tests/kunbalancedgrdtest.cpp
@@ -0,0 +1,176 @@
+#include "kunbalancedgrdtest.h"
+#include <kapplication.h>
+#include <kpixmapeffect.h>
+#include <qpainter.h>
+#include <qstring.h>
+#include <qlayout.h>
+
+int cols = 3, rows = 3; // how many
+
+
+KGradientWidget::KGradientWidget(QWidget *parent, const char *name)
+ :QWidget(parent, name)
+{
+ time.start();
+ setMinimumSize(250 * cols, 250 * rows);
+}
+
+void KGradientWidget::paintEvent(QPaintEvent *)
+{
+ int it, ft;
+ QString say;
+
+ QColor ca = Qt::black, cb = Qt::cyan;
+
+ int x = 0, y = 0;
+
+ pix.resize(width()/cols, height()/rows);
+ QPainter p(this);
+ p.setPen(Qt::white);
+
+ // draw once, so that the benchmarking be fair :-)
+ KPixmapEffect::unbalancedGradient(pix,ca, cb,
+ KPixmapEffect::VerticalGradient,
+ xbalance, ybalance);
+
+ // vertical
+ time.start();
+ it = time.elapsed();
+ KPixmapEffect::unbalancedGradient(pix,ca, cb,
+ KPixmapEffect::VerticalGradient,
+ xbalance, ybalance);
+ ft = time.elapsed();
+ say.setNum( ft - it); say = "Vertical";
+ p.drawPixmap(x*width()/cols, y*height()/rows, pix);
+ p.drawText(5 + (x++)*width()/cols, 15+y*height()/rows, say); // augment x
+
+ // horizontal
+ it = time.elapsed();
+ KPixmapEffect::unbalancedGradient(pix,ca, cb,
+ KPixmapEffect::HorizontalGradient,
+ xbalance, ybalance);
+ ft = time.elapsed() ;
+ say.setNum( ft - it); say = "Horizontal";
+ p.drawPixmap(x*width()/cols, y*height()/rows, pix);
+ p.drawText(5+(x++)*width()/cols, 15+y*height()/rows, say);
+
+ // elliptic
+ it = time.elapsed();
+ KPixmapEffect::unbalancedGradient(pix, ca, cb,
+ KPixmapEffect::EllipticGradient,
+ xbalance, ybalance);
+ ft = time.elapsed() ;
+ say.setNum( ft - it); say = "Elliptic";
+ p.drawPixmap(x*width()/cols, y*height()/rows, pix);
+ p.drawText(5+(x++)*width()/cols, 15+y*height()/rows, say);
+
+ y++; // next row
+ x = 0; // reset the columns
+
+ // diagonal
+ it = time.elapsed();
+ KPixmapEffect::unbalancedGradient(pix,ca, cb,
+ KPixmapEffect::DiagonalGradient,
+ xbalance, ybalance);
+ ft = time.elapsed();
+ say.setNum( ft - it); say = "Diagonal";
+ p.drawPixmap(x*width()/cols, y*height()/rows, pix);
+ p.drawText(5+(x++)*width()/cols, 15+y*height()/rows, say);
+
+ // crossdiagonal
+ it = time.elapsed();
+ KPixmapEffect::unbalancedGradient(pix,ca, cb,
+ KPixmapEffect::CrossDiagonalGradient,
+ xbalance, ybalance);
+ ft = time.elapsed();
+ say.setNum( ft - it); say = "CrossDiagonal";
+ p.drawPixmap(width()/cols, y*height()/rows, pix);
+ p.drawText(5+(x++)*width()/cols, 15+y*height()/rows, say);
+
+ y++; // next row
+ x = 0; // reset the columns
+
+ // pyramidal
+ it = time.elapsed();
+ KPixmapEffect::unbalancedGradient(pix, ca, cb,
+ KPixmapEffect::PyramidGradient,
+ xbalance, ybalance);
+ ft = time.elapsed();
+ say.setNum( ft - it); say = "Pyramid";
+ p.drawPixmap(x*width()/cols, y*height()/rows, pix);
+ p.drawText(5+(x++)*width()/cols, 15+y*height()/rows, say);
+
+ // rectangular
+ it = time.elapsed();
+ KPixmapEffect::unbalancedGradient(pix, ca, cb,
+ KPixmapEffect::RectangleGradient,
+ xbalance, ybalance);
+ ft = time.elapsed();
+ say.setNum( ft - it); say = "Rectangle";
+ p.drawPixmap(x*width()/cols, y*height()/rows, pix);
+ p.drawText(5+(x++)*width()/rows, 15+y*height()/rows, say);
+
+ // crosspipe
+ it = time.elapsed();
+ KPixmapEffect::unbalancedGradient(pix, ca, cb,
+ KPixmapEffect::PipeCrossGradient,
+ xbalance, ybalance);
+ ft = time.elapsed();
+ say.setNum( ft - it); say = "PipeCross";
+ p.drawPixmap(x*width()/cols, y*height()/rows, pix);
+ p.drawText(5+(x++)*width()/rows, 15+y*height()/rows, say);
+}
+
+myTopWidget::myTopWidget (QWidget *parent, const char *name)
+ :QWidget(parent, name)
+{
+ QGridLayout *lay = new QGridLayout (this, 2, 3, 0);
+
+ grds = new KGradientWidget(this);
+ lay->addMultiCellWidget(grds, 0, 0 ,0, 2);
+
+ bLabel = new QLabel("Balance: X = 000; Y = 000", this);
+ lay->addWidget(bLabel, 1, 0);
+
+ xSlider = new QSlider ( -200, 200, 1, 100, QSlider::Horizontal, this);
+ lay->addWidget(xSlider, 1, 1);
+
+ ySlider = new QSlider ( -200, 200, 1, 100, QSlider::Horizontal, this);
+ lay->addWidget(ySlider, 1, 2);
+
+ connect(xSlider, SIGNAL(valueChanged(int)), this, SLOT(rebalance()));
+ connect(ySlider, SIGNAL(valueChanged(int)), this, SLOT(rebalance()));
+
+ rebalance();
+
+ itime = otime = 0;
+ time.start();
+}
+
+void myTopWidget::rebalance()
+{
+ otime = time.elapsed();
+
+ QString val; val.sprintf("Balance: X = %3d; Y = %3d",
+ xSlider->value(), ySlider->value());
+
+ bLabel->setText(val);
+ grds->setBalance(xSlider->value(), ySlider->value());
+
+ if ((otime - itime )> 500)
+ {
+ grds->repaint(false);
+ itime = time.elapsed();
+ }
+}
+
+int main(int argc, char **argv)
+{
+ KApplication *app = new KApplication(argc, argv, "KUnbalancedGradientTest");
+ myTopWidget w;
+ app->setMainWidget(&w);
+ w.show();
+ return(app->exec());
+}
+
+#include "kunbalancedgrdtest.moc"
diff --git a/kdeui/tests/kunbalancedgrdtest.h b/kdeui/tests/kunbalancedgrdtest.h
new file mode 100644
index 000000000..6af7e4e92
--- /dev/null
+++ b/kdeui/tests/kunbalancedgrdtest.h
@@ -0,0 +1,49 @@
+//
+// Simple little hack to show off new diagonal gradients.
+//
+// (C) KDE Artistic Daniel M. Duley <mosfet@kde.org>
+//
+
+#ifndef __KGRADIENT_TEST_H
+#define __KGRADIENT_TEST_H
+
+#include <qwidget.h>
+#include <kpixmap.h>
+#include <qslider.h>
+#include <qlabel.h>
+#include <qdatetime.h>
+
+class KGradientWidget : public QWidget
+{
+public:
+ KGradientWidget(QWidget *parent=0, const char *name=0);
+
+ void setBalance(int a, int b) { xbalance = a; ybalance = b; }
+protected:
+ void paintEvent(QPaintEvent *ev);
+private:
+ KPixmap pix;
+ int xbalance, ybalance;
+ QTime time;
+
+};
+
+class myTopWidget: public QWidget
+{
+ Q_OBJECT
+public:
+ myTopWidget(QWidget *parent=0, const char *name=0);
+
+private:
+ QLabel *bLabel;
+ QSlider *xSlider, *ySlider;
+ KGradientWidget *grds;
+
+ QTime time;
+
+ int itime, otime;
+
+private slots:
+ void rebalance();
+};
+#endif
diff --git a/kdeui/tests/kwindowtest.cpp b/kdeui/tests/kwindowtest.cpp
new file mode 100644
index 000000000..ae19dd7e3
--- /dev/null
+++ b/kdeui/tests/kwindowtest.cpp
@@ -0,0 +1,528 @@
+#include <qmessagebox.h>
+#include <qpopupmenu.h>
+#include <qpixmap.h>
+#include <qkeycode.h>
+#include <qwidget.h>
+#include <qstring.h>
+#include <qcursor.h>
+
+#include <stdlib.h>
+
+#include <kstatusbar.h>
+#include <kapplication.h>
+#include <kcombobox.h>
+#include <khelpmenu.h>
+#include <kcmdlineargs.h>
+#include <kmenubar.h>
+#include <ktoolbarradiogroup.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+#include <qmultilineedit.h>
+#include "kwindowtest.h"
+
+#include <kglobal.h>
+
+
+//#include <dclock.h>
+
+/*
+ Ok this is a constructor of our top widget. It inherits KMainWindow.
+ In constructor wi will create all of our interface elements:
+ menubar, toolbar(s), statusbar, and main widget. Non of those
+ interface is obligatory, i.e. you don't have to use menubar,
+ toolbars or statusbar if you don't want to. Theoreticly, you
+ don't need even main widget (but in that case, you'll get blank
+ KMainWindow).
+ */
+
+static int itemId = 0;
+
+testWindow::testWindow (QWidget *parent, const char *name)
+ : KMainWindow (parent,name)
+{
+ ena=false;
+ setCaption("test window");
+setAutoSaveSettings();
+ /******************************/
+ /* First, we setup setup Menus */
+ /******************************/
+ menuBar = new KMenuBar (this);
+
+ // First popup...
+ fileMenu = new QPopupMenu;
+ // We insert this popup in menubar with caption "File".
+ // Prefix "&" means that "F" will be underlined
+ menuBar->insertItem ("&File", fileMenu);
+ // We insert item "Exit" with accelerator ALT-Q, and connect
+ // it to application's exit-slot.
+ fileMenu->insertItem ("&Exit", KApplication::kApplication(),
+ SLOT( quit() ), ALT + Key_Q );
+
+ // Another popup...
+ toolBarMenu = new QPopupMenu;
+ menuBar->insertItem ("&Toolbars", toolBarMenu);
+ toolBarMenu->insertItem ("(Un)Hide tollbar 1", this, SLOT(slotHide1()));
+ toolBarMenu->insertItem ("(Un)Hide tollbar 2", this, SLOT(slotHide2()));
+
+ itemsMenu = new QPopupMenu;
+ menuBar->insertItem ("&Items", itemsMenu);
+
+ exitB = true; // exit button is shown
+ lineL = true; // Lined is enabled
+ greenF = false; // Frame not inserted
+
+ itemsMenu->insertItem ("delete/insert exit button", this, SLOT(slotExit()));
+ itemsMenu->insertItem ("insert/delete green frame!", this, SLOT(slotFrame()));
+ itemsMenu->insertItem ("enable/disable Lined", this, SLOT(slotLined()));
+ itemsMenu->insertItem ("Toggle fileNew", this, SLOT(slotNew()));
+ itemsMenu->insertItem ("Clear comboBox", this, SLOT(slotClearCombo()));
+ itemsMenu->insertItem ("Insert List in Combo", this, SLOT(slotInsertListInCombo()));
+ itemsMenu->insertItem ("Make item 3 curent", this, SLOT(slotMakeItem3Current()));
+ //itemsMenu->insertItem ("Insert clock!", this, SLOT(slotInsertClock()));
+ itemsMenu->insertItem ("Important!", this, SLOT(slotImportant()));
+
+ menuBar->insertSeparator();
+ helpMenu = new KHelpMenu(this, "KWindowTest was programmed by Sven Radej");
+ menuBar->insertItem( "&Help", helpMenu->menu() );
+
+ /**************************************************/
+ /*Now, we setup statusbar order is not important. */
+ /**************************************************/
+ statusBar = new KStatusBar (this);
+ statusBar->insertItem("Hi there! ", 0);
+ statusBar->insertItem("Look for tooltips to see functions", 1);
+
+ //DigitalClock *clk = new DigitalClock (statusBar);
+ //clk->setFrameStyle(QFrame::NoFrame);
+ //statusBar->insertWidget(clk, 70, 2);
+
+ /***********************/
+ /* And now the toolbar */
+ /***********************/
+
+ // pixmap which we will use
+ QPixmap pix;
+
+ // Create toolbar...
+ tb = toolBar();
+
+ // and set it to full width
+ tb->setFullSize(true);
+
+
+
+ // First four buttons
+ pix = BarIcon("filenew");
+ itemId = tb->insertButton(pix, 0, SIGNAL(clicked()), this, SLOT(slotNew()),
+ true, "Create.. (toggles upper button)", 50);
+ pix = BarIcon("fileopen");
+ tb->insertButton(pix, 1, SIGNAL(clicked()), this, SLOT(slotOpen()),
+ false, "Open");
+ pix = BarIcon("filefloppy");
+ tb->insertButton(pix, 2, SIGNAL(clicked()), this, SLOT(slotSave()),
+ true, "Save (beep or delayed popup)");
+ tb->setDelayedPopup(2, itemsMenu);
+ pix = BarIcon("fileprint");
+ tb->insertButton(pix, 3, SIGNAL(clicked()), this, SLOT(slotPrint()),
+ true, "Print (enables/disables open)");
+
+ // And a combobox
+ // arguments: text (or strList), ID, writable, signal, object, slot, enabled,
+ // tooltiptext, size
+ tb->insertCombo (QString("one"), 4, true, SIGNAL(activated(const QString&)), this,
+ SLOT(slotList(const QString&)), true, "ComboBox", 150);
+
+
+ // Then one line editor
+ // arguments: text, id, signal, object (this), slot, enabled, tooltiptext, size
+ tb->insertLined ("ftp://ftp.kde.org/pub/kde", 5, SIGNAL(returnPressed()), this,
+ SLOT(slotReturn()), true, "Location", 200);
+
+ // Set this Lined to auto size itself. Note that only one item (Lined or Combo)
+ // Can be set to autosize; If you specify more of them only last (according to
+ /// index) will be set to autosize itself. Only Lined or Combo can be
+ // set to autosize. All items after autoSized one must be aligned right.
+ // Auto size is valid only for fullWidth toolbars.
+
+ tb->setItemAutoSized (5);
+
+ // Now add another button and align it right
+ pix = BarIcon("exit");
+ tb->insertButton(pix, 6, SIGNAL(clicked()), KApplication::kApplication(),
+ SLOT( quit() ), true, "Exit");
+ tb->alignItemRight (6);
+
+ // Another toolbar
+ tb1 = new KToolBar(this, QMainWindow::DockTop); // this one is normal and has separators
+
+
+ pix = BarIcon("filenew");
+ tb1->insertButton(pix, 0, true, "Create new file2 (Toggle)");
+ tb1->setToggle(0);
+ tb1->addConnection (0, SIGNAL(toggled(bool)), this, SLOT(slotToggle(bool)));
+
+ pix = BarIcon("fileopen");
+ tb1->insertButton(pix, 1, SIGNAL(clicked()), this, SLOT(slotOpen()),
+ true, "Open (starts progres in sb)");
+
+ tb1->insertSeparator ();
+
+ pix = BarIcon("filefloppy");
+ tb1->insertButton(pix, 2, SIGNAL(clicked()), this, SLOT(slotSave()),
+ true, "Save file2 (autorepeat)");
+ tb1->setAutoRepeat(2);
+
+ pix = BarIcon("fileprint");
+ tb1->insertButton(pix, 3, itemsMenu, true, "Print (pops menu)");
+
+ tb1->insertSeparator ();
+ /**** RADIO BUTTONS */
+ pix = BarIcon("filenew");
+ tb1->insertButton(pix, 4, true, "Radiobutton1");
+ tb1->setToggle(4);
+
+ pix = BarIcon("fileopen");
+ tb1->insertButton(pix, 5, true, "Radiobutton2");
+ tb1->setToggle(5);
+
+ pix = BarIcon("filefloppy");
+ tb1->insertButton(pix, 6, true, "Radiobutton3");
+ tb1->setToggle(6);
+
+ pix = BarIcon("fileprint");
+ tb1->insertButton(pix, 7, true, "Radiobutton4");
+ tb1->setToggle(7);
+
+ //Create
+ rg = new KToolBarRadioGroup (tb1);
+
+ rg->addButton(4);
+ rg->addButton(5);
+ rg->addButton(6);
+ rg->addButton(7);
+
+ connect (tb1, SIGNAL(toggled(int)), this, SLOT(slotToggled(int)));
+
+ // Set caption for floating toolbars
+ tb->setTitle ("Toolbar 1");
+ tb1->setTitle ("Toolbar 2");
+
+ // Set main widget. In this example it is Qt's multiline editor.
+ widget = new QMultiLineEdit (this);
+
+ // Setup is now complete
+
+ // add two toolbars
+ //addToolBar (tb1);
+ //addToolBar (tb);
+
+ connect (tb, SIGNAL(highlighted(int,bool)), this, SLOT(slotMessage(int, bool)));
+ connect (tb1, SIGNAL(highlighted(int, bool)), this, SLOT(slotMessage(int, bool)));
+
+ // Floating is enabled by default, so you don't need this.
+ // tb->enableFloating(true);
+ // tb1->enableFloating(true);
+
+ // Show toolbars
+ tb->show();
+ tb1->show();
+
+ //... and main widget
+ setCentralWidget (widget);
+
+ // This is not strictly related to toolbars, menubars or KMainWindow.
+ // Setup popup for completions
+ completions = new QPopupMenu;
+
+ completions->insertItem("/");
+ completions->insertItem("/usr/");
+ completions->insertItem("/lib/");
+ completions->insertItem("/var/");
+ completions->insertItem("/bin/");
+ completions->insertItem("/kde/");
+ completions->insertItem("/home/");
+ completions->insertItem("/vmlinuz :-)");
+
+ connect (completions, SIGNAL(activated(int)), this, SLOT(slotCompletionsMenu(int)));
+ pr = 0;
+}
+/***********************************/
+/* Now slots for toolbar actions */
+/***********************************/
+void testWindow::slotToggled(int)
+{
+ statusBar->message ("Buton toggled", 1500);
+}
+
+void testWindow::slotInsertClock()
+{
+ //DigitalClock *clock = new DigitalClock(tb1);
+ //clock->setFrameStyle(QFrame::NoFrame);
+ //tb1->insertWidget(8, 70, clock);
+}
+
+void testWindow::slotNew()
+{
+ tb1->toggleButton(0);
+ toolBar()->removeItem( itemId );
+}
+void testWindow::slotOpen()
+{
+ if (pr == 0)
+ pr = new QProgressBar (statusBar);
+// statusBar->message(pr);
+ timer = new QTimer (pr);
+
+ connect (timer, SIGNAL(timeout()), this, SLOT(slotGoGoGoo()));
+ timer->start(100);
+}
+
+void testWindow::slotGoGoGoo()
+{
+ pr->setProgress(pr->progress()+1);
+ if (pr->progress()==100)
+ {
+ timer->stop();
+ statusBar->clear();
+ delete pr;
+ pr = 0;
+ }
+}
+
+void testWindow::slotSave()
+{
+ kapp->beep();
+ statusBar->changeItem("Saving properties...", 0);
+}
+
+void testWindow::slotPrint()
+{
+ statusBar->changeItem("Print file pressed", 0);
+ ena=!ena;
+ tb->setItemEnabled(1,ena );
+}
+void testWindow::slotReturn()
+{
+ QString s = "You entered ";
+ s = s + tb->getLinedText(5);
+ statusBar->changeItem(s, 0);
+
+}
+void testWindow::slotList(const QString &str)
+{
+ QString s = "You chose ";
+ s = s + str;
+ statusBar->changeItem(s, 0);
+}
+
+void testWindow::slotCompletion()
+{
+ // Now do a completion
+ // Call your completing function and set that text in klined
+ // QString s = tb->getLinedText(/* ID */ 4)
+ // QString completed = complete (s);
+ // tb->setLinedText(/* ID */ 4, completed.data())
+
+ // for now this:
+
+ completions->popup(QCursor::pos()); // This popup should understunf keys up and down
+
+ /* This is just an example. KLined automatically sets cursor at end of string
+ when ctrl-d or ctrl-s is pressed. KToolBar will also put cursor at end of text in Lined
+ after inserting text with setLinedText (...).
+ */
+
+}
+
+void testWindow::slotListCompletion()
+{
+ /*
+ Combo is not behaving good and it is ugly. I will see how it behaves in Qt-1.3,
+ and then decide should I make a new combobox.
+ */
+ QString s(tb->getComboItem(4)); // get text in combo
+ s+= "(completing)";
+ //tb->getCombo(4)->changeItem(s.data()); // setTextIncombo
+
+}
+
+void testWindow::slotCompletionsMenu(int id)
+{
+ // Now set text in lined
+ QString s =completions->text(id);
+ tb->setLinedText(5, s); // Cursor is automatically at the end of string after this
+}
+
+void testWindow::slotHide2 ()
+{
+ tb1->show();
+}
+
+void testWindow::slotHide1 ()
+{
+ tb->show();
+}
+
+testWindow::~testWindow ()
+{
+ /********************************************************/
+ /* */
+ /* THIS IS NOT ANY MORE IMPORTANT BUT ALLOWED!!! */
+ /* */
+ /********************************************************/
+
+ delete tb1->getWidget(8);
+ //debug ("kwindowtest: deleted clock");
+
+ delete tb;
+ delete tb1;
+ delete menuBar;
+
+ qDebug ("kwindowtest finished");
+}
+
+void testWindow::beFixed()
+{
+ widget->setFixedSize (400, 200);
+}
+
+void testWindow::beYFixed()
+{
+ widget->setMinimumSize(400, 200);
+ widget->setMaximumSize(9999, 200);
+}
+
+void testWindow::slotImportant ()
+{
+ statusBar->message("This important message will go away in 15 seconds", 15000);
+}
+
+void testWindow::slotExit ()
+{
+ if (exitB == true)
+ {
+ tb->removeItem(6);
+ exitB = false;
+ }
+ else
+ {
+ QPixmap pix;
+ pix = BarIcon("exit");
+ tb->insertButton(pix, 6, SIGNAL(clicked()), KApplication::kApplication(),
+ SLOT( quit() ), true, "Exit");
+ tb->alignItemRight (6);
+ exitB = true;
+ }
+}
+
+void testWindow::slotLined()
+{
+ lineL = !lineL;
+ tb->setItemEnabled(5, lineL); // enable/disable lined
+}
+
+void testWindow::slotToggle (bool on)
+{
+ if (on == true)
+ statusBar->changeItem("Toggle is on", 0);
+ else
+ statusBar->changeItem("Toggle is off", 0);
+}
+
+void testWindow::slotFrame()
+{
+#if 0
+ if (greenF == false)
+ {
+ tb1->insertFrame(10, 100);
+ tb1->alignItemRight (10); // this is pointless 'cause tb1 is not fullwidth
+
+ QFrame *myFrame = tb1->getFrame(10); // get frame pointer
+
+ if (myFrame == 0)
+ {
+ warning ("bad frame ID");
+ return;
+ }
+
+ //paint it green
+ // Or do whatever you want with it, just don't change its height (height = hardcoded = 24)
+ // And don't move it
+ // If you want to have something right from your toolbar you can reduce its
+ // max_width with setMaxWidth()
+ myFrame->setBackgroundColor (QColor("green"));
+
+ greenF = true;
+ }
+ else
+ {
+ tb1->removeItem (10);
+ greenF = false;
+ }
+#endif
+}
+
+void testWindow::slotMessage(int, bool boo)
+{
+ if (boo)
+ statusBar->message("This button does this and that", 1500);
+ else
+ statusBar->clear();
+}
+// Now few Combo slots, for Torben
+
+void testWindow::slotClearCombo()
+{
+ tb->getCombo(4)->clear();
+}
+
+void testWindow::slotInsertListInCombo()
+{
+ QStringList list;
+ list.append("ListOne");
+ list.append("ListTwo");
+ list.append("ListThree");
+ list.append("ListFour");
+ list.append("ListFive");
+ list.append("ListSix");
+ list.append("ListSeven");
+ list.append("ListEight");
+ list.append("ListNine");
+ list.append("ListTen");
+ list.append("ListEleven");
+ list.append("ListAndSoOn");
+ tb->getCombo(4)->insertStringList (list,0);
+}
+
+void testWindow::slotMakeItem3Current()
+{
+ tb->getCombo(4)->setCurrentItem(3);
+}
+
+int main( int argc, char *argv[] )
+{
+ int i;
+ KCmdLineArgs::init(argc, argv, "KWindowTest", "description", "version");
+
+ KApplication *myApp = new KApplication();
+ testWindow *test = new testWindow;
+
+ myApp->setMainWidget(test);
+
+ i = QMessageBox::information(0, "Select", "Select type of mainwidget",
+ "Fixed", "Y-fixed", "Resizable");
+ if (i == 0)
+ test->beFixed();
+ else if (i == 1)
+ test->beYFixed();
+
+ test->show();
+ test->resize(400, 500);
+ int ret = myApp->exec();
+
+ //delete test;
+ return ret;
+}
+
+#include "kwindowtest.moc"
+
diff --git a/kdeui/tests/kwindowtest.h b/kdeui/tests/kwindowtest.h
new file mode 100644
index 000000000..c041d7723
--- /dev/null
+++ b/kdeui/tests/kwindowtest.h
@@ -0,0 +1,71 @@
+#ifndef testwindow_h
+#define testwindow_h
+
+#include <qpopupmenu.h>
+#include <qtimer.h>
+#include <qprogressbar.h>
+#include <kmenubar.h>
+#include <kstatusbar.h>
+#include <ktoolbar.h>
+#include <kmainwindow.h>
+
+class QMultiLineEdit;
+class KToolBarRadioGroup;
+class KHelpMenu;
+
+class testWindow : public KMainWindow
+{
+ Q_OBJECT
+
+public:
+ testWindow (QWidget *parent=0, const char *name=0);
+ ~testWindow ();
+
+public slots:
+ void beFixed();
+ void beYFixed();
+
+ void slotNew();
+ void slotPrint();
+ void slotReturn();
+ void slotSave();
+ void slotList(const QString &str);
+ void slotOpen();
+ void slotCompletion();
+ void slotCompletionsMenu(int id);
+ void slotHide2 ();
+ void slotInsertClock();
+ void slotHide1 ();
+ void slotLined ();
+ void slotImportant ();
+ void slotExit();
+ void slotFrame();
+ void slotListCompletion();
+ void slotMessage(int, bool);
+ void slotToggle(bool);
+ void slotClearCombo();
+ void slotGoGoGoo();
+ void slotInsertListInCombo ();
+ void slotMakeItem3Current ();
+ void slotToggled(int);
+protected:
+ KMenuBar *menuBar;
+ QPopupMenu *fileMenu;
+ QPopupMenu *itemsMenu;
+ QPopupMenu *completions;
+ QPopupMenu *toolBarMenu;
+ KStatusBar *statusBar;
+ KHelpMenu *helpMenu;
+ KToolBar *tb;
+ KToolBar *tb1;
+ bool lineL;
+ bool exitB;
+ bool greenF;
+ bool ena;
+ QMultiLineEdit *widget;
+ QTimer *timer;
+ QProgressBar *pr;
+ KToolBarRadioGroup *rg;
+};
+#endif
+
diff --git a/kdeui/tests/kwizardtest.cpp b/kdeui/tests/kwizardtest.cpp
new file mode 100644
index 000000000..2d5f7e288
--- /dev/null
+++ b/kdeui/tests/kwizardtest.cpp
@@ -0,0 +1,54 @@
+/*
+ * kwizardtest - a test program for the KWizard dialog
+ * Copyright (C) 1998 Thomas Tanghus (tanghus@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.
+ *
+ */
+
+#include <qlabel.h>
+#include <qlayout.h>
+#include <kapplication.h>
+#include <kwizard.h>
+
+int main(int argc, char **argv)
+{
+ KApplication a(argc,argv,"kwizardtest");
+ KWizard *wiz = new KWizard(0, "kwizardtest", false);
+ QObject::connect((QObject*) wiz->cancelButton(), SIGNAL(clicked()),
+ &a, SLOT(quit()));
+ QObject::connect((QObject*) wiz->finishButton(), SIGNAL(clicked()),
+ &a, SLOT(quit()));
+ for(int i = 1; i < 11; i++)
+ {
+ QWidget *p = new QWidget;
+ QString msg = QString("This is page %1 out of 10").arg(i);
+ QLabel *label = new QLabel(msg, p);
+ QHBoxLayout *layout = new QHBoxLayout(p, 5);
+ label->setAlignment(Qt::AlignCenter);
+ label->setFixedSize(300, 200);
+ layout->addWidget(label);
+ QString title = QString("%1. page").arg(i);
+ wiz->addPage(p, title);
+ wiz->setFinishEnabled(p, (i==10));
+ }
+
+ a.setMainWidget(wiz);
+ wiz->show();
+ return a.exec();
+}
+
+
+
diff --git a/kdeui/tests/kwordwraptest.cpp b/kdeui/tests/kwordwraptest.cpp
new file mode 100644
index 000000000..60a35b394
--- /dev/null
+++ b/kdeui/tests/kwordwraptest.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2003 David Faure <faure@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation;
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <qwidget.h>
+#include "kwordwrap.h"
+
+int main(int argc, char *argv[])
+{
+ KApplication app(argc, argv, "KWordWrapTest");
+
+ QFont font( "helvetica", 12 ); // let's hope we all have the same...
+ QFontMetrics fm( font );
+ QRect r( 0, 0, 100, -1 );
+ QString str = "test wadabada [/foo/bar/waba]";
+ KWordWrap* ww = KWordWrap::formatText( fm, r, 0, str );
+ kdDebug() << str << " => " << ww->truncatedString() << endl;
+ delete ww;
+
+ str = "</p></p></p></p>";
+ for ( ; r.width() > 0 ; r.setWidth( r.width()-10 ) )
+ {
+ ww = KWordWrap::formatText( fm, r, 0, str );
+ kdDebug() << str << " => " << ww->truncatedString() << endl;
+ delete ww;
+ }
+}
diff --git a/kdeui/tests/kxmlguitest.cpp b/kdeui/tests/kxmlguitest.cpp
new file mode 100644
index 000000000..949eb03c4
--- /dev/null
+++ b/kdeui/tests/kxmlguitest.cpp
@@ -0,0 +1,64 @@
+#include "kxmlguitest.h"
+#include <kapplication.h>
+#include <kmainwindow.h>
+#include <kxmlguifactory.h>
+#include <kxmlguiclient.h>
+#include <kxmlguibuilder.h>
+#include <kaction.h>
+#include <kdebug.h>
+#include <kstdaction.h>
+#include <kstandarddirs.h>
+#include <qlineedit.h>
+#include <qdir.h>
+
+void Client::slotSec()
+{
+ kdDebug() << "Client::slotSec()" << endl;
+}
+
+int main( int argc, char **argv )
+{
+ KApplication app( argc, argv, "kxmlguitest" );
+
+ // KXMLGUIClient looks in the "data" resource for the .rc files
+ // Let's add $PWD (ideally $srcdir instead...) to it
+ KGlobal::dirs()->addResourceDir( "data", QDir::currentDirPath() );
+
+ KMainWindow *mainwindow = new KMainWindow;
+
+ QLineEdit* line = new QLineEdit( mainwindow );
+ mainwindow->setCentralWidget( line );
+
+ mainwindow->show();
+
+ KXMLGUIBuilder *builder = new KXMLGUIBuilder( mainwindow );
+
+ KXMLGUIFactory *factory = new KXMLGUIFactory( builder );
+
+ Client *shell = new Client;
+ shell->setInstance( new KInstance( "konqueror" ) );
+ shell->instance()->dirs()->addResourceDir( "data", QDir::currentDirPath() );
+
+ (void)new KAction( "Split", "view_left_right", 0, 0, 0, shell->actionCollection(), "splitviewh" );
+
+ shell->setXMLFile( "./kxmlguitest_shell.rc" );
+
+ factory->addClient( shell );
+
+ Client *part = new Client;
+
+ (void)new KAction( "decfont", "viewmag-", 0, 0, 0, part->actionCollection(), "decFontSizes" );
+ (void)new KAction( "sec", "unlock", Qt::ALT + Qt::Key_1, part, SLOT( slotSec() ), part->actionCollection(), "security" );
+
+ part->setXMLFile( "./kxmlguitest_part.rc" );
+
+ factory->addClient( part );
+ for ( int i = 0; i < 10; ++i )
+ {
+ factory->removeClient( part );
+ factory->addClient( part );
+ }
+
+ return app.exec();
+}
+#include "kxmlguitest.moc"
diff --git a/kdeui/tests/kxmlguitest.h b/kdeui/tests/kxmlguitest.h
new file mode 100644
index 000000000..de651e8a9
--- /dev/null
+++ b/kdeui/tests/kxmlguitest.h
@@ -0,0 +1,19 @@
+#ifndef KXMLGUITEST_H
+#define KXMLGUITEST_H
+
+#include <kxmlguiclient.h>
+#include <qobject.h>
+
+class Client : public QObject, public KXMLGUIClient
+{
+ Q_OBJECT
+public:
+ Client() {}
+
+ void setXMLFile( const QString &f, bool merge = true ) { KXMLGUIClient::setXMLFile( f, merge ); }
+ void setInstance( KInstance *inst ) { KXMLGUIClient::setInstance( inst ); }
+
+public slots:
+ void slotSec();
+};
+#endif
diff --git a/kdeui/tests/kxmlguitest_part.rc b/kdeui/tests/kxmlguitest_part.rc
new file mode 100644
index 000000000..84f5e4f57
--- /dev/null
+++ b/kdeui/tests/kxmlguitest_part.rc
@@ -0,0 +1,8 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="khtmlpart" version="7">
+<ToolBar name="mainToolBar"><text>Main Toolbar</text>
+ <Action name="decFontSizes" />
+ <Separator />
+ <Action name="security" />
+</ToolBar>
+</kpartgui>
diff --git a/kdeui/tests/kxmlguitest_shell.rc b/kdeui/tests/kxmlguitest_shell.rc
new file mode 100644
index 000000000..f211eb259
--- /dev/null
+++ b/kdeui/tests/kxmlguitest_shell.rc
@@ -0,0 +1,7 @@
+<!DOCTYPE kpartgui ><kpartgui version="31" name="Konqueror" >
+ <ToolBar newline="true" name="mainToolBar" fullWidth="true" >
+ <text>Main Toolbar</text>
+ <Merge/>
+ <Action name="splitviewh" />
+ </ToolBar>
+</kpartgui>
diff --git a/kdeui/tests/qxembedtest.cpp b/kdeui/tests/qxembedtest.cpp
new file mode 100644
index 000000000..513231051
--- /dev/null
+++ b/kdeui/tests/qxembedtest.cpp
@@ -0,0 +1,88 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "qapplication.h"
+#include "qpushbutton.h"
+#include "qlineedit.h"
+#include "qhbox.h"
+#include "qvbox.h"
+#include "qxembed.h"
+
+WId windowWithName(const char *);
+
+
+int
+main(int argc, char**argv)
+{
+ if (argc != 2)
+ {
+ fprintf(stderr,
+ "usage: qxembedtest [qtoptions] windowid\n"
+ " qxembedtest [qtoptions] windowTitle\n");
+ exit(10);
+ }
+
+
+ QApplication a(argc,argv);
+
+ QWidget *main = new QVBox(NULL,"main",Qt::WDestructiveClose);
+ QWidget *top = new QHBox(main);
+ QPushButton *quit = new QPushButton("Quit", top);
+ QObject::connect( quit, SIGNAL(clicked()), main, SLOT(close()) );
+ QLineEdit *edit = new QLineEdit(top);
+ edit->setText( "Just to see focus changes");
+ QXEmbed *embed = new QXEmbed(main);
+ embed->setProtocol(QXEmbed::XPLAIN);
+ a.setMainWidget(main);
+ main->show();
+
+ WId wid = strtol(argv[1], NULL, 0);
+ if (! wid)
+ wid = windowWithName(argv[1]);
+ if (! wid)
+ {
+ fprintf(stderr,"qxembedtest: window not found\n");
+ exit(10);
+ }
+
+ fprintf(stderr,"qxembedtest: embedding wid=0x%08x\n", (unsigned int)wid);
+
+ embed->embed(wid);
+
+ return a.exec();
+}
+
+
+
+
+
+#include <X11/Xlib.h>
+#include <qpaintdevice.h>
+
+// This is lifted from X11 xprop.
+
+Window Window_With_Name(Display *dpy, Window top, const char *name)
+{
+ Window *children, dummy;
+ unsigned int nchildren;
+ Window w=0;
+ char *window_name;
+ if (XFetchName(dpy, top, &window_name) && !strcmp(window_name, name))
+ return(top);
+ if (!XQueryTree(dpy, top, &dummy, &dummy, &children, &nchildren))
+ return(0);
+ for (unsigned int i=0; i<nchildren; i++) {
+ w = Window_With_Name(dpy, children[i], name);
+ if (w)
+ break;
+ }
+ if (children)
+ XFree ((char *)children);
+ return(w);
+}
+
+
+WId windowWithName(const char *name)
+{
+ return Window_With_Name(qt_xdisplay(), qt_xrootwin(), name);
+}
diff --git a/kdeui/tests/testimage.png b/kdeui/tests/testimage.png
new file mode 100644
index 000000000..2f591d8e8
--- /dev/null
+++ b/kdeui/tests/testimage.png
Binary files differ
diff --git a/kdeui/ui_standards.rc b/kdeui/ui_standards.rc
new file mode 100644
index 000000000..8c4f1fe2c
--- /dev/null
+++ b/kdeui/ui_standards.rc
@@ -0,0 +1,211 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="standard_containers" version="11">
+<MenuBar>
+ <Menu name="file"><text>&amp;File</text>
+ <Action name="file_new"/>
+ <MergeLocal name="new_merge"/>
+ <Action name="file_open"/>
+ <Action name="file_open_recent"/>
+ <MergeLocal name="open_merge"/>
+ <Separator/>
+ <Action name="file_save"/>
+ <Action name="file_save_as"/>
+ <Action name="file_save_all"/>
+ <MergeLocal name="save_merge"/>
+ <Action name="file_revert"/>
+ <Action name="file_revert_all"/>
+ <MergeLocal name="revert_merge"/>
+ <Separator/>
+ <Action name="file_print"/>
+ <Action name="file_print_preview"/>
+ <MergeLocal name="print_merge"/>
+ <Action name="file_mail"/>
+ <MergeLocal name="mail_merge"/>
+ <Separator/>
+ <MergeLocal/>
+ <Separator/>
+ <Action name="file_close"/>
+ <Action name="file_close_all"/>
+ <MergeLocal name="close_merge"/>
+ <Separator/>
+ <Action name="file_quit"/>
+ </Menu>
+ <Menu name="game"><text>&amp;Game</text>
+ <Action name="game_new"/>
+ <Action name="game_load"/>
+ <Action name="game_load_recent"/>
+ <Action name="game_restart"/>
+ <MergeLocal name="new_merge"/>
+ <Separator/>
+ <Action name="game_save"/>
+ <Action name="game_save_as"/>
+ <MergeLocal name="save_merge"/>
+ <Separator/>
+ <Action name="game_end"/>
+ <MergeLocal name="end_merge"/>
+ <Separator/>
+ <Action name="game_pause"/>
+ <Action name="game_highscores"/>
+ <Action name="game_print"/>
+ <Action name="game_print_preview"/>
+ <MergeLocal name="misc_merge"/>
+ <Separator/>
+ <MergeLocal/>
+ <Separator/>
+ <Action name="game_quit"/>
+ </Menu>
+ <Menu name="edit"><text>&amp;Edit</text>
+ <Action name="edit_undo"/>
+ <Action name="edit_redo"/>
+ <MergeLocal name="edit_undo_merge"/>
+ <Separator/>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <MergeLocal name="edit_paste_merge"/>
+ <Action name="edit_clear"/>
+ <Separator/>
+ <Action name="edit_select_all"/>
+ <Action name="edit_deselect"/>
+ <MergeLocal name="edit_select_merge"/>
+ <Separator/>
+ <Action name="edit_find"/>
+ <Action name="edit_find_next"/>
+ <Action name="edit_find_last"/>
+ <Action name="edit_replace"/>
+ <MergeLocal name="edit_find_merge"/>
+ <Separator/>
+ <MergeLocal/>
+ </Menu>
+ <Menu name="move"><text context="Menu title">&amp;Move</text>
+ <Action name="move_repeat"/>
+ <Action name="move_undo"/>
+ <Action name="move_redo"/>
+ <MergeLocal name="move_undo_merge"/>
+ <Separator/>
+ <Action name="move_roll"/>
+ <Action name="move_end_turn"/>
+ <MergeLocal name="move_turn_merge"/>
+ <Separator/>
+ <Action name="move_hint"/>
+ <Action name="move_demo"/>
+ <Action name="move_solve"/>
+ <MergeLocal name="move_solve_merge"/>
+ <Separator/>
+ <MergeLocal/>
+ </Menu>
+ <Menu name="view"><text>&amp;View</text>
+ <Action name="view_actual_size"/>
+ <Action name="view_fit_to_page"/>
+ <Action name="view_fit_to_width"/>
+ <Action name="view_fit_to_height"/>
+ <Separator/>
+ <MergeLocal name="view_zoom_merge"/>
+ <Action name="view_zoom_in"/>
+ <Action name="view_zoom_out"/>
+ <Action name="view_zoom"/>
+ <WeakSeparator/>
+ <Action name="view_redisplay"/>
+ <Separator/>
+ <MergeLocal/>
+ </Menu>
+ <Menu name="go_web"><text>&amp;Go</text>
+ <Action name="go_up"/>
+ <Action name="go_back"/>
+ <Action name="go_forward"/>
+ <Action name="go_home"/>
+ <Separator/>
+ <MergeLocal/>
+ </Menu>
+ <Menu name="go_document"><text>&amp;Go</text>
+ <Action name="go_previous"/>
+ <Action name="go_next"/>
+ <Action name="go_goto_page"/>
+ <Action name="go_goto_line"/>
+ <Action name="go_goto"/>
+ <Separator/>
+ <Action name="go_first"/>
+ <Action name="go_last"/>
+ <Separator/>
+ <MergeLocal/>
+ </Menu>
+ <MergeLocal/>
+ <Menu name="bookmarks"><text>&amp;Bookmarks</text>
+ <Action name="bookmark_add"/>
+ <Action name="bookmark_edit"/>
+ <Separator/>
+ <MergeLocal/>
+ </Menu>
+ <Menu name="tools"><text>&amp;Tools</text>
+ <Action name="tools_spelling"/>
+ <MergeLocal/>
+ </Menu>
+ <Menu name="settings"><text>&amp;Settings</text>
+ <MergeLocal/>
+ <Separator/>
+ <Action name="options_show_menubar"/>
+ <Action name="options_show_toolbar"/>
+ <Merge name="StandardToolBarMenuHandler" />
+ <Merge name="KMDIViewActions"/>
+ <MergeLocal name="show_toolbar_merge"/>
+ <Action name="options_show_statusbar"/>
+ <MergeLocal name="show_merge"/>
+ <Separator/>
+ <Action name="fullscreen"/>
+ <MergeLocal name="fullscreen_merge"/>
+ <Separator/>
+ <Action name="options_save_options"/>
+ <Action name="options_choose_game_type"/>
+ <MergeLocal name="save_merge"/>
+ <Separator/>
+ <Action name="options_configure_keybinding"/>
+ <Action name="options_configure_toolbars"/>
+ <Action name="options_configure_notifications"/>
+ <Action name="options_configure_carddecks"/>
+ <Action name="options_configure_highscores"/>
+ <MergeLocal name="configure_merge"/>
+ <Action name="options_configure"/>
+ </Menu>
+ <MergeLocal name="settings_merge"/>
+ <Menu name="help"><text>&amp;Help</text>
+ <Action name="help_contents"/>
+ <Action name="help_whats_this"/>
+ <Separator/>
+ <MergeLocal/>
+ <Action name="help_show_tip"/>
+ <Separator/>
+ <Action name="help_report_bug"/>
+ <Separator/>
+ <Action name="switch_application_language"/>
+ <Separator/>
+ <MergeLocal name="about_merge"/>
+ <Action name="help_about_app"/>
+ <Action name="help_about_kde"/>
+ </Menu>
+</MenuBar>
+<ToolBar name="mainToolBar"><text>Main Toolbar</text>
+ <Action name="file_new"/>
+ <Action name="file_open"/>
+ <Action name="file_save"/>
+ <Action name="file_print"/>
+ <Action name="file_print_preview"/>
+ <Action name="file_mail"/>
+ <Separator/>
+ <Action name="edit_undo"/>
+ <Action name="edit_redo"/>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <Separator/>
+ <Action name="edit_find"/>
+ <Action name="view_zoom"/>
+ <Separator/>
+ <Action name="go_previous"/>
+ <Action name="go_next"/>
+ <Action name="go_home"/>
+ <Separator/>
+ <MergeLocal/>
+ <Action name="help"/>
+</ToolBar>
+<StatusBar/>
+</kpartgui>